aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml16
-rw-r--r--.cirrus.yml21
-rw-r--r--.gitignore5
-rw-r--r--.travis.yml73
-rw-r--r--.tx/config2
-rw-r--r--CONTRIBUTING.md71
-rw-r--r--Makefile.am40
-rw-r--r--README.md2
-rw-r--r--build-aux/m4/ax_boost_base.m43
-rw-r--r--build-aux/m4/ax_boost_chrono.m4118
-rw-r--r--build-aux/m4/ax_cxx_compile_stdcxx.m4455
-rw-r--r--build_msvc/.gitignore14
-rw-r--r--build_msvc/README.md5
-rw-r--r--build_msvc/bitcoin_config.h16
-rw-r--r--build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in1
-rw-r--r--build_msvc/libleveldb/libleveldb.vcxproj14
-rw-r--r--build_msvc/testconsensus/testconsensus.cpp2
-rw-r--r--build_msvc/vcpkg-packages.txt2
-rw-r--r--ci/README.md2
-rwxr-xr-xci/lint/06_script.sh1
-rwxr-xr-xci/test/00_setup_env.sh16
-rw-r--r--ci/test/00_setup_env_arm.sh5
-rw-r--r--ci/test/00_setup_env_i686_centos.sh1
-rw-r--r--ci/test/00_setup_env_mac.sh5
-rw-r--r--ci/test/00_setup_env_mac_host.sh7
-rw-r--r--ci/test/00_setup_env_native_asan.sh5
-rw-r--r--ci/test/00_setup_env_native_fuzz.sh9
-rw-r--r--ci/test/00_setup_env_native_fuzz_with_valgrind.sh18
-rw-r--r--ci/test/00_setup_env_native_nowallet.sh3
-rw-r--r--ci/test/00_setup_env_native_qt5.sh8
-rw-r--r--ci/test/00_setup_env_native_tsan.sh11
-rw-r--r--ci/test/00_setup_env_native_valgrind.sh12
-rw-r--r--ci/test/00_setup_env_s390x.sh3
-rw-r--r--ci/test/00_setup_env_s390x_host.sh14
-rw-r--r--ci/test/00_setup_env_win64.sh3
-rwxr-xr-xci/test/04_install.sh37
-rwxr-xr-xci/test/05_before_script.sh9
-rwxr-xr-xci/test/06_script_a.sh22
-rwxr-xr-xci/test/06_script_b.sh13
-rwxr-xr-xci/test/wrap-qemu.sh2
-rw-r--r--configure.ac316
-rw-r--r--contrib/devtools/README.md2
-rwxr-xr-xcontrib/devtools/circular-dependencies.py2
-rwxr-xr-xcontrib/devtools/copyright_header.py3
-rwxr-xr-xcontrib/devtools/previous_release.sh152
-rwxr-xr-xcontrib/devtools/security-check.py57
-rwxr-xr-xcontrib/devtools/symbol-check.py49
-rwxr-xr-xcontrib/devtools/test-security-check.py37
-rwxr-xr-xcontrib/devtools/test_deterministic_coverage.sh2
-rwxr-xr-xcontrib/filter-lcov.py2
-rwxr-xr-xcontrib/gitian-build.py2
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml37
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml38
-rw-r--r--contrib/gitian-descriptors/gitian-win-signer.yml1
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml45
-rwxr-xr-xcontrib/gitian-descriptors/make_git_archive20
-rw-r--r--contrib/gitian-keys/keys.txt2
-rw-r--r--contrib/guix/README.md4
-rwxr-xr-xcontrib/guix/guix-build.sh115
-rw-r--r--contrib/guix/libexec/build.sh194
-rw-r--r--contrib/guix/manifest.scm125
-rwxr-xr-xcontrib/linearize/linearize-data.py2
-rw-r--r--contrib/macdeploy/README.md140
-rwxr-xr-xcontrib/macdeploy/extract-osx-sdk.sh2
-rwxr-xr-xcontrib/seeds/makeseeds.py5
-rw-r--r--contrib/seeds/nodes_main.txt951
-rwxr-xr-xcontrib/verify-commits/pre-push-hook.sh2
-rw-r--r--contrib/windeploy/win-codesign.cert56
-rw-r--r--depends/Makefile7
-rw-r--r--depends/README.md3
-rw-r--r--depends/config.site.in2
-rw-r--r--depends/hosts/darwin.mk7
-rw-r--r--depends/packages/boost.mk2
-rw-r--r--depends/packages/native_cctools.mk47
-rw-r--r--depends/packages/native_libdmg-hfsplus.mk2
-rw-r--r--depends/packages/packages.mk2
-rw-r--r--depends/packages/qt.mk1
-rw-r--r--depends/packages/rapidcheck.mk21
-rw-r--r--depends/patches/qt/mac-qmake.conf2
-rw-r--r--doc/Doxyfile.in3
-rw-r--r--doc/README.md6
-rw-r--r--doc/REST-interface.md2
-rw-r--r--doc/build-freebsd.md19
-rw-r--r--doc/build-netbsd.md14
-rw-r--r--doc/build-openbsd.md12
-rw-r--r--doc/build-osx.md94
-rw-r--r--doc/build-unix.md2
-rw-r--r--doc/dependencies.md2
-rw-r--r--doc/descriptors.md1
-rw-r--r--doc/developer-notes.md179
-rw-r--r--doc/files.md4
-rw-r--r--doc/fuzzing.md259
-rw-r--r--doc/init.md6
-rw-r--r--doc/productivity.md4
-rw-r--r--doc/rapidcheck.md84
-rw-r--r--doc/reduce-memory.md5
-rw-r--r--doc/reduce-traffic.md16
-rw-r--r--doc/release-notes-15437.md53
-rw-r--r--doc/release-notes-15954.md4
-rw-r--r--doc/release-notes-17056.md4
-rw-r--r--doc/release-notes-17410.md5
-rw-r--r--doc/release-notes-17437.md5
-rw-r--r--doc/release-notes-17578.md13
-rw-r--r--doc/release-notes.md49
-rw-r--r--doc/release-notes/release-notes-0.19.1.md115
-rw-r--r--doc/release-process.md7
-rwxr-xr-xshare/genbuild.sh6
-rw-r--r--share/qt/Info.plist.in2
-rw-r--r--share/setup.nsi.in5
-rw-r--r--src/Makefile.am20
-rw-r--r--src/Makefile.bench.include4
-rw-r--r--src/Makefile.crc32c.include75
-rw-r--r--src/Makefile.leveldb.include44
-rw-r--r--src/Makefile.qt_locale.include35
-rw-r--r--src/Makefile.test.include620
-rw-r--r--src/Makefile.test_fuzz.include24
-rw-r--r--src/Makefile.test_util.include2
-rw-r--r--src/addrman.cpp12
-rw-r--r--src/addrman.h11
-rw-r--r--src/banman.h9
-rw-r--r--src/bench/addrman.cpp140
-rw-r--r--src/bench/bech32.cpp4
-rw-r--r--src/bench/bench.cpp15
-rw-r--r--src/bench/bench.h5
-rw-r--r--src/bench/bench_bitcoin.cpp47
-rw-r--r--src/bench/block_assemble.cpp14
-rw-r--r--src/bench/ccoins_caching.cpp48
-rw-r--r--src/bench/chacha_poly_aead.cpp4
-rw-r--r--src/bench/checkblock.cpp6
-rw-r--r--src/bench/checkqueue.cpp16
-rw-r--r--src/bench/crypto_hash.cpp8
-rw-r--r--src/bench/duplicate_inputs.cpp12
-rw-r--r--src/bench/examples.cpp4
-rw-r--r--src/bench/mempool_eviction.cpp13
-rw-r--r--src/bench/mempool_stress.cpp2
-rw-r--r--src/bench/merkle_root.cpp6
-rw-r--r--src/bench/rpc_blockchain.cpp6
-rw-r--r--src/bench/verify_script.cpp29
-rw-r--r--src/bench/wallet_balance.cpp17
-rw-r--r--src/bitcoin-cli.cpp30
-rw-r--r--src/bitcoin-tx.cpp5
-rw-r--r--src/bitcoin-wallet.cpp4
-rw-r--r--src/bitcoind.cpp8
-rw-r--r--src/blockencodings.h142
-rw-r--r--src/blockfilter.cpp32
-rw-r--r--src/bloom.cpp13
-rw-r--r--src/bloom.h3
-rw-r--r--src/chain.h8
-rw-r--r--src/chainparams.cpp34
-rw-r--r--src/chainparams.h5
-rw-r--r--src/chainparamsseeds.h953
-rw-r--r--src/checkqueue.h2
-rw-r--r--src/coins.cpp55
-rw-r--r--src/coins.h50
-rw-r--r--src/compressor.h12
-rw-r--r--src/consensus/merkle.cpp4
-rw-r--r--src/consensus/validation.h61
-rw-r--r--src/core_read.cpp10
-rw-r--r--src/crc32c/.appveyor.yml37
-rw-r--r--src/crc32c/.clang-format3
-rw-r--r--src/crc32c/.clang_complete8
-rw-r--r--src/crc32c/.gitignore8
-rw-r--r--src/crc32c/.gitmodules0
-rw-r--r--src/crc32c/.travis.yml76
-rw-r--r--src/crc32c/.ycm_extra_conf.py142
-rw-r--r--src/crc32c/AUTHORS9
-rw-r--r--src/crc32c/CMakeLists.txt423
-rw-r--r--src/crc32c/CONTRIBUTING.md23
-rw-r--r--src/crc32c/Crc32cConfig.cmake5
-rw-r--r--src/crc32c/LICENSE28
-rw-r--r--src/crc32c/README.md125
-rw-r--r--src/crc32c/include/crc32c/crc32c.h89
-rw-r--r--src/crc32c/src/crc32c.cc39
-rw-r--r--src/crc32c/src/crc32c_arm64.cc126
-rw-r--r--src/crc32c/src/crc32c_arm64.h27
-rw-r--r--src/crc32c/src/crc32c_arm64_linux_check.h50
-rw-r--r--src/crc32c/src/crc32c_arm64_unittest.cc24
-rw-r--r--src/crc32c/src/crc32c_benchmark.cc106
-rw-r--r--src/crc32c/src/crc32c_capi_unittest.c66
-rw-r--r--src/crc32c/src/crc32c_config.h.in36
-rw-r--r--src/crc32c/src/crc32c_extend_unittests.h112
-rw-r--r--src/crc32c/src/crc32c_internal.h23
-rw-r--r--src/crc32c/src/crc32c_portable.cc351
-rw-r--r--src/crc32c/src/crc32c_portable_unittest.cc20
-rw-r--r--src/crc32c/src/crc32c_prefetch.h46
-rw-r--r--src/crc32c/src/crc32c_prefetch_unittest.cc9
-rw-r--r--src/crc32c/src/crc32c_read_le.h53
-rw-r--r--src/crc32c/src/crc32c_read_le_unittest.cc32
-rw-r--r--src/crc32c/src/crc32c_round_up.h34
-rw-r--r--src/crc32c/src/crc32c_round_up_unittest.cc84
-rw-r--r--src/crc32c/src/crc32c_sse42.cc258
-rw-r--r--src/crc32c/src/crc32c_sse42.h33
-rw-r--r--src/crc32c/src/crc32c_sse42_check.h50
-rw-r--r--src/crc32c/src/crc32c_sse42_unittest.cc24
-rw-r--r--src/crc32c/src/crc32c_test_main.cc22
-rw-r--r--src/crc32c/src/crc32c_unittest.cc129
-rw-r--r--src/crypto/sha256_shani.cpp36
-rw-r--r--src/cuckoocache.h1
-rw-r--r--src/flatfile.h4
-rw-r--r--src/httprpc.cpp4
-rw-r--r--src/httpserver.cpp16
-rw-r--r--src/httpserver.h4
-rw-r--r--src/index/base.cpp7
-rw-r--r--src/index/base.h7
-rw-r--r--src/indirectmap.h4
-rw-r--r--src/init.cpp350
-rw-r--r--src/init.h6
-rw-r--r--src/interfaces/chain.cpp326
-rw-r--r--src/interfaces/chain.h206
-rw-r--r--src/interfaces/handler.cpp2
-rw-r--r--src/interfaces/handler.h2
-rw-r--r--src/interfaces/node.cpp20
-rw-r--r--src/interfaces/node.h6
-rw-r--r--src/interfaces/wallet.cpp115
-rw-r--r--src/interfaces/wallet.h43
-rw-r--r--src/leveldb/.appveyor.yml35
-rw-r--r--src/leveldb/.clang-format18
-rw-r--r--src/leveldb/.gitignore21
-rw-r--r--src/leveldb/.travis.yml81
-rw-r--r--src/leveldb/CMakeLists.txt465
-rw-r--r--src/leveldb/CONTRIBUTING.md4
-rw-r--r--src/leveldb/Makefile424
-rw-r--r--src/leveldb/README.md87
-rw-r--r--src/leveldb/WINDOWS.md39
-rw-r--r--src/leveldb/benchmarks/db_bench.cc (renamed from src/leveldb/db/db_bench.cc)203
-rw-r--r--src/leveldb/benchmarks/db_bench_sqlite3.cc (renamed from src/leveldb/doc/bench/db_bench_sqlite3.cc)184
-rw-r--r--src/leveldb/benchmarks/db_bench_tree_db.cc (renamed from src/leveldb/doc/bench/db_bench_tree_db.cc)130
-rwxr-xr-xsrc/leveldb/build_detect_platform259
-rw-r--r--src/leveldb/cmake/leveldbConfig.cmake1
-rw-r--r--src/leveldb/db/autocompact_test.cc36
-rw-r--r--src/leveldb/db/builder.cc25
-rw-r--r--src/leveldb/db/builder.h8
-rw-r--r--src/leveldb/db/c.cc391
-rw-r--r--src/leveldb/db/c_test.c36
-rw-r--r--src/leveldb/db/corruption_test.cc100
-rw-r--r--src/leveldb/db/db_impl.cc547
-rw-r--r--src/leveldb/db/db_impl.h146
-rw-r--r--src/leveldb/db/db_iter.cc93
-rw-r--r--src/leveldb/db/db_iter.h12
-rw-r--r--src/leveldb/db/db_test.cc722
-rw-r--r--src/leveldb/db/dbformat.cc43
-rw-r--r--src/leveldb/db/dbformat.h80
-rw-r--r--src/leveldb/db/dbformat_test.cc95
-rw-r--r--src/leveldb/db/dumpfile.cc29
-rw-r--r--src/leveldb/db/fault_injection_test.cc132
-rw-r--r--src/leveldb/db/filename.cc37
-rw-r--r--src/leveldb/db/filename.h31
-rw-r--r--src/leveldb/db/filename_test.cc86
-rw-r--r--src/leveldb/db/leveldbutil.cc21
-rw-r--r--src/leveldb/db/log_reader.cc28
-rw-r--r--src/leveldb/db/log_reader.h47
-rw-r--r--src/leveldb/db/log_test.cc291
-rw-r--r--src/leveldb/db/log_writer.cc29
-rw-r--r--src/leveldb/db/log_writer.h14
-rw-r--r--src/leveldb/db/memtable.cc68
-rw-r--r--src/leveldb/db/memtable.h23
-rw-r--r--src/leveldb/db/recovery_test.cc72
-rw-r--r--src/leveldb/db/repair.cc95
-rw-r--r--src/leveldb/db/skiplist.h182
-rw-r--r--src/leveldb/db/skiplist_test.cc65
-rw-r--r--src/leveldb/db/snapshot.h78
-rw-r--r--src/leveldb/db/table_cache.cc47
-rw-r--r--src/leveldb/db/table_cache.h33
-rw-r--r--src/leveldb/db/version_edit.cc55
-rw-r--r--src/leveldb/db/version_edit.h27
-rw-r--r--src/leveldb/db/version_edit_test.cc6
-rw-r--r--src/leveldb/db/version_set.cc517
-rw-r--r--src/leveldb/db/version_set.h123
-rw-r--r--src/leveldb/db/version_set_test.cc243
-rw-r--r--src/leveldb/db/write_batch.cc23
-rw-r--r--src/leveldb/db/write_batch_internal.h9
-rw-r--r--src/leveldb/db/write_batch_test.cc73
-rw-r--r--src/leveldb/doc/benchmark.html6
-rw-r--r--src/leveldb/doc/impl.md14
-rw-r--r--src/leveldb/doc/index.md10
-rw-r--r--src/leveldb/helpers/memenv/memenv.cc203
-rw-r--r--src/leveldb/helpers/memenv/memenv.h4
-rw-r--r--src/leveldb/helpers/memenv/memenv_test.cc60
-rw-r--r--src/leveldb/include/leveldb/c.h320
-rw-r--r--src/leveldb/include/leveldb/cache.h21
-rw-r--r--src/leveldb/include/leveldb/comparator.h11
-rw-r--r--src/leveldb/include/leveldb/db.h58
-rw-r--r--src/leveldb/include/leveldb/dumpfile.h5
-rw-r--r--src/leveldb/include/leveldb/env.h220
-rw-r--r--src/leveldb/include/leveldb/export.h33
-rw-r--r--src/leveldb/include/leveldb/filter_policy.h12
-rw-r--r--src/leveldb/include/leveldb/iterator.h34
-rw-r--r--src/leveldb/include/leveldb/options.h100
-rw-r--r--src/leveldb/include/leveldb/slice.h38
-rw-r--r--src/leveldb/include/leveldb/status.h52
-rw-r--r--src/leveldb/include/leveldb/table.h33
-rw-r--r--src/leveldb/include/leveldb/table_builder.h11
-rw-r--r--src/leveldb/include/leveldb/write_batch.h37
-rw-r--r--src/leveldb/issues/issue178_test.cc12
-rw-r--r--src/leveldb/issues/issue200_test.cc10
-rw-r--r--src/leveldb/issues/issue320_test.cc128
-rw-r--r--src/leveldb/port/README.md (renamed from src/leveldb/port/README)2
-rw-r--r--src/leveldb/port/atomic_pointer.h245
-rw-r--r--src/leveldb/port/port.h8
-rw-r--r--src/leveldb/port/port_config.h.in39
-rw-r--r--src/leveldb/port/port_example.h67
-rw-r--r--src/leveldb/port/port_posix.cc67
-rw-r--r--src/leveldb/port/port_posix.h161
-rw-r--r--src/leveldb/port/port_posix_sse.cc110
-rw-r--r--src/leveldb/port/port_stdcxx.h153
-rw-r--r--src/leveldb/port/port_win.cc158
-rw-r--r--src/leveldb/port/port_win.h184
-rw-r--r--src/leveldb/port/thread_annotations.h78
-rw-r--r--src/leveldb/port/win/stdint.h24
-rw-r--r--src/leveldb/table/block.cc69
-rw-r--r--src/leveldb/table/block.h16
-rw-r--r--src/leveldb/table/block_builder.cc23
-rw-r--r--src/leveldb/table/block_builder.h26
-rw-r--r--src/leveldb/table/filter_block.cc19
-rw-r--r--src/leveldb/table/filter_block.h21
-rw-r--r--src/leveldb/table/filter_block_test.cc38
-rw-r--r--src/leveldb/table/format.cc11
-rw-r--r--src/leveldb/table/format.h42
-rw-r--r--src/leveldb/table/iterator.cc75
-rw-r--r--src/leveldb/table/iterator_wrapper.h58
-rw-r--r--src/leveldb/table/merger.cc52
-rw-r--r--src/leveldb/table/merger.h4
-rw-r--r--src/leveldb/table/table.cc68
-rw-r--r--src/leveldb/table/table_builder.cc61
-rw-r--r--src/leveldb/table/table_test.cc315
-rw-r--r--src/leveldb/table/two_level_iterator.cc91
-rw-r--r--src/leveldb/table/two_level_iterator.h11
-rw-r--r--src/leveldb/util/arena.cc18
-rw-r--r--src/leveldb/util/arena.h25
-rw-r--r--src/leveldb/util/arena_test.cc19
-rw-r--r--src/leveldb/util/bloom.cc27
-rw-r--r--src/leveldb/util/bloom_test.cc56
-rw-r--r--src/leveldb/util/cache.cc123
-rw-r--r--src/leveldb/util/cache_test.cc60
-rw-r--r--src/leveldb/util/coding.cc84
-rw-r--r--src/leveldb/util/coding.h136
-rw-r--r--src/leveldb/util/coding_test.cc42
-rw-r--r--src/leveldb/util/comparator.cc40
-rw-r--r--src/leveldb/util/crc32c.cc634
-rw-r--r--src/leveldb/util/crc32c.h6
-rw-r--r--src/leveldb/util/crc32c_test.cc31
-rw-r--r--src/leveldb/util/env.cc26
-rw-r--r--src/leveldb/util/env_posix.cc1122
-rw-r--r--src/leveldb/util/env_posix_test.cc300
-rw-r--r--src/leveldb/util/env_test.cc235
-rw-r--r--src/leveldb/util/env_win.cc902
-rw-r--r--src/leveldb/util/env_windows.cc849
-rw-r--r--src/leveldb/util/env_windows_test.cc64
-rw-r--r--src/leveldb/util/env_windows_test_helper.h25
-rw-r--r--src/leveldb/util/filter_policy.cc2
-rw-r--r--src/leveldb/util/hash.cc15
-rw-r--r--src/leveldb/util/hash.h4
-rw-r--r--src/leveldb/util/hash_test.cc32
-rw-r--r--src/leveldb/util/histogram.cc207
-rw-r--r--src/leveldb/util/histogram.h20
-rw-r--r--src/leveldb/util/logging.cc52
-rw-r--r--src/leveldb/util/logging.h14
-rw-r--r--src/leveldb/util/logging_test.cc143
-rw-r--r--src/leveldb/util/mutexlock.h12
-rw-r--r--src/leveldb/util/no_destructor.h46
-rw-r--r--src/leveldb/util/no_destructor_test.cc47
-rw-r--r--src/leveldb/util/options.cc18
-rw-r--r--src/leveldb/util/posix_logger.h168
-rw-r--r--src/leveldb/util/random.h9
-rw-r--r--src/leveldb/util/status.cc14
-rw-r--r--src/leveldb/util/status_test.cc40
-rw-r--r--src/leveldb/util/testharness.cc18
-rw-r--r--src/leveldb/util/testharness.h85
-rw-r--r--src/leveldb/util/testutil.cc12
-rw-r--r--src/leveldb/util/testutil.h29
-rw-r--r--src/leveldb/util/windows_logger.h124
-rw-r--r--src/logging.cpp23
-rw-r--r--src/logging.h17
-rw-r--r--src/logging/timer.h4
-rw-r--r--src/memusage.h4
-rw-r--r--src/miner.cpp16
-rw-r--r--src/miner.h5
-rw-r--r--src/net.cpp53
-rw-r--r--src/net.h58
-rw-r--r--src/net_permissions.h6
-rw-r--r--src/net_processing.cpp270
-rw-r--r--src/net_processing.h14
-rw-r--r--src/netaddress.cpp104
-rw-r--r--src/netaddress.h10
-rw-r--r--src/node/coinstats.cpp4
-rw-r--r--src/node/context.cpp3
-rw-r--r--src/node/context.h6
-rw-r--r--src/node/psbt.cpp33
-rw-r--r--src/node/transaction.cpp7
-rw-r--r--src/node/transaction.h10
-rw-r--r--src/outputtype.cpp16
-rw-r--r--src/prevector.h25
-rw-r--r--src/primitives/transaction.cpp9
-rw-r--r--src/protocol.cpp11
-rw-r--r--src/protocol.h4
-rw-r--r--src/psbt.cpp2
-rw-r--r--src/psbt.h6
-rw-r--r--src/pubkey.h5
-rw-r--r--src/qt/addresstablemodel.cpp4
-rw-r--r--src/qt/bantablemodel.cpp2
-rw-r--r--src/qt/bantablemodel.h2
-rw-r--r--src/qt/bitcoin.cpp4
-rw-r--r--src/qt/bitcoin_locale.qrc35
-rw-r--r--src/qt/bitcoingui.cpp12
-rw-r--r--src/qt/bitcoingui.h5
-rw-r--r--src/qt/bitcoinstrings.cpp9
-rw-r--r--src/qt/clientmodel.cpp17
-rw-r--r--src/qt/clientmodel.h4
-rw-r--r--src/qt/coincontroldialog.cpp8
-rw-r--r--src/qt/coincontroltreewidget.h2
-rw-r--r--src/qt/createwalletdialog.cpp5
-rw-r--r--src/qt/createwalletdialog.h1
-rw-r--r--src/qt/csvmodelwriter.h2
-rw-r--r--src/qt/forms/createwalletdialog.ui20
-rw-r--r--src/qt/forms/debugwindow.ui60
-rw-r--r--src/qt/guiutil.cpp6
-rw-r--r--src/qt/guiutil.h4
-rw-r--r--src/qt/locale/bitcoin_af.ts2154
-rw-r--r--src/qt/locale/bitcoin_am.ts434
-rw-r--r--src/qt/locale/bitcoin_ar.ts2943
-rw-r--r--src/qt/locale/bitcoin_be.ts (renamed from src/qt/locale/bitcoin_be_BY.ts)113
-rw-r--r--src/qt/locale/bitcoin_bg.ts2328
-rw-r--r--src/qt/locale/bitcoin_bn.ts186
-rw-r--r--src/qt/locale/bitcoin_bs.ts (renamed from src/qt/locale/bitcoin_he_IL.ts)171
-rw-r--r--src/qt/locale/bitcoin_ca.ts2999
-rw-r--r--src/qt/locale/bitcoin_cs.ts183
-rw-r--r--src/qt/locale/bitcoin_cs_CZ.ts691
-rw-r--r--src/qt/locale/bitcoin_cy.ts113
-rw-r--r--src/qt/locale/bitcoin_da.ts255
-rw-r--r--src/qt/locale/bitcoin_de.ts381
-rw-r--r--src/qt/locale/bitcoin_de_DE.ts929
-rw-r--r--src/qt/locale/bitcoin_el.ts1849
-rw-r--r--src/qt/locale/bitcoin_el_GR.ts2095
-rw-r--r--src/qt/locale/bitcoin_en.ts642
-rw-r--r--src/qt/locale/bitcoin_en_AU.ts187
-rw-r--r--src/qt/locale/bitcoin_en_GB.ts407
-rw-r--r--src/qt/locale/bitcoin_eo.ts133
-rw-r--r--src/qt/locale/bitcoin_es.ts1012
-rw-r--r--src/qt/locale/bitcoin_es_CL.ts145
-rw-r--r--src/qt/locale/bitcoin_es_CO.ts139
-rw-r--r--src/qt/locale/bitcoin_es_DO.ts629
-rw-r--r--src/qt/locale/bitcoin_es_ES.ts3185
-rw-r--r--src/qt/locale/bitcoin_es_MX.ts390
-rw-r--r--src/qt/locale/bitcoin_es_VE.ts239
-rw-r--r--src/qt/locale/bitcoin_et.ts63
-rw-r--r--src/qt/locale/bitcoin_et_EE.ts779
-rw-r--r--src/qt/locale/bitcoin_eu.ts423
-rw-r--r--src/qt/locale/bitcoin_fa.ts169
-rw-r--r--src/qt/locale/bitcoin_fi.ts307
-rw-r--r--src/qt/locale/bitcoin_fil.ts165
-rw-r--r--src/qt/locale/bitcoin_fr.ts385
-rw-r--r--src/qt/locale/bitcoin_fr_FR.ts2314
-rw-r--r--src/qt/locale/bitcoin_gl.ts1349
-rw-r--r--src/qt/locale/bitcoin_he.ts160
-rw-r--r--src/qt/locale/bitcoin_hi.ts31
-rw-r--r--src/qt/locale/bitcoin_hr.ts315
-rw-r--r--src/qt/locale/bitcoin_hu.ts571
-rw-r--r--src/qt/locale/bitcoin_hu_HU.ts2685
-rw-r--r--src/qt/locale/bitcoin_id.ts841
-rw-r--r--src/qt/locale/bitcoin_id_ID.ts2137
-rw-r--r--src/qt/locale/bitcoin_is.ts15
-rw-r--r--src/qt/locale/bitcoin_it.ts291
-rw-r--r--src/qt/locale/bitcoin_it_IT.ts1081
-rw-r--r--src/qt/locale/bitcoin_ja.ts358
-rw-r--r--src/qt/locale/bitcoin_ka.ts615
-rw-r--r--src/qt/locale/bitcoin_kk.ts3
-rw-r--r--src/qt/locale/bitcoin_km.ts7
-rw-r--r--src/qt/locale/bitcoin_ko.ts179
-rw-r--r--src/qt/locale/bitcoin_ku_IQ.ts87
-rw-r--r--src/qt/locale/bitcoin_ky.ts3
-rw-r--r--src/qt/locale/bitcoin_la.ts587
-rw-r--r--src/qt/locale/bitcoin_lt.ts153
-rw-r--r--src/qt/locale/bitcoin_lv.ts43
-rw-r--r--src/qt/locale/bitcoin_lv_LV.ts1279
-rw-r--r--src/qt/locale/bitcoin_mk.ts13
-rw-r--r--src/qt/locale/bitcoin_ml.ts3
-rw-r--r--src/qt/locale/bitcoin_mn.ts457
-rw-r--r--src/qt/locale/bitcoin_mr_IN.ts7
-rw-r--r--src/qt/locale/bitcoin_ms.ts31
-rw-r--r--src/qt/locale/bitcoin_ms_MY.ts632
-rw-r--r--src/qt/locale/bitcoin_my.ts166
-rw-r--r--src/qt/locale/bitcoin_nb.ts141
-rw-r--r--src/qt/locale/bitcoin_ne.ts25
-rw-r--r--src/qt/locale/bitcoin_nl.ts334
-rw-r--r--src/qt/locale/bitcoin_nl_NL.ts1029
-rw-r--r--src/qt/locale/bitcoin_pam.ts563
-rw-r--r--src/qt/locale/bitcoin_pl.ts165
-rw-r--r--src/qt/locale/bitcoin_pt.ts434
-rw-r--r--src/qt/locale/bitcoin_pt_BR.ts423
-rw-r--r--src/qt/locale/bitcoin_pt_PT.ts3502
-rw-r--r--src/qt/locale/bitcoin_ro.ts143
-rw-r--r--src/qt/locale/bitcoin_ro_RO.ts3659
-rw-r--r--src/qt/locale/bitcoin_ru.ts421
-rw-r--r--src/qt/locale/bitcoin_ru_RU.ts2407
-rw-r--r--src/qt/locale/bitcoin_si.ts5
-rw-r--r--src/qt/locale/bitcoin_sk.ts333
-rw-r--r--src/qt/locale/bitcoin_sk_SK.ts3651
-rw-r--r--src/qt/locale/bitcoin_sl.ts576
-rw-r--r--src/qt/locale/bitcoin_sl_SI.ts1913
-rw-r--r--src/qt/locale/bitcoin_sn.ts15
-rw-r--r--src/qt/locale/bitcoin_sq.ts774
-rw-r--r--src/qt/locale/bitcoin_sr.ts187
-rw-r--r--src/qt/locale/bitcoin_sr@latin.ts169
-rw-r--r--src/qt/locale/bitcoin_sv.ts255
-rw-r--r--src/qt/locale/bitcoin_szl.ts71
-rw-r--r--src/qt/locale/bitcoin_ta.ts1459
-rw-r--r--src/qt/locale/bitcoin_te.ts11
-rw-r--r--src/qt/locale/bitcoin_th.ts127
-rw-r--r--src/qt/locale/bitcoin_tr.ts567
-rw-r--r--src/qt/locale/bitcoin_tr_TR.ts1518
-rw-r--r--src/qt/locale/bitcoin_uk.ts609
-rw-r--r--src/qt/locale/bitcoin_uk_UA.ts239
-rw-r--r--src/qt/locale/bitcoin_ur.ts5
-rw-r--r--src/qt/locale/bitcoin_uz@Cyrl.ts725
-rw-r--r--src/qt/locale/bitcoin_uz@Latn.ts (renamed from src/qt/locale/bitcoin_fr_CA.ts)107
-rw-r--r--src/qt/locale/bitcoin_vi.ts183
-rw-r--r--src/qt/locale/bitcoin_vi_VN.ts1250
-rw-r--r--src/qt/locale/bitcoin_yo.ts13
-rw-r--r--src/qt/locale/bitcoin_zh-Hans.ts3
-rw-r--r--src/qt/locale/bitcoin_zh.ts1373
-rw-r--r--src/qt/locale/bitcoin_zh_CN.ts269
-rw-r--r--src/qt/locale/bitcoin_zh_HK.ts15
-rw-r--r--src/qt/locale/bitcoin_zh_TW.ts1675
-rw-r--r--src/qt/macnotificationhandler.mm2
-rw-r--r--src/qt/main.cpp4
-rw-r--r--src/qt/modaloverlay.cpp2
-rw-r--r--src/qt/optionsmodel.cpp3
-rw-r--r--src/qt/overviewpage.cpp31
-rw-r--r--src/qt/peertablemodel.cpp6
-rw-r--r--src/qt/peertablemodel.h2
-rw-r--r--src/qt/qvaluecombobox.h2
-rw-r--r--src/qt/receivecoinsdialog.cpp47
-rw-r--r--[-rwxr-xr-x]src/qt/res/icons/bitcoin.icobin57964 -> 57964 bytes
-rw-r--r--src/qt/rpcconsole.cpp17
-rw-r--r--src/qt/sendcoinsdialog.cpp157
-rw-r--r--src/qt/sendcoinsdialog.h3
-rw-r--r--src/qt/signverifymessagedialog.cpp114
-rw-r--r--src/qt/splashscreen.cpp4
-rw-r--r--src/qt/test/addressbooktests.cpp8
-rw-r--r--src/qt/test/apptests.cpp3
-rw-r--r--src/qt/test/apptests.h2
-rw-r--r--src/qt/test/util.cpp2
-rw-r--r--src/qt/test/util.h2
-rw-r--r--src/qt/test/wallettests.cpp14
-rw-r--r--src/qt/trafficgraphwidget.h2
-rw-r--r--src/qt/transactiondescdialog.h2
-rw-r--r--src/qt/transactiontablemodel.cpp9
-rw-r--r--src/qt/utilitydialog.cpp2
-rw-r--r--src/qt/utilitydialog.h2
-rw-r--r--src/qt/walletcontroller.cpp35
-rw-r--r--src/qt/walletcontroller.h7
-rw-r--r--src/qt/walletframe.cpp12
-rw-r--r--src/qt/walletframe.h3
-rw-r--r--src/qt/walletmodel.cpp50
-rw-r--r--src/qt/walletmodel.h9
-rw-r--r--src/qt/walletview.cpp80
-rw-r--r--src/qt/walletview.h6
-rw-r--r--src/random.cpp24
-rw-r--r--src/random.h17
-rw-r--r--src/randomenv.cpp21
-rw-r--r--src/rest.cpp4
-rw-r--r--src/reverselock.h34
-rw-r--r--src/rpc/blockchain.cpp681
-rw-r--r--src/rpc/client.cpp9
-rw-r--r--src/rpc/mining.cpp440
-rw-r--r--src/rpc/misc.cpp203
-rw-r--r--src/rpc/net.cpp304
-rw-r--r--src/rpc/rawtransaction.cpp618
-rw-r--r--src/rpc/rawtransaction_util.cpp60
-rw-r--r--src/rpc/rawtransaction_util.h4
-rw-r--r--src/rpc/server.cpp33
-rw-r--r--src/rpc/util.cpp165
-rw-r--r--src/rpc/util.h164
-rw-r--r--src/scheduler.cpp82
-rw-r--r--src/scheduler.h62
-rw-r--r--src/script/descriptor.cpp311
-rw-r--r--src/script/descriptor.h61
-rw-r--r--src/script/interpreter.cpp195
-rw-r--r--src/script/interpreter.h7
-rw-r--r--src/script/script.h33
-rw-r--r--src/script/script_error.cpp4
-rw-r--r--src/script/sign.cpp53
-rw-r--r--src/script/sign.h6
-rw-r--r--src/script/signingprovider.h46
-rw-r--r--src/serialize.h190
-rw-r--r--src/span.h35
-rw-r--r--src/support/lockedpool.cpp5
-rw-r--r--src/sync.cpp21
-rw-r--r--src/sync.h43
-rw-r--r--src/test/README.md29
-rw-r--r--src/test/addrman_tests.cpp62
-rw-r--r--src/test/arith_uint256_tests.cpp16
-rw-r--r--src/test/base32_tests.cpp4
-rw-r--r--src/test/base64_tests.cpp4
-rw-r--r--src/test/bip32_tests.cpp4
-rw-r--r--src/test/blockchain_tests.cpp7
-rw-r--r--src/test/blockfilter_index_tests.cpp4
-rw-r--r--src/test/bloom_tests.cpp9
-rw-r--r--src/test/bswap_tests.cpp22
-rw-r--r--src/test/checkqueue_tests.cpp16
-rw-r--r--src/test/coins_tests.cpp195
-rw-r--r--src/test/compilerbug_tests.cpp4
-rw-r--r--src/test/compress_tests.cpp4
-rw-r--r--src/test/crypto_tests.cpp6
-rw-r--r--src/test/cuckoocache_tests.cpp6
-rw-r--r--src/test/data/script_tests.json26
-rw-r--r--src/test/data/tx_invalid.json2
-rw-r--r--src/test/data/tx_valid.json6
-rw-r--r--src/test/dbwrapper_tests.cpp12
-rw-r--r--src/test/denialofservice_tests.cpp14
-rw-r--r--src/test/descriptor_tests.cpp156
-rw-r--r--src/test/fuzz/addition_overflow.cpp55
-rw-r--r--src/test/fuzz/addrdb.cpp43
-rw-r--r--src/test/fuzz/asmap.cpp28
-rw-r--r--src/test/fuzz/base_encode_decode.cpp9
-rw-r--r--src/test/fuzz/block.cpp14
-rw-r--r--src/test/fuzz/block_header.cpp41
-rw-r--r--src/test/fuzz/blockfilter.cpp44
-rw-r--r--src/test/fuzz/bloom_filter.cpp74
-rw-r--r--src/test/fuzz/chain.cpp65
-rw-r--r--src/test/fuzz/checkqueue.cpp65
-rw-r--r--src/test/fuzz/cuckoocache.cpp49
-rw-r--r--src/test/fuzz/descriptor_parse.cpp11
-rw-r--r--src/test/fuzz/deserialize.cpp20
-rw-r--r--src/test/fuzz/eval_script.cpp6
-rw-r--r--src/test/fuzz/fee_rate.cpp40
-rw-r--r--src/test/fuzz/fees.cpp29
-rw-r--r--src/test/fuzz/flatfile.cpp30
-rw-r--r--src/test/fuzz/float.cpp42
-rw-r--r--src/test/fuzz/fuzz.cpp2
-rw-r--r--src/test/fuzz/golomb_rice.cpp112
-rw-r--r--src/test/fuzz/hex.cpp25
-rw-r--r--src/test/fuzz/http_request.cpp73
-rw-r--r--src/test/fuzz/integer.cpp180
-rw-r--r--src/test/fuzz/key.cpp309
-rw-r--r--src/test/fuzz/key_io.cpp50
-rw-r--r--src/test/fuzz/kitchen_sink.cpp25
-rw-r--r--src/test/fuzz/locale.cpp96
-rw-r--r--src/test/fuzz/merkleblock.cpp27
-rw-r--r--src/test/fuzz/multiplication_overflow.cpp55
-rw-r--r--src/test/fuzz/net_permissions.cpp51
-rw-r--r--src/test/fuzz/netaddress.cpp134
-rw-r--r--src/test/fuzz/p2p_transport_deserializer.cpp47
-rw-r--r--src/test/fuzz/parse_hd_keypath.cpp10
-rw-r--r--src/test/fuzz/parse_univalue.cpp20
-rw-r--r--src/test/fuzz/policy_estimator.cpp69
-rw-r--r--src/test/fuzz/pow.cpp81
-rw-r--r--src/test/fuzz/prevector.cpp263
-rw-r--r--src/test/fuzz/primitives_transaction.cpp34
-rw-r--r--src/test/fuzz/process_message.cpp81
-rw-r--r--src/test/fuzz/process_messages.cpp80
-rw-r--r--src/test/fuzz/protocol.cpp32
-rw-r--r--src/test/fuzz/psbt.cpp4
-rw-r--r--src/test/fuzz/random.cpp31
-rw-r--r--src/test/fuzz/rbf.cpp47
-rw-r--r--src/test/fuzz/rolling_bloom_filter.cpp50
-rw-r--r--src/test/fuzz/script.cpp66
-rw-r--r--src/test/fuzz/script_flags.cpp4
-rw-r--r--src/test/fuzz/script_ops.cpp71
-rw-r--r--src/test/fuzz/scriptnum_ops.cpp134
-rw-r--r--src/test/fuzz/signature_checker.cpp68
-rw-r--r--src/test/fuzz/span.cpp39
-rw-r--r--src/test/fuzz/string.cpp122
-rw-r--r--src/test/fuzz/strprintf.cpp47
-rw-r--r--src/test/fuzz/system.cpp123
-rw-r--r--src/test/fuzz/timedata.cpp29
-rw-r--r--src/test/fuzz/transaction.cpp28
-rw-r--r--src/test/fuzz/util.h152
-rw-r--r--src/test/gen/crypto_gen.cpp19
-rw-r--r--src/test/gen/crypto_gen.h63
-rw-r--r--src/test/getarg_tests.cpp4
-rw-r--r--src/test/hash_tests.cpp4
-rw-r--r--src/test/interfaces_tests.cpp163
-rw-r--r--src/test/key_io_tests.cpp4
-rw-r--r--src/test/key_properties.cpp48
-rw-r--r--src/test/key_tests.cpp9
-rw-r--r--src/test/main.cpp20
-rw-r--r--src/test/merkleblock_tests.cpp4
-rw-r--r--src/test/multisig_tests.cpp6
-rw-r--r--src/test/net_tests.cpp18
-rw-r--r--src/test/netbase_tests.cpp4
-rw-r--r--src/test/pmt_tests.cpp6
-rw-r--r--src/test/policyestimator_tests.cpp4
-rw-r--r--src/test/prevector_tests.cpp4
-rw-r--r--src/test/random_tests.cpp4
-rw-r--r--src/test/reverselock_tests.cpp47
-rw-r--r--src/test/rpc_tests.cpp4
-rw-r--r--src/test/sanity_tests.cpp2
-rw-r--r--src/test/scheduler_tests.cpp106
-rw-r--r--src/test/script_p2sh_tests.cpp6
-rw-r--r--src/test/script_tests.cpp58
-rw-r--r--src/test/scriptnum10.h4
-rw-r--r--src/test/scriptnum_tests.cpp4
-rw-r--r--src/test/serialize_tests.cpp30
-rw-r--r--src/test/settings_tests.cpp5
-rw-r--r--src/test/sighash_tests.cpp6
-rw-r--r--src/test/sigopcount_tests.cpp6
-rw-r--r--src/test/timedata_tests.cpp5
-rw-r--r--src/test/transaction_tests.cpp121
-rw-r--r--src/test/txindex_tests.cpp10
-rw-r--r--src/test/txvalidation_tests.cpp4
-rw-r--r--src/test/txvalidationcache_tests.cpp16
-rw-r--r--src/test/uint256_tests.cpp7
-rw-r--r--src/test/util/logging.cpp8
-rw-r--r--src/test/util/logging.h14
-rw-r--r--src/test/util/net.cpp39
-rw-r--r--src/test/util/net.h33
-rw-r--r--src/test/util/setup_common.cpp57
-rw-r--r--src/test/util/setup_common.h11
-rw-r--r--src/test/util/transaction_utils.cpp34
-rw-r--r--src/test/util/transaction_utils.h12
-rw-r--r--src/test/util_tests.cpp170
-rw-r--r--src/test/util_threadnames_tests.cpp13
-rw-r--r--src/test/validation_block_tests.cpp40
-rw-r--r--src/test/validation_chainstatemanager_tests.cpp107
-rw-r--r--src/test/validation_flush_tests.cpp28
-rw-r--r--src/test/validationinterface_tests.cpp60
-rw-r--r--src/test/versionbits_tests.cpp8
-rw-r--r--src/txdb.cpp4
-rw-r--r--src/txmempool.cpp24
-rw-r--r--src/txmempool.h22
-rw-r--r--src/undo.h73
-rw-r--r--src/univalue/Makefile.am2
-rw-r--r--src/univalue/lib/univalue_read.cpp11
-rw-r--r--src/univalue/test/fail45.json1
-rw-r--r--src/univalue/test/pass4.json1
-rw-r--r--src/univalue/test/unitester.cpp2
-rw-r--r--src/util/asmap.cpp44
-rw-r--r--src/util/bip32.cpp2
-rw-r--r--src/util/bip32.h2
-rw-r--r--src/util/golombrice.h43
-rw-r--r--src/util/message.cpp92
-rw-r--r--src/util/message.h76
-rw-r--r--src/util/moneystr.cpp26
-rw-r--r--src/util/moneystr.h4
-rw-r--r--src/util/strencodings.cpp12
-rw-r--r--src/util/strencodings.h6
-rw-r--r--src/util/string.h16
-rw-r--r--src/util/system.cpp52
-rw-r--r--src/util/system.h12
-rw-r--r--src/util/time.cpp43
-rw-r--r--src/util/time.h6
-rw-r--r--src/util/url.h6
-rw-r--r--src/util/validation.cpp25
-rw-r--r--src/util/validation.h18
-rw-r--r--src/validation.cpp352
-rw-r--r--src/validation.h251
-rw-r--r--src/validationinterface.cpp138
-rw-r--r--src/validationinterface.h48
-rw-r--r--src/wallet/coinselection.cpp3
-rw-r--r--src/wallet/db.cpp6
-rw-r--r--src/wallet/db.h6
-rw-r--r--src/wallet/feebumper.cpp137
-rw-r--r--src/wallet/feebumper.h12
-rw-r--r--src/wallet/init.cpp11
-rw-r--r--src/wallet/load.cpp32
-rw-r--r--src/wallet/psbtwallet.cpp77
-rw-r--r--src/wallet/psbtwallet.h32
-rw-r--r--src/wallet/rpcdump.cpp419
-rw-r--r--src/wallet/rpcwallet.cpp1420
-rw-r--r--src/wallet/rpcwallet.h3
-rw-r--r--src/wallet/scriptpubkeyman.cpp776
-rw-r--r--src/wallet/scriptpubkeyman.h158
-rw-r--r--src/wallet/test/coinselector_tests.cpp30
-rw-r--r--src/wallet/test/psbt_wallet_tests.cpp9
-rw-r--r--src/wallet/test/scriptpubkeyman_tests.cpp43
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp5
-rw-r--r--src/wallet/test/wallet_test_fixture.h3
-rw-r--r--src/wallet/test/wallet_tests.cpp256
-rw-r--r--src/wallet/wallet.cpp920
-rw-r--r--src/wallet/wallet.h175
-rw-r--r--src/wallet/walletdb.cpp193
-rw-r--r--src/wallet/walletdb.h16
-rw-r--r--src/wallet/wallettool.cpp4
-rw-r--r--src/wallet/walletutil.cpp7
-rw-r--r--src/wallet/walletutil.h41
-rw-r--r--src/zmq/zmqnotificationinterface.cpp2
-rw-r--r--src/zmq/zmqnotificationinterface.h2
-rw-r--r--src/zmq/zmqrpc.cpp19
-rw-r--r--test/README.md2
-rw-r--r--test/functional/README.md8
-rw-r--r--test/functional/data/invalid_txs.py32
-rwxr-xr-xtest/functional/feature_abortnode.py6
-rwxr-xr-xtest/functional/feature_asmap.py106
-rwxr-xr-xtest/functional/feature_assumevalid.py6
-rwxr-xr-xtest/functional/feature_backwards_compatibility.py354
-rwxr-xr-xtest/functional/feature_bip68_sequence.py4
-rwxr-xr-xtest/functional/feature_block.py22
-rwxr-xr-xtest/functional/feature_cltv.py6
-rwxr-xr-xtest/functional/feature_config_args.py6
-rwxr-xr-xtest/functional/feature_csv_activation.py81
-rwxr-xr-xtest/functional/feature_dersig.py10
-rwxr-xr-xtest/functional/feature_fee_estimation.py27
-rwxr-xr-xtest/functional/feature_filelock.py2
-rwxr-xr-xtest/functional/feature_help.py2
-rwxr-xr-xtest/functional/feature_loadblock.py2
-rwxr-xr-xtest/functional/feature_logging.py2
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py19
-rwxr-xr-xtest/functional/feature_notifications.py18
-rwxr-xr-xtest/functional/feature_nulldummy.py9
-rwxr-xr-xtest/functional/feature_pruning.py2
-rwxr-xr-xtest/functional/feature_rbf.py4
-rwxr-xr-xtest/functional/feature_segwit.py51
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py100
-rwxr-xr-xtest/functional/interface_rpc.py2
-rwxr-xr-xtest/functional/mempool_accept.py7
-rwxr-xr-xtest/functional/mempool_expiry.py100
-rwxr-xr-xtest/functional/mempool_packages.py32
-rwxr-xr-xtest/functional/mempool_persist.py42
-rwxr-xr-xtest/functional/mempool_reorg.py37
-rwxr-xr-xtest/functional/mempool_unbroadcast.py99
-rwxr-xr-xtest/functional/mempool_updatefromblock.py123
-rwxr-xr-xtest/functional/mining_basic.py2
-rwxr-xr-xtest/functional/p2p_addr_relay.py71
-rwxr-xr-xtest/functional/p2p_compactblocks.py10
-rwxr-xr-xtest/functional/p2p_dos_header_tree.py11
-rwxr-xr-xtest/functional/p2p_filter.py158
-rwxr-xr-xtest/functional/p2p_fingerprint.py2
-rwxr-xr-xtest/functional/p2p_invalid_block.py4
-rwxr-xr-xtest/functional/p2p_invalid_locator.py4
-rwxr-xr-xtest/functional/p2p_invalid_messages.py39
-rwxr-xr-xtest/functional/p2p_invalid_tx.py19
-rwxr-xr-xtest/functional/p2p_leak.py59
-rwxr-xr-xtest/functional/p2p_leak_tx.py5
-rwxr-xr-xtest/functional/p2p_permissions.py12
-rwxr-xr-xtest/functional/p2p_segwit.py52
-rwxr-xr-xtest/functional/p2p_sendheaders.py16
-rwxr-xr-xtest/functional/p2p_timeouts.py11
-rwxr-xr-xtest/functional/p2p_tx_download.py14
-rwxr-xr-xtest/functional/p2p_unrequested_blocks.py37
-rwxr-xr-xtest/functional/rpc_blockchain.py5
-rwxr-xr-xtest/functional/rpc_createmultisig.py55
-rwxr-xr-xtest/functional/rpc_dumptxoutset.py4
-rwxr-xr-xtest/functional/rpc_estimatefee.py51
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py13
-rwxr-xr-xtest/functional/rpc_generateblock.py106
-rwxr-xr-xtest/functional/rpc_getaddressinfo_label_deprecation.py2
-rwxr-xr-xtest/functional/rpc_getaddressinfo_labels_purpose_deprecation.py2
-rwxr-xr-xtest/functional/rpc_getdescriptorinfo.py65
-rwxr-xr-xtest/functional/rpc_psbt.py66
-rwxr-xr-xtest/functional/rpc_scantxoutset.py2
-rwxr-xr-xtest/functional/rpc_signrawtransaction.py40
-rw-r--r--test/functional/test_framework/address.py2
-rw-r--r--test/functional/test_framework/authproxy.py19
-rw-r--r--test/functional/test_framework/bignum.py58
-rw-r--r--test/functional/test_framework/descriptors.py9
-rw-r--r--test/functional/test_framework/key.py13
-rwxr-xr-xtest/functional/test_framework/messages.py157
-rwxr-xr-xtest/functional/test_framework/mininode.py111
-rw-r--r--test/functional/test_framework/script.py331
-rwxr-xr-xtest/functional/test_framework/script_util.py1
-rwxr-xr-xtest/functional/test_framework/test_framework.py91
-rwxr-xr-xtest/functional/test_framework/test_node.py195
-rw-r--r--test/functional/test_framework/util.py32
-rwxr-xr-xtest/functional/test_framework/wallet_util.py23
-rwxr-xr-xtest/functional/test_runner.py56
-rwxr-xr-xtest/functional/tool_wallet.py2
-rwxr-xr-xtest/functional/wallet_abandonconflict.py6
-rwxr-xr-xtest/functional/wallet_address_types.py15
-rwxr-xr-xtest/functional/wallet_avoidreuse.py189
-rwxr-xr-xtest/functional/wallet_backup.py10
-rwxr-xr-xtest/functional/wallet_balance.py36
-rwxr-xr-xtest/functional/wallet_basic.py84
-rwxr-xr-xtest/functional/wallet_bumpfee.py195
-rwxr-xr-xtest/functional/wallet_bumpfee_totalfee_deprecation.py54
-rwxr-xr-xtest/functional/wallet_createwallet.py12
-rwxr-xr-xtest/functional/wallet_descriptor.py144
-rwxr-xr-xtest/functional/wallet_dump.py49
-rwxr-xr-xtest/functional/wallet_encryption.py24
-rwxr-xr-xtest/functional/wallet_groups.py8
-rwxr-xr-xtest/functional/wallet_hd.py115
-rwxr-xr-xtest/functional/wallet_import_rescan.py3
-rwxr-xr-xtest/functional/wallet_importdescriptors.py445
-rwxr-xr-xtest/functional/wallet_importmulti.py9
-rwxr-xr-xtest/functional/wallet_keypool.py132
-rwxr-xr-xtest/functional/wallet_keypool_topup.py10
-rwxr-xr-xtest/functional/wallet_labels.py19
-rwxr-xr-xtest/functional/wallet_listsinceblock.py28
-rwxr-xr-xtest/functional/wallet_listtransactions.py2
-rwxr-xr-xtest/functional/wallet_multiwallet.py29
-rwxr-xr-xtest/functional/wallet_resendwallettransactions.py30
-rwxr-xr-xtest/functional/wallet_txn_clone.py2
-rwxr-xr-xtest/functional/wallet_upgradewallet.py141
-rwxr-xr-xtest/fuzz/test_runner.py183
-rw-r--r--test/lint/README.md1
-rwxr-xr-xtest/lint/extended-lint-all.sh2
-rwxr-xr-xtest/lint/extended-lint-cppcheck.sh6
-rwxr-xr-xtest/lint/lint-circular-dependencies.sh2
-rwxr-xr-xtest/lint/lint-format-strings.sh2
-rwxr-xr-xtest/lint/lint-include-guards.sh2
-rwxr-xr-xtest/lint/lint-includes.sh5
-rwxr-xr-xtest/lint/lint-locale-dependence.sh19
-rwxr-xr-xtest/lint/lint-python-utf8-encoding.sh6
-rwxr-xr-xtest/lint/lint-shebang.sh2
-rwxr-xr-xtest/lint/lint-shell.sh14
-rw-r--r--test/lint/lint-spelling.ignore-words.txt2
-rwxr-xr-xtest/lint/lint-spelling.sh2
-rwxr-xr-xtest/lint/lint-submodule.sh20
-rwxr-xr-xtest/lint/lint-whitespace.sh4
-rw-r--r--test/sanitizer_suppressions/tsan8
-rw-r--r--test/sanitizer_suppressions/ubsan3
-rw-r--r--test/util/data/bitcoin-util-test.json40
-rw-r--r--test/util/data/txcreatescript5.hex1
-rw-r--r--test/util/data/txcreatescript6.hex1
904 files changed, 61768 insertions, 63536 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 777eebd2c3..eeb2d6590b 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -16,10 +16,8 @@ environment:
VCPKG_COMMIT_ID: 'ed0df8ecc4ed7e755ea03e18aaf285fd9b4b4a74'
cache:
- C:\tools\vcpkg\installed -> build_msvc\vcpkg-packages.txt
-- C:\Users\appveyor\clcache -> .appveyor.yml, build_msvc\**, **\Makefile.am, **\*.vcxproj.in
- C:\Qt5.9.8_x64_static_vs2019
install:
-- cmd: pip install --quiet git+https://github.com/frerich/clcache.git@v4.2.0
# 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:
@@ -46,7 +44,6 @@ install:
}
c:\tools\vcpkg\vcpkg integrate install
before_build:
-- ps: clcache -M 536870912
# Powershell block below is to download and extract the Qt static libraries. The pseudo code is:
# 1. If the Qt destination directory exists assume it is correct and do nothing. To
# force a fresh install of the packages delete the job's appveyor cache.
@@ -72,21 +69,20 @@ before_build:
Write-Host "Qt binaries already present.";
}
- cmd: python build_msvc\msvc-autogen.py
-- ps: Start-Process clcache-server
-- ps: fsutil behavior set disablelastaccess 0 # Enable Access time feature on Windows (for clcache)
build_script:
-- cmd: msbuild /p:TrackFileAccess=false /p:CLToolExe=clcache.exe build_msvc\bitcoin.sln /m /v:q /nologo
+- cmd: msbuild /p:TrackFileAccess=false build_msvc\bitcoin.sln /m /v:q /nologo
after_build:
-- ps: fsutil behavior set disablelastaccess 1 # Disable Access time feature on Windows (better performance)
-- ps: clcache -z
#- 7z a bitcoin-%APPVEYOR_BUILD_VERSION%.zip %APPVEYOR_BUILD_FOLDER%\build_msvc\%platform%\%configuration%\*.exe
test_script:
-- cmd: src\test_bitcoin.exe -k stdout -e stdout 2> NUL
+- cmd: src\test_bitcoin.exe -l test_suite
- cmd: src\bench_bitcoin.exe -evals=1 -scaling=0 > NUL
- ps: python test\util\bitcoin-util-test.py
- cmd: python test\util\rpcauth-test.py
# Fee estimation test failing on appveyor with: WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted.
-- cmd: python test\functional\test_runner.py --ci --quiet --combinedlogslen=4000 --failfast --exclude feature_fee_estimation
+# functional tests disabled for now. See
+# https://github.com/bitcoin/bitcoin/pull/18626#issuecomment-613396202
+# https://github.com/bitcoin/bitcoin/issues/18623
+# - cmd: python test\functional\test_runner.py --ci --quiet --combinedlogslen=4000 --failfast --exclude feature_fee_estimation
artifacts:
#- path: bitcoin-%APPVEYOR_BUILD_VERSION%.zip
deploy: off
diff --git a/.cirrus.yml b/.cirrus.yml
index f4a3878ed8..b839bfa5fb 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,7 +1,7 @@
task:
- name: "FreeBsd 12.0 amd64 [GOAL: install] [no depends, only system libs]"
+ name: "FreeBsd 12.1 amd64 [GOAL: install] [no depends, only system libs]"
freebsd_instance:
- image: freebsd-12-0-release-amd64
+ image_family: freebsd-12-1 # https://cirrus-ci.org/guide/FreeBSD/
cpu: 8
memory: 8G
timeout_in: 60m
@@ -28,6 +28,21 @@ task:
- gmake check ${MAKEJOBS} VERBOSE=1
functional_test_script:
- ./test/functional/test_runner.py --jobs 9 --ci --extended --exclude feature_dbcrash --combinedlogslen=1000 --quiet --failfast
+#task:
+# name: "Windows"
+# windows_container:
+# image: cirrusci/windowsservercore:2019
+# env:
+# CIRRUS_SHELL: powershell
+# PATH: 'C:\Python37;C:\Python37\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_LOCAL_PATH: 'C:\Qt5.9.8_x64_static_vs2019'
+# VCPKG_INSTALL_PATH: 'C:\tools\vcpkg\installed'
+# VCPKG_COMMIT_ID: 'ed0df8ecc4ed7e755ea03e18aaf285fd9b4b4a74'
+# install_script:
+# - choco install python --version=3.7.7 -y
task:
name: "x86_64 Linux [GOAL: install] [bionic] [Using ./ci/ system]"
container:
@@ -37,7 +52,7 @@ task:
timeout_in: 60m
env:
MAKEJOBS: "-j9"
- RUN_CI_ON_HOST: "1"
+ DANGER_RUN_CI_ON_HOST: "1"
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"
diff --git a/.gitignore b/.gitignore
index db493811c5..1c487f43a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -90,7 +90,7 @@ src/qt/bitcoin-qt.includes
*.qm
Makefile
!depends/Makefile
-bitcoin-qt
+src/qt/bitcoin-qt
Bitcoin-Qt.app
background.tiff*
@@ -108,6 +108,9 @@ qrc_*.cpp
.DS_Store
build
+# Previous releases
+releases
+
#lcov
*.gcno
*.gcda
diff --git a/.travis.yml b/.travis.yml
index fbc81b2614..63e502cc3e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,6 +25,8 @@
# [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: xenial
os: linux
language: minimal
@@ -35,9 +37,7 @@ cache:
- $TRAVIS_BUILD_DIR/depends/built
- $TRAVIS_BUILD_DIR/depends/sdk-sources
- $TRAVIS_BUILD_DIR/ci/scratch/.ccache
- # macOS
- - $HOME/Library/Caches/Homebrew
- - /usr/local/Homebrew
+ - $TRAVIS_BUILD_DIR/releases/$HOST
before_cache:
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then brew cleanup; fi
stages:
@@ -71,7 +71,7 @@ jobs:
- stage: lint
name: 'lint'
env:
- cache: false
+ cache: pip
language: python
python: '3.5' # Oldest supported version according to doc/dependencies.md
install:
@@ -83,17 +83,39 @@ jobs:
- stage: test
name: 'ARM [GOAL: install] [buster] [unit tests, functional tests]'
- arch: arm64
+ 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="" # Can run the tests natively without qemu
+ QEMU_USER_CMD=""
- stage: test
- name: 'S390x [GOAL: install] [buster] [unit tests, functional tests]'
+ name: 's390x native BE [GOAL: install] [bionic] [no depends, no GUI]'
arch: s390x
+ dist: bionic
+ addons:
+ apt:
+ packages:
+ - bsdmainutils
+ - libboost-filesystem-dev
+ - libboost-system-dev
+ - libboost-test-dev
+ - libboost-thread-dev
+ - libdb++-dev
+ - libdb-dev
+ - libevent-dev
env: >-
- FILE_ENV="./ci/test/00_setup_env_s390x.sh"
- QEMU_USER_CMD="" # Can run the tests natively without qemu
+ DANGER_RUN_CI_ON_HOST=true
+ CI_USE_APT_INSTALL=no
+ FILE_ENV="./ci/test/00_setup_env_s390x_host.sh"
+
+# s390 build was disabled temporarily because of disk space issues on the Travis VM
+#
+# - 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 functional tests]'
@@ -106,7 +128,7 @@ jobs:
FILE_ENV="./ci/test/00_setup_env_i686_centos.sh"
- stage: test
- name: 'x86_64 Linux [GOAL: install] [bionic] [uses qt5 dev package and some depends packages] [unsigned char]'
+ 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"
@@ -127,11 +149,16 @@ jobs:
FILE_ENV="./ci/test/00_setup_env_native_valgrind.sh"
- stage: test
- name: 'x86_64 Linux [GOAL: install] [bionic] [no depends, only system libs, sanitizers: fuzzer,address,undefined]'
+ 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] [no depends, only system libs, fuzzers under valgrind]'
+ env: >-
+ FILE_ENV="./ci/test/00_setup_env_native_fuzz_with_valgrind.sh"
+
+ - stage: test
name: 'x86_64 Linux [GOAL: install] [bionic] [no wallet]'
env: >-
FILE_ENV="./ci/test/00_setup_env_native_nowallet.sh"
@@ -145,8 +172,28 @@ jobs:
name: 'macOS 10.14 native [GOAL: install] [GUI] [no depends]'
os: osx
# Use the most recent version:
- # Xcode 11.2.1, macOS 10.14, JDK 13.0.1, SDK 10.15
+ # Xcode 11.3.1, macOS 10.14, SDK 10.15
# https://docs.travis-ci.com/user/reference/osx/#macos-version
- osx_image: xcode11.2
+ osx_image: xcode11.3
+ cache:
+ directories:
+ - $TRAVIS_BUILD_DIR/ci/scratch/.ccache
+ - $TRAVIS_BUILD_DIR/releases/$HOST
+ - $HOME/Library/Caches/Homebrew
+ - /usr/local/Homebrew
+ addons:
+ homebrew:
+ packages:
+ - libtool
+ - berkeley-db4
+ - boost
+ - miniupnpc
+ - qt
+ - qrencode
+ - python3
+ - 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/.tx/config b/.tx/config
index 0e18a0df98..cd9e237158 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,7 +1,7 @@
[main]
host = https://www.transifex.com
-[bitcoin.qt-translation-019x]
+[bitcoin.qt-translation-020x]
file_filter = src/qt/locale/bitcoin_<lang>.ts
source_file = src/qt/locale/bitcoin_en.ts
source_lang = en
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 33c797d799..7216db0500 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -46,15 +46,15 @@ facilitates social contribution, easy testing and peer review.
To contribute a patch, the workflow is as follows:
- 1. Fork repository ([only the first time](https://help.github.com/en/articles/fork-a-repo)).
+ 1. Fork repository ([only for the first time](https://help.github.com/en/articles/fork-a-repo))
1. Create topic branch
1. Commit patches
The project coding conventions in the [developer notes](doc/developer-notes.md)
-must be adhered to.
+must be followed.
-In general [commits should be atomic](https://en.wikipedia.org/wiki/Atomic_commit#Atomic_commit_convention)
-and diffs should be easy to read. For this reason do not mix any formatting
+In general, [commits should be atomic](https://en.wikipedia.org/wiki/Atomic_commit#Atomic_commit_convention)
+and diffs should be easy to read. For this reason, do not mix any formatting
fixes or code moves with actual code changes.
Commit messages should be verbose by default consisting of a short subject line
@@ -100,7 +100,7 @@ Examples:
qt: Add feed bump button
log: Fix typo in log message
-Note that translations should not be submitted as pull requests, please see
+Note that translations should not be submitted as pull requests. Please see
[Translation Process](https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md)
for more information on helping with translations.
@@ -113,16 +113,16 @@ patch does together with any justification/reasoning. You should include
references to any discussions (for example other tickets or mailing list
discussions).
-At this stage one should expect comments and review from other contributors. You
+At this stage, one should expect comments and review from other contributors. You
can add more commits to your pull request by committing them locally and pushing
to your fork until you have satisfied all feedback.
-Note: Code review is a burdensome but important part of the development process, and as such, certain types of pull requests are rejected. In general, if the **improvements** do not warrant the **review effort** required, the PR has a high chance of being rejected. It is up to the PR author to convince the reviewers that the changes warrant the review effort, and if reviewers are "Concept NAK'ing" the PR, the author may need to present arguments and/or do research backing their suggested changes.
+Note: Code review is a burdensome but important part of the development process, and as such, certain types of pull requests are rejected. In general, if the **improvements** do not warrant the **review effort** required, the PR has a high chance of being rejected. It is up to the PR author to convince the reviewers that the changes warrant the review effort, and if reviewers are "Concept NACK'ing" the PR, the author may need to present arguments and/or do research backing their suggested changes.
-Squashing Commits
----------------------------
-If your pull request is accepted for merging, you may be asked by a maintainer
-to squash and or [rebase](https://git-scm.com/docs/git-rebase) your commits
+### Squashing Commits
+
+If your pull request contains fixup commits (commits that change the same line of code repeatedly) or too fine-grained
+commits, you may be asked to [squash](https://git-scm.com/docs/git-rebase#_interactive_mode) your commits
before it will be merged. The basic squashing workflow is shown below.
git checkout your_branch_name
@@ -133,8 +133,8 @@ before it will be merged. The basic squashing workflow is shown below.
# Save and quit.
git push -f # (force push to GitHub)
-Please update the resulting commit message if needed, it should read as a
-coherent message. In most cases this means that you should not just list the
+Please update the resulting commit message if needed. It should read as a
+coherent message. In most cases, this means that you should not just list the
interim commits.
If you have problems with squashing (or other workflows with `git`), you can
@@ -149,6 +149,20 @@ the respective change set.
The length of time required for peer review is unpredictable and will vary from
pull request to pull request.
+### Rebasing Changes
+
+When a pull request conflicts with the target branch, you may be asked to rebase it on top of the current target branch.
+The `git rebase` command will take care of rebuilding your commits on top of the new base.
+
+This project aims to have a clean git history, where code changes are only made in non-merge commits. This simplifies
+auditability because merge commits can be assumed to not contain arbitrary code changes. Merge commits should be signed,
+and the resulting git tree hash must be deterministic and reproducible. The script in
+[/contrib/verify-commits](/contrib/verify-commits) checks that.
+
+After a rebase, reviewers are encouraged to sign off on the force push. This should be relatively straightforward with
+the `git range-diff` tool explained in the [productivity
+notes](/doc/productivity.md#diff-the-diffs-with-git-range-diff). To avoid needless review churn, maintainers will
+generally merge pull requests that received the most review attention first.
Pull Request Philosophy
-----------------------
@@ -173,9 +187,9 @@ in the future, they may be removed by the Repository Maintainer.
Refactoring is a necessary part of any software project's evolution. The
following guidelines cover refactoring pull requests for the project.
-There are three categories of refactoring, code only moves, code style fixes,
-code refactoring. In general refactoring pull requests should not mix these
-three kinds of activity in order to make refactoring pull requests easy to
+There are three categories of refactoring: code-only moves, code style fixes, and
+code refactoring. In general, refactoring pull requests should not mix these
+three kinds of activities in order to make refactoring pull requests easy to
review and uncontroversial. In all cases, refactoring PRs must not change the
behaviour of code within the pull request (bugs must be preserved as is).
@@ -309,6 +323,31 @@ about:
when someone else is asking for feedback on their code, and universe balances out.
+Backporting
+-----------
+
+Security and bug fixes can be backported from `master` to release
+branches.
+If the backport is non-trivial, it may be appropriate to open an
+additional PR, to backport the change, only after the original PR
+has been merged.
+Otherwise, backports will be done in batches and
+the maintainers will use the proper `Needs backport (...)` labels
+when needed (the original author does not need to worry).
+
+A backport should contain the following metadata in the commit body:
+
+```
+Github-Pull: #<PR number>
+Rebased-From: <commit hash of the original commit>
+```
+
+Have a look at [an example backport PR](
+https://github.com/bitcoin/bitcoin/pull/16189).
+
+Also see the [backport.py script](
+https://github.com/bitcoin-core/bitcoin-maintainer-tools#backport).
+
Release Policy
--------------
diff --git a/Makefile.am b/Makefile.am
index 22b83e80dd..c35f5080aa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (c) 2013-2016 The Bitcoin Core developers
+# Copyright (c) 2013-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.
@@ -43,16 +43,7 @@ OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns
OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed
OSX_QT_TRANSLATIONS = da,de,es,hu,ru,uk,zh_CN,zh_TW
-DIST_DOCS = \
- README.md \
- $(wildcard doc/*.md) \
- $(wildcard doc/release-notes/*.md)
-DIST_CONTRIB = $(top_srcdir)/contrib/bitcoin-cli.bash-completion \
- $(top_srcdir)/contrib/bitcoin-tx.bash-completion \
- $(top_srcdir)/contrib/bitcoind.bash-completion \
- $(top_srcdir)/contrib/debian/copyright \
- $(top_srcdir)/contrib/init \
- $(top_srcdir)/contrib/install_db4.sh \
+DIST_CONTRIB = \
$(top_srcdir)/contrib/linearize/linearize-data.py \
$(top_srcdir)/contrib/linearize/linearize-hashes.py
@@ -77,7 +68,7 @@ OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \
COVERAGE_INFO = baseline.info \
test_bitcoin_filtered.info total_coverage.info \
baseline_filtered.info functional_test.info functional_test_filtered.info \
- test_bitcoin_coverage.info test_bitcoin.info
+ test_bitcoin_coverage.info test_bitcoin.info fuzz.info fuzz_coverage.info
dist-hook:
-$(GIT) archive --format=tar HEAD -- src/clientversion.cpp | $(AMTAR) -C $(top_distdir) -xf -
@@ -194,6 +185,7 @@ LCOV_FILTER_PATTERN = \
-p "/usr/lib/" \
-p "/usr/lib64/" \
-p "src/leveldb/" \
+ -p "src/crc32c/" \
-p "src/bench/" \
-p "src/univalue" \
-p "src/crypto/ctaes" \
@@ -207,6 +199,15 @@ baseline_filtered.info: baseline.info
$(abs_builddir)/contrib/filter-lcov.py $(LCOV_FILTER_PATTERN) $< $@
$(LCOV) -a $@ $(LCOV_OPTS) -o $@
+fuzz.info: baseline_filtered.info
+ @TIMEOUT=15 test/fuzz/test_runner.py qa-assets/fuzz_seed_corpus -l DEBUG
+ $(LCOV) -c $(LCOV_OPTS) -d $(abs_builddir)/src --t fuzz-tests -o $@
+ $(LCOV) -z $(LCOV_OPTS) -d $(abs_builddir)/src
+
+fuzz_filtered.info: fuzz.info
+ $(abs_builddir)/contrib/filter-lcov.py $(LCOV_FILTER_PATTERN) $< $@
+ $(LCOV) -a $@ $(LCOV_OPTS) -o $@
+
test_bitcoin.info: baseline_filtered.info
$(MAKE) -C src/ check
$(LCOV) -c $(LCOV_OPTS) -d $(abs_builddir)/src -t test_bitcoin -o $@
@@ -225,12 +226,19 @@ functional_test_filtered.info: functional_test.info
$(abs_builddir)/contrib/filter-lcov.py $(LCOV_FILTER_PATTERN) $< $@
$(LCOV) -a $@ $(LCOV_OPTS) -o $@
+fuzz_coverage.info: fuzz_filtered.info
+ $(LCOV) -a $(LCOV_OPTS) baseline_filtered.info -a fuzz_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt
+
test_bitcoin_coverage.info: baseline_filtered.info test_bitcoin_filtered.info
$(LCOV) -a $(LCOV_OPTS) baseline_filtered.info -a test_bitcoin_filtered.info -o $@
total_coverage.info: test_bitcoin_filtered.info functional_test_filtered.info
$(LCOV) -a $(LCOV_OPTS) baseline_filtered.info -a test_bitcoin_filtered.info -a functional_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt
+fuzz.coverage/.dirstamp: fuzz_coverage.info
+ $(GENHTML) -s $(LCOV_OPTS) $< -o $(@D)
+ @touch $@
+
test_bitcoin.coverage/.dirstamp: test_bitcoin_coverage.info
$(GENHTML) -s $(LCOV_OPTS) $< -o $(@D)
@touch $@
@@ -239,13 +247,15 @@ total.coverage/.dirstamp: total_coverage.info
$(GENHTML) -s $(LCOV_OPTS) $< -o $(@D)
@touch $@
+cov_fuzz: fuzz.coverage/.dirstamp
+
cov: test_bitcoin.coverage/.dirstamp total.coverage/.dirstamp
endif
dist_noinst_SCRIPTS = autogen.sh
-EXTRA_DIST = $(DIST_SHARE) $(DIST_CONTRIB) $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) $(BIN_CHECKS)
+EXTRA_DIST = $(DIST_SHARE) $(DIST_CONTRIB) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) $(BIN_CHECKS)
EXTRA_DIST += \
test/functional \
@@ -300,6 +310,8 @@ EXTRA_DIST += \
test/util/data/txcreatescript3.json \
test/util/data/txcreatescript4.hex \
test/util/data/txcreatescript4.json \
+ test/util/data/txcreatescript5.hex \
+ test/util/data/txcreatescript6.hex \
test/util/data/txcreatesignv1.hex \
test/util/data/txcreatesignv1.json \
test/util/data/txcreatesignv2.hex \
@@ -327,6 +339,6 @@ clean-docs:
rm -rf doc/doxygen
clean-local: clean-docs
- rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ test/tmp/ cache/ $(OSX_APP)
+ rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ fuzz.coverage/ test/tmp/ cache/ $(OSX_APP)
rm -rf test/functional/__pycache__ test/functional/test_framework/__pycache__ test/cache share/rpcauth/__pycache__
rm -rf osx_volname dist/ dpi36.background.tiff dpi72.background.tiff
diff --git a/README.md b/README.md
index 400320dde0..9213471c41 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ information or see https://opensource.org/licenses/MIT.
Development Process
-------------------
-The `master` branch is regularly built and tested, but is not guaranteed to be
+The `master` branch is regularly built (see doc/build-*.md for instructions) and tested, but is not guaranteed to be
completely stable. [Tags](https://github.com/bitcoin/bitcoin/tags) are created
regularly to indicate new official, stable release versions of Bitcoin Core.
diff --git a/build-aux/m4/ax_boost_base.m4 b/build-aux/m4/ax_boost_base.m4
index 16fa69b41f..2ae33f7140 100644
--- a/build-aux/m4/ax_boost_base.m4
+++ b/build-aux/m4/ax_boost_base.m4
@@ -33,7 +33,7 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 47
+#serial 48
# example boost program (need to pass version)
m4_define([_AX_BOOST_BASE_PROGRAM],
@@ -123,6 +123,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
dnl are almost assuredly the ones desired.
AS_CASE([${host_cpu}],
[i?86],[multiarch_libsubdir="lib/i386-${host_os}"],
+ [armv7l],[multiarch_libsubdir="lib/arm-${host_os}"],
[multiarch_libsubdir="lib/${host_cpu}-${host_os}"]
)
diff --git a/build-aux/m4/ax_boost_chrono.m4 b/build-aux/m4/ax_boost_chrono.m4
deleted file mode 100644
index 4cd3b86041..0000000000
--- a/build-aux/m4/ax_boost_chrono.m4
+++ /dev/null
@@ -1,118 +0,0 @@
-# ===========================================================================
-# https://www.gnu.org/software/autoconf-archive/ax_boost_chrono.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_BOOST_CHRONO
-#
-# DESCRIPTION
-#
-# Test for Chrono library from the Boost C++ libraries. The macro requires
-# a preceding call to AX_BOOST_BASE. Further documentation is available at
-# <http://randspringer.de/boost/index.html>.
-#
-# This macro calls:
-#
-# AC_SUBST(BOOST_CHRONO_LIB)
-#
-# And sets:
-#
-# HAVE_BOOST_CHRONO
-#
-# LICENSE
-#
-# Copyright (c) 2012 Xiyue Deng <manphiz@gmail.com>
-#
-# Copying and distribution of this file, with or without modification, are
-# permitted in any medium without royalty provided the copyright notice
-# and this notice are preserved. This file is offered as-is, without any
-# warranty.
-
-#serial 5
-
-AC_DEFUN([AX_BOOST_CHRONO],
-[
- AC_ARG_WITH([boost-chrono],
- AS_HELP_STRING([--with-boost-chrono@<:@=special-lib@:>@],
- [use the Chrono library from boost - it is possible to specify a certain library for the linker
- e.g. --with-boost-chrono=boost_chrono-gcc-mt ]),
- [
- if test "$withval" = "no"; then
- want_boost="no"
- elif test "$withval" = "yes"; then
- want_boost="yes"
- ax_boost_user_chrono_lib=""
- else
- want_boost="yes"
- ax_boost_user_chrono_lib="$withval"
- fi
- ],
- [want_boost="yes"]
- )
-
- if test "x$want_boost" = "xyes"; then
- AC_REQUIRE([AC_PROG_CC])
- AC_REQUIRE([AC_CANONICAL_BUILD])
- CPPFLAGS_SAVED="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
- export CPPFLAGS
-
- LDFLAGS_SAVED="$LDFLAGS"
- LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
- export LDFLAGS
-
- AC_CACHE_CHECK(whether the Boost::Chrono library is available,
- ax_cv_boost_chrono,
- [AC_LANG_PUSH([C++])
- CXXFLAGS_SAVE=$CXXFLAGS
-
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/chrono.hpp>]],
- [[boost::chrono::system_clock::time_point* time = new boost::chrono::system_clock::time_point; delete time;]])],
- ax_cv_boost_chrono=yes, ax_cv_boost_chrono=no)
- CXXFLAGS=$CXXFLAGS_SAVE
- AC_LANG_POP([C++])
- ])
- if test "x$ax_cv_boost_chrono" = "xyes"; then
- AC_SUBST(BOOST_CPPFLAGS)
-
- AC_DEFINE(HAVE_BOOST_CHRONO,,[define if the Boost::Chrono library is available])
- BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
-
- LDFLAGS_SAVE=$LDFLAGS
- if test "x$ax_boost_user_chrono_lib" = "x"; then
- for libextension in `ls $BOOSTLIBDIR/libboost_chrono*.so* $BOOSTLIBDIR/libboost_chrono*.dylib* $BOOSTLIBDIR/libboost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_chrono.*\)\.so.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.a.*$;\1;'` ; do
- ax_lib=${libextension}
- AC_CHECK_LIB($ax_lib, exit,
- [BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
- [link_chrono="no"])
- done
- if test "x$link_chrono" != "xyes"; then
- for libextension in `ls $BOOSTLIBDIR/boost_chrono*.dll* $BOOSTLIBDIR/boost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_chrono.*\)\.dll.*$;\1;' -e 's;^\(boost_chrono.*\)\.a.*$;\1;'` ; do
- ax_lib=${libextension}
- AC_CHECK_LIB($ax_lib, exit,
- [BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
- [link_chrono="no"])
- done
- fi
-
- else
- for ax_lib in $ax_boost_user_chrono_lib boost_chrono-$ax_boost_user_chrono_lib; do
- AC_CHECK_LIB($ax_lib, exit,
- [BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
- [link_chrono="no"])
- done
-
- fi
- if test "x$ax_lib" = "x"; then
- AC_MSG_ERROR(Could not find a version of the Boost::Chrono library!)
- fi
- if test "x$link_chrono" = "xno"; then
- AC_MSG_ERROR(Could not link against $ax_lib !)
- fi
- fi
-
- CPPFLAGS="$CPPFLAGS_SAVED"
- LDFLAGS="$LDFLAGS_SAVED"
- fi
-])
diff --git a/build-aux/m4/ax_cxx_compile_stdcxx.m4 b/build-aux/m4/ax_cxx_compile_stdcxx.m4
index f147cee3b1..43087b2e68 100644
--- a/build-aux/m4/ax_cxx_compile_stdcxx.m4
+++ b/build-aux/m4/ax_cxx_compile_stdcxx.m4
@@ -1,5 +1,5 @@
# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
# ===========================================================================
#
# SYNOPSIS
@@ -33,21 +33,23 @@
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
+# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
+# Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 4
+#serial 11
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
dnl (serial version number 13).
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
- m4_if([$1], [11], [],
- [$1], [14], [],
- [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])],
+ m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
+ [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
+ [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$2], [], [],
[$2], [ext], [],
@@ -57,26 +59,13 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
- m4_if([$4], [], [ax_cxx_compile_cxx$1_try_default=true],
- [$4], [default], [ax_cxx_compile_cxx$1_try_default=true],
- [$4], [nodefault], [ax_cxx_compile_cxx$1_try_default=false],
- [m4_fatal([invalid fourth argument `$4' to AX_CXX_COMPILE_STDCXX])])
AC_LANG_PUSH([C++])dnl
ac_success=no
- m4_if([$4], [nodefault], [], [dnl
- AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
- ax_cv_cxx_compile_cxx$1,
- [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
- [ax_cv_cxx_compile_cxx$1=yes],
- [ax_cv_cxx_compile_cxx$1=no])])
- if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
- ac_success=yes
- fi])
-
m4_if([$2], [noext], [], [dnl
if test x$ac_success = xno; then
- for switch in -std=gnu++$1 -std=gnu++0x; do
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ switch="-std=gnu++${alternative}"
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
@@ -102,22 +91,27 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
dnl HP's aCC needs +std=c++11 according to:
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
dnl Cray's crayCC needs "-h std=c++11"
- for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do
- cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
- AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
- $cachevar,
- [ac_save_CXX="$CXX"
- CXX="$CXX $switch"
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
- [eval $cachevar=yes],
- [eval $cachevar=no])
- CXX="$ac_save_CXX"])
- if eval test x\$$cachevar = xyes; then
- CXX="$CXX $switch"
- if test -n "$CXXCPP" ; then
- CXXCPP="$CXXCPP $switch"
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+ $cachevar,
+ [ac_save_CXX="$CXX"
+ CXX="$CXX $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXX="$ac_save_CXX"])
+ if eval test x\$$cachevar = xyes; then
+ CXX="$CXX $switch"
+ if test -n "$CXXCPP" ; then
+ CXXCPP="$CXXCPP $switch"
+ fi
+ ac_success=yes
+ break
fi
- ac_success=yes
+ done
+ if test x$ac_success = xyes; then
break
fi
done
@@ -154,6 +148,11 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
)
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+)
dnl Tests for new features in C++11
@@ -191,11 +190,13 @@ namespace cxx11
struct Base
{
+ virtual ~Base() {}
virtual void f() {}
};
struct Derived : public Base
{
+ virtual ~Derived() override {}
virtual void f() override {}
};
@@ -524,7 +525,7 @@ namespace cxx14
}
- namespace test_digit_seperators
+ namespace test_digit_separators
{
constexpr auto ten_million = 100'000'000;
@@ -566,3 +567,385 @@ namespace cxx14
#endif // __cplusplus >= 201402L
]])
+
+
+dnl Tests for new features in C++17
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
+
+// If the compiler admits that it is not ready for C++17, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201703L
+
+#error "This is not a C++17 compiler"
+
+#else
+
+#include <initializer_list>
+#include <utility>
+#include <type_traits>
+
+namespace cxx17
+{
+
+ namespace test_constexpr_lambdas
+ {
+
+ constexpr int foo = [](){return 42;}();
+
+ }
+
+ namespace test::nested_namespace::definitions
+ {
+
+ }
+
+ namespace test_fold_expression
+ {
+
+ template<typename... Args>
+ int multiply(Args... args)
+ {
+ return (args * ... * 1);
+ }
+
+ template<typename... Args>
+ bool all(Args... args)
+ {
+ return (args && ...);
+ }
+
+ }
+
+ namespace test_extended_static_assert
+ {
+
+ static_assert (true);
+
+ }
+
+ namespace test_auto_brace_init_list
+ {
+
+ auto foo = {5};
+ auto bar {5};
+
+ static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
+ static_assert(std::is_same<int, decltype(bar)>::value);
+ }
+
+ namespace test_typename_in_template_template_parameter
+ {
+
+ template<template<typename> typename X> struct D;
+
+ }
+
+ namespace test_fallthrough_nodiscard_maybe_unused_attributes
+ {
+
+ int f1()
+ {
+ return 42;
+ }
+
+ [[nodiscard]] int f2()
+ {
+ [[maybe_unused]] auto unused = f1();
+
+ switch (f1())
+ {
+ case 17:
+ f1();
+ [[fallthrough]];
+ case 42:
+ f1();
+ }
+ return f1();
+ }
+
+ }
+
+ namespace test_extended_aggregate_initialization
+ {
+
+ struct base1
+ {
+ int b1, b2 = 42;
+ };
+
+ struct base2
+ {
+ base2() {
+ b3 = 42;
+ }
+ int b3;
+ };
+
+ struct derived : base1, base2
+ {
+ int d;
+ };
+
+ derived d1 {{1, 2}, {}, 4}; // full initialization
+ derived d2 {{}, {}, 4}; // value-initialized bases
+
+ }
+
+ namespace test_general_range_based_for_loop
+ {
+
+ struct iter
+ {
+ int i;
+
+ int& operator* ()
+ {
+ return i;
+ }
+
+ const int& operator* () const
+ {
+ return i;
+ }
+
+ iter& operator++()
+ {
+ ++i;
+ return *this;
+ }
+ };
+
+ struct sentinel
+ {
+ int i;
+ };
+
+ bool operator== (const iter& i, const sentinel& s)
+ {
+ return i.i == s.i;
+ }
+
+ bool operator!= (const iter& i, const sentinel& s)
+ {
+ return !(i == s);
+ }
+
+ struct range
+ {
+ iter begin() const
+ {
+ return {0};
+ }
+
+ sentinel end() const
+ {
+ return {5};
+ }
+ };
+
+ void f()
+ {
+ range r {};
+
+ for (auto i : r)
+ {
+ [[maybe_unused]] auto v = i;
+ }
+ }
+
+ }
+
+ namespace test_lambda_capture_asterisk_this_by_value
+ {
+
+ struct t
+ {
+ int i;
+ int foo()
+ {
+ return [*this]()
+ {
+ return i;
+ }();
+ }
+ };
+
+ }
+
+ namespace test_enum_class_construction
+ {
+
+ enum class byte : unsigned char
+ {};
+
+ byte foo {42};
+
+ }
+
+ namespace test_constexpr_if
+ {
+
+ template <bool cond>
+ int f ()
+ {
+ if constexpr(cond)
+ {
+ return 13;
+ }
+ else
+ {
+ return 42;
+ }
+ }
+
+ }
+
+ namespace test_selection_statement_with_initializer
+ {
+
+ int f()
+ {
+ return 13;
+ }
+
+ int f2()
+ {
+ if (auto i = f(); i > 0)
+ {
+ return 3;
+ }
+
+ switch (auto i = f(); i + 4)
+ {
+ case 17:
+ return 2;
+
+ default:
+ return 1;
+ }
+ }
+
+ }
+
+ namespace test_template_argument_deduction_for_class_templates
+ {
+
+ template <typename T1, typename T2>
+ struct pair
+ {
+ pair (T1 p1, T2 p2)
+ : m1 {p1},
+ m2 {p2}
+ {}
+
+ T1 m1;
+ T2 m2;
+ };
+
+ void f()
+ {
+ [[maybe_unused]] auto p = pair{13, 42u};
+ }
+
+ }
+
+ namespace test_non_type_auto_template_parameters
+ {
+
+ template <auto n>
+ struct B
+ {};
+
+ B<5> b1;
+ B<'a'> b2;
+
+ }
+
+ namespace test_structured_bindings
+ {
+
+ int arr[2] = { 1, 2 };
+ std::pair<int, int> pr = { 1, 2 };
+
+ auto f1() -> int(&)[2]
+ {
+ return arr;
+ }
+
+ auto f2() -> std::pair<int, int>&
+ {
+ return pr;
+ }
+
+ struct S
+ {
+ int x1 : 2;
+ volatile double y1;
+ };
+
+ S f3()
+ {
+ return {};
+ }
+
+ auto [ x1, y1 ] = f1();
+ auto& [ xr1, yr1 ] = f1();
+ auto [ x2, y2 ] = f2();
+ auto& [ xr2, yr2 ] = f2();
+ const auto [ x3, y3 ] = f3();
+
+ }
+
+ namespace test_exception_spec_type_system
+ {
+
+ struct Good {};
+ struct Bad {};
+
+ void g1() noexcept;
+ void g2();
+
+ template<typename T>
+ Bad
+ f(T*, T*);
+
+ template<typename T1, typename T2>
+ Good
+ f(T1*, T2*);
+
+ static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
+
+ }
+
+ namespace test_inline_variables
+ {
+
+ template<class T> void f(T)
+ {}
+
+ template<class T> inline T g(T)
+ {
+ return T{};
+ }
+
+ template<> inline void f<>(int)
+ {}
+
+ template<> int g<>(int)
+ {
+ return 5;
+ }
+
+ }
+
+} // namespace cxx17
+
+#endif // __cplusplus < 201703L
+
+]])
diff --git a/build_msvc/.gitignore b/build_msvc/.gitignore
index 4d4aef7e35..3e71c7b8d3 100644
--- a/build_msvc/.gitignore
+++ b/build_msvc/.gitignore
@@ -8,7 +8,19 @@ packages/*
*/Release
*/x64
*.vcxproj.user
-*.vcxproj
+
+# .vcxproj files that are auto-generated by the msvc-autogen.py script.
+libbitcoin_cli/libbitcoin_cli.vcxproj
+libbitcoin_common/libbitcoin_common.vcxproj
+libbitcoin_crypto/libbitcoin_crypto.vcxproj
+libbitcoin_server/libbitcoin_server.vcxproj
+libbitcoin_util/libbitcoin_util.vcxproj
+libbitcoin_wallet_tool/libbitcoin_wallet_tool.vcxproj
+libbitcoin_wallet/libbitcoin_wallet.vcxproj
+libbitcoin_zmq/libbitcoin_zmq.vcxproj
+bench_bitcoin/bench_bitcoin.vcxproj
+libtest_util/libtest_util.vcxproj
+
*/Win32
libbitcoin_qt/QtGeneratedFiles/*
test_bitcoin-qt/QtGeneratedFiles/*
diff --git a/build_msvc/README.md b/build_msvc/README.md
index e5aaf57abf..a489fb36b2 100644
--- a/build_msvc/README.md
+++ b/build_msvc/README.md
@@ -12,7 +12,8 @@ Quick Start
The minimal steps required to build Bitcoin Core with the msbuild toolchain are below. More detailed instructions are contained in the following sections.
```
-vcpkg install --triplet x64-windows-static berkeleydb boost-filesystem boost-multi-index boost-signals2 boost-test boost-thread libevent[thread] rapidcheck zeromq double-conversion
+vcpkg install --triplet x64-windows-static berkeleydb boost-filesystem boost-multi-index boost-signals2 boost-test boost-thread libevent[thread] zeromq double-conversion
+vcpkg integrate install
py -3 build_msvc\msvc-autogen.py
msbuild /m build_msvc\bitcoin.sln /p:Platform=x64 /p:Configuration=Release /t:build
```
@@ -34,7 +35,6 @@ The [external dependencies](https://github.com/bitcoin/bitcoin/blob/master/doc/d
- DoubleConversion
- libevent
- Qt5
-- RapidCheck
- ZeroMQ
Qt
@@ -56,6 +56,7 @@ The instructions below use `vcpkg` to install the dependencies.
```
PS >.\vcpkg install --triplet x64-windows-static $(Get-Content -Path build_msvc\vcpkg-packages.txt).split()
+PS >.\vcpkg integrate install
```
- Use Python to generate `*.vcxproj` from Makefile
diff --git a/build_msvc/bitcoin_config.h b/build_msvc/bitcoin_config.h
index 3178f2a3d8..c8b2fb1658 100644
--- a/build_msvc/bitcoin_config.h
+++ b/build_msvc/bitcoin_config.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
@@ -18,7 +18,7 @@
#define CLIENT_VERSION_MAJOR 0
/* Minor version */
-#define CLIENT_VERSION_MINOR 19
+#define CLIENT_VERSION_MINOR 20
/* Build revision */
#define CLIENT_VERSION_REVISION 99
@@ -47,9 +47,6 @@
/* define if the Boost library is available */
#define HAVE_BOOST /**/
-/* define if the Boost::Chrono library is available */
-#define HAVE_BOOST_CHRONO /**/
-
/* define if the Boost::Filesystem library is available */
#define HAVE_BOOST_FILESYSTEM /**/
@@ -258,12 +255,6 @@
/* Define if the visibility attribute is supported. */
#define HAVE_VISIBILITY_ATTRIBUTE 1
-/* Define this symbol if boost sleep works */
-/* #undef HAVE_WORKING_BOOST_SLEEP */
-
-/* Define this symbol if boost sleep_for works */
-#define HAVE_WORKING_BOOST_SLEEP_FOR 1
-
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
@@ -313,9 +304,6 @@
/* Define this symbol to build in assembly routines */
//#define USE_ASM 1
-/* Define this symbol if coverage is enabled */
-/* #undef USE_COVERAGE */
-
/* Define if dbus support should be compiled in */
/* #undef USE_DBUS */
diff --git a/build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in b/build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in
index adf4fa0354..6ec40461c2 100644
--- a/build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in
+++ b/build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in
@@ -8,6 +8,7 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<ItemGroup>
+ <ClCompile Include="..\..\src\util\url.cpp" />
@SOURCE_FILES@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
diff --git a/build_msvc/libleveldb/libleveldb.vcxproj b/build_msvc/libleveldb/libleveldb.vcxproj
index f855923c62..1610ae7d86 100644
--- a/build_msvc/libleveldb/libleveldb.vcxproj
+++ b/build_msvc/libleveldb/libleveldb.vcxproj
@@ -24,8 +24,6 @@
<ClCompile Include="..\..\src\leveldb\db\version_set.cc" />
<ClCompile Include="..\..\src\leveldb\db\write_batch.cc" />
<ClCompile Include="..\..\src\leveldb\helpers\memenv\memenv.cc" />
- <ClCompile Include="..\..\src\leveldb\port\port_posix_sse.cc" />
- <ClCompile Include="..\..\src\leveldb\port\port_win.cc" />
<ClCompile Include="..\..\src\leveldb\table\block.cc" />
<ClCompile Include="..\..\src\leveldb\table\block_builder.cc" />
<ClCompile Include="..\..\src\leveldb\table\filter_block.cc" />
@@ -42,7 +40,7 @@
<ClCompile Include="..\..\src\leveldb\util\comparator.cc" />
<ClCompile Include="..\..\src\leveldb\util\crc32c.cc" />
<ClCompile Include="..\..\src\leveldb\util\env.cc" />
- <ClCompile Include="..\..\src\leveldb\util\env_win.cc" />
+ <ClCompile Include="..\..\src\leveldb\util\env_windows.cc" />
<ClCompile Include="..\..\src\leveldb\util\filter_policy.cc" />
<ClCompile Include="..\..\src\leveldb\util\hash.cc" />
<ClCompile Include="..\..\src\leveldb\util\histogram.cc" />
@@ -51,11 +49,11 @@
<ClCompile Include="..\..\src\leveldb\util\status.cc" />
</ItemGroup>
<ItemDefinitionGroup>
- <ClCompile>
- <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;LEVELDB_PLATFORM_WINDOWS;LEVELDB_ATOMIC_PRESENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <DisableSpecificWarnings>4244;4267;4312;</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>..\..\src\leveldb;..\..\src\leveldb\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
+ <ClCompile>
+ <PreprocessorDefinitions>HAVE_CRC32C=0;HAVE_SNAPPY=0;__STDC_LIMIT_MACROS;LEVELDB_IS_BIG_ENDIAN=0;_UNICODE;UNICODE;_CRT_NONSTDC_NO_DEPRECATE;LEVELDB_PLATFORM_WINDOWS;LEVELDB_ATOMIC_PRESENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <DisableSpecificWarnings>4244;4267;4312;4722;</DisableSpecificWarnings>
+ <AdditionalIncludeDirectories>..\..\src\leveldb;..\..\src\leveldb\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/build_msvc/testconsensus/testconsensus.cpp b/build_msvc/testconsensus/testconsensus.cpp
index 571d19957f..5fdd97dc78 100644
--- a/build_msvc/testconsensus/testconsensus.cpp
+++ b/build_msvc/testconsensus/testconsensus.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-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.
diff --git a/build_msvc/vcpkg-packages.txt b/build_msvc/vcpkg-packages.txt
index 27e2bbdcde..307f295f08 100644
--- a/build_msvc/vcpkg-packages.txt
+++ b/build_msvc/vcpkg-packages.txt
@@ -1 +1 @@
-berkeleydb boost-filesystem boost-multi-index boost-signals2 boost-test boost-thread libevent[thread] rapidcheck zeromq double-conversion \ No newline at end of file
+berkeleydb boost-filesystem boost-multi-index boost-signals2 boost-test boost-thread libevent[thread] zeromq double-conversion \ No newline at end of file
diff --git a/ci/README.md b/ci/README.md
index 880e49b459..d2ea255b4b 100644
--- a/ci/README.md
+++ b/ci/README.md
@@ -13,7 +13,7 @@ If the repository is not a fresh git clone, you might have to clean files from p
The ci needs to perform various sysadmin tasks such as installing packages or writing to the user's home directory.
While most of the actions are done inside a docker container, this is not possible for all. Thus, cache directories,
-such as the depends cache or ccache, are mounted as read-write into the docker container. While it should be fine to run
+such as the depends cache, previous release binaries, or ccache, are mounted as read-write into the docker container. While it should be fine to run
the ci system locally on you development box, the ci scripts can generally be assumed to have received less review and
testing compared to other parts of the codebase. If you want to keep the work tree clean, you might want to run the ci
system in a virtual machine with a Linux operating system of your choice.
diff --git a/ci/lint/06_script.sh b/ci/lint/06_script.sh
index ae8122f9af..003bdf3c29 100755
--- a/ci/lint/06_script.sh
+++ b/ci/lint/06_script.sh
@@ -14,6 +14,7 @@ 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
test/lint/git-subtree-check.sh src/leveldb
+test/lint/git-subtree-check.sh src/crc32c
test/lint/check-doc.py
test/lint/check-rpc-mappings.py .
test/lint/lint-all.sh
diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh
index a008d51523..dae61c5e34 100755
--- a/ci/test/00_setup_env.sh
+++ b/ci/test/00_setup_env.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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.
@@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8
# The root dir.
# The ci system copies this folder.
-# This is where the build is done (depends and dist).
+# This is where the depends build is done.
BASE_ROOT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../../ >/dev/null 2>&1 && pwd )
export BASE_ROOT_DIR
@@ -24,7 +24,7 @@ echo "Fallback to default values in env (if not yet set)"
export MAKEJOBS=${MAKEJOBS:--j4}
# A folder for the ci system to put temporary files (ccache, datadirs for tests, ...)
# This folder only exists on the ci host.
-export BASE_SCRATCH_DIR=${BASE_SCRATCH_DIR:-$BASE_ROOT_DIR/ci/scratch/}
+export BASE_SCRATCH_DIR=${BASE_SCRATCH_DIR:-$BASE_ROOT_DIR/ci/scratch}
# What host to compile for. See also ./depends/README.md
# Tests that need cross-compilation export the appropriate HOST.
# Tests that run natively guess the host
@@ -33,7 +33,9 @@ export HOST=${HOST:-$("$BASE_ROOT_DIR/depends/config.guess")}
export USE_BUSY_BOX=${USE_BUSY_BOX:-false}
export RUN_UNIT_TESTS=${RUN_UNIT_TESTS:-true}
export RUN_FUNCTIONAL_TESTS=${RUN_FUNCTIONAL_TESTS:-true}
+export TEST_PREVIOUS_RELEASES=${TEST_PREVIOUS_RELEASES:-false}
export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false}
+export CONTAINER_NAME=${CONTAINER_NAME:-ci_unnamed}
export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:18.04}
# Randomize test order.
# See https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/utf_reference/rt_param_reference/random.html
@@ -47,12 +49,14 @@ export CCACHE_DIR=${CCACHE_DIR:-$BASE_SCRATCH_DIR/.ccache}
# The depends dir.
# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
-# Folder where the build is done (bin and lib).
+# Folder where the build result is put (bin and lib).
export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_SCRATCH_DIR/out/$HOST}
+# Folder where the build is done (dist and out-of-tree build).
+export BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_SCRATCH_DIR/build}
+export PREVIOUS_RELEASES_DIR=${PREVIOUS_RELEASES_DIR:-$BASE_ROOT_DIR/releases/$HOST}
export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks}
-export WINEDEBUG=${WINEDEBUG:-fixme-all}
export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3 rsync git procps}
export GOAL=${GOAL:-install}
export DIR_QA_ASSETS=${DIR_QA_ASSETS:-${BASE_SCRATCH_DIR}/qa-assets}
export PATH=${BASE_ROOT_DIR}/ci/retry:$PATH
-export CI_RETRY_EXE=${CI_RETRY_EXE:retry}
+export CI_RETRY_EXE=${CI_RETRY_EXE:-"retry --"}
diff --git a/ci/test/00_setup_env_arm.sh b/ci/test/00_setup_env_arm.sh
index 2a522f5a8f..b70a581532 100644
--- a/ci/test/00_setup_env_arm.sh
+++ b/ci/test/00_setup_env_arm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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.
@@ -16,6 +16,7 @@ if [ -n "$QEMU_USER_CMD" ]; then
# Likely cross-compiling, so install the needed gcc and qemu-user
export PACKAGES="$PACKAGES qemu-user"
fi
+export CONTAINER_NAME=ci_arm_linux
# Use debian to avoid 404 apt errors when cross compiling
export DOCKER_NAME_TAG="debian:buster"
export USE_BUSY_BOX=true
@@ -24,4 +25,4 @@ export RUN_FUNCTIONAL_TESTS=true
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"
+export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CXXFLAGS=-Wno-psabi --enable-werror"
diff --git a/ci/test/00_setup_env_i686_centos.sh b/ci/test/00_setup_env_i686_centos.sh
index b875dceef0..5688799f9e 100644
--- a/ci/test/00_setup_env_i686_centos.sh
+++ b/ci/test/00_setup_env_i686_centos.sh
@@ -7,6 +7,7 @@
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 GOAL="install"
diff --git a/ci/test/00_setup_env_mac.sh b/ci/test/00_setup_env_mac.sh
index af166b6ca7..a4dc54d1c1 100644
--- a/ci/test/00_setup_env_mac.sh
+++ b/ci/test/00_setup_env_mac.sh
@@ -1,14 +1,15 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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
+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 OSX_SDK=10.11
+export OSX_SDK=10.14
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export GOAL="deploy"
diff --git a/ci/test/00_setup_env_mac_host.sh b/ci/test/00_setup_env_mac_host.sh
index 0b437a723f..982e38daee 100644
--- a/ci/test/00_setup_env_mac_host.sh
+++ b/ci/test/00_setup_env_mac_host.sh
@@ -1,19 +1,16 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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
export HOST=x86_64-apple-darwin16
-export BREW_PACKAGES="automake berkeley-db4 libtool boost miniupnpc pkg-config qt qrencode python3 ccache zeromq"
export PIP_PACKAGES="zmq"
-export RUN_CI_ON_HOST=true
-export RUN_UNIT_TESTS=true
-export RUN_FUNCTIONAL_TESTS=false
export GOAL="install"
export BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --enable-werror"
+export TEST_RUNNER_EXTRA="wallet_disable" # Only run wallet_disable as a smoke test, see https://github.com/bitcoin/bitcoin/pull/17240#issuecomment-546022121 why the other tests are disabled
# Run without depends
export NO_DEPENDS=1
export OSX_SDK=""
diff --git a/ci/test/00_setup_env_native_asan.sh b/ci/test/00_setup_env_native_asan.sh
index 2ffd3c5107..28c63f1cf6 100644
--- a/ci/test/00_setup_env_native_asan.sh
+++ b/ci/test/00_setup_env_native_asan.sh
@@ -1,12 +1,13 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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
-export PACKAGES="clang-8 llvm-8 python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev"
+export CONTAINER_NAME=ci_native_asan
+export PACKAGES="clang-8 llvm-8 python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev"
# Use clang-8 instead of default clang (which is clang-6 on Bionic) to avoid spurious segfaults when running on ppc64le
export NO_DEPENDS=1
export GOAL="install"
diff --git a/ci/test/00_setup_env_native_fuzz.sh b/ci/test/00_setup_env_native_fuzz.sh
index b0405bb762..43ee219ef9 100644
--- a/ci/test/00_setup_env_native_fuzz.sh
+++ b/ci/test/00_setup_env_native_fuzz.sh
@@ -1,16 +1,17 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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
-export PACKAGES="clang-8 llvm-8 python3 libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev"
+export DOCKER_NAME_TAG="ubuntu:20.04"
+export CONTAINER_NAME=ci_native_fuzz
+export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev"
export NO_DEPENDS=1
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export RUN_FUZZ_TESTS=true
export GOAL="install"
-export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=clang-8 CXX=clang++-8"
-# Use clang-8, instead of default clang on bionic, which is clang-6 and does not come with libfuzzer on aarch64
+export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=clang CXX=clang++"
diff --git a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh
new file mode 100644
index 0000000000..c27d525003
--- /dev/null
+++ b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2019-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
+
+export DOCKER_NAME_TAG="ubuntu:20.04"
+export CONTAINER_NAME=ci_native_fuzz_valgrind
+export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev valgrind"
+export NO_DEPENDS=1
+export RUN_UNIT_TESTS=false
+export RUN_FUNCTIONAL_TESTS=false
+export RUN_FUZZ_TESTS=true
+export FUZZ_TESTS_CONFIG="--valgrind"
+export GOAL="install"
+export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer CC=clang CXX=clang++"
diff --git a/ci/test/00_setup_env_native_nowallet.sh b/ci/test/00_setup_env_native_nowallet.sh
index 53348559be..9c2be4cfac 100644
--- a/ci/test/00_setup_env_native_nowallet.sh
+++ b/ci/test/00_setup_env_native_nowallet.sh
@@ -1,11 +1,12 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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
+export CONTAINER_NAME=ci_native_nowallet
export PACKAGES="python3-zmq"
export DEP_OPTS="NO_WALLET=1"
export GOAL="install"
diff --git a/ci/test/00_setup_env_native_qt5.sh b/ci/test/00_setup_env_native_qt5.sh
index 622ec3cfe1..4dedea23bc 100644
--- a/ci/test/00_setup_env_native_qt5.sh
+++ b/ci/test/00_setup_env_native_qt5.sh
@@ -1,13 +1,17 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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
+export CONTAINER_NAME=ci_native_qt5
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="--coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash
+export RUN_UNIT_TESTS_SEQUENTIAL="true"
+export RUN_UNIT_TESTS="false"
export GOAL="install"
-export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\""
+export TEST_PREVIOUS_RELEASES=true
+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\""
diff --git a/ci/test/00_setup_env_native_tsan.sh b/ci/test/00_setup_env_native_tsan.sh
index e9b7a7bba1..73ab5eebb6 100644
--- a/ci/test/00_setup_env_native_tsan.sh
+++ b/ci/test/00_setup_env_native_tsan.sh
@@ -1,17 +1,14 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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
+export CONTAINER_NAME=ci_native_tsan
export DOCKER_NAME_TAG=ubuntu:16.04
-export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev"
+export PACKAGES="clang-8 llvm-8 python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev"
export NO_DEPENDS=1
export GOAL="install"
-export BITCOIN_CONFIG="--enable-zmq --disable-wallet --with-gui=qt5 CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' --with-sanitizers=thread --disable-hardening --disable-asm CC=clang CXX=clang++"
-
-# xenial comes with old clang versions that can not parse the sanitizer suppressions files
-# Remove unparseable lines as a hacky workaround
-sed -i '/^implicit-/d' "${BASE_ROOT_DIR}/test/sanitizer_suppressions/ubsan"
+export BITCOIN_CONFIG="--enable-zmq --disable-wallet --with-gui=qt5 CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' --with-sanitizers=thread --disable-hardening --disable-asm CC=clang-8 CXX=clang++-8"
diff --git a/ci/test/00_setup_env_native_valgrind.sh b/ci/test/00_setup_env_native_valgrind.sh
index 906ffd7d79..153a781b0a 100644
--- a/ci/test/00_setup_env_native_valgrind.sh
+++ b/ci/test/00_setup_env_native_valgrind.sh
@@ -1,15 +1,19 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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
-export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev"
+export CONTAINER_NAME=ci_native_valgrind
+export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev"
export USE_VALGRIND=1
export NO_DEPENDS=1
-export TEST_RUNNER_EXTRA="p2p_segwit.py" # Only run one test for now. TODO enable all and bump timeouts
-export RUN_FUNCTIONAL_TESTS=true
+if [[ "${TRAVIS}" == "true" && "${TRAVIS_REPO_SLUG}" != "bitcoin/bitcoin" ]]; then
+ export TEST_RUNNER_EXTRA="wallet_disable" # Only run wallet_disable as a smoke test to not hit the 50 min travis time limit
+else
+ export TEST_RUNNER_EXTRA="--exclude rpc_bind --factor=2" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547
+fi
export GOAL="install"
export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no CC=clang CXX=clang++" # TODO enable GUI
diff --git a/ci/test/00_setup_env_s390x.sh b/ci/test/00_setup_env_s390x.sh
index 6452feb5f2..c180d023de 100644
--- a/ci/test/00_setup_env_s390x.sh
+++ b/ci/test/00_setup_env_s390x.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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.
@@ -17,6 +17,7 @@ if [ -n "$QEMU_USER_CMD" ]; then
export PACKAGES="$PACKAGES g++-s390x-linux-gnu qemu-user libc6:s390x libstdc++6:s390x libfontconfig1:s390x libxcb1:s390x"
fi
# Use debian to avoid 404 apt errors
+export CONTAINER_NAME=ci_s390x
export DOCKER_NAME_TAG="debian:buster"
export RUN_UNIT_TESTS=true
export RUN_FUNCTIONAL_TESTS=true
diff --git a/ci/test/00_setup_env_s390x_host.sh b/ci/test/00_setup_env_s390x_host.sh
new file mode 100644
index 0000000000..3e31867f2f
--- /dev/null
+++ b/ci/test/00_setup_env_s390x_host.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2019-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
+
+export HOST=s390x-linux-gnu
+export NO_DEPENDS=1
+export BITCOIN_CONFIG="--with-incompatible-bdb --enable-reduce-exports"
+export RUN_UNIT_TESTS=true
+export RUN_FUNCTIONAL_TESTS=true
+export GOAL="install"
diff --git a/ci/test/00_setup_env_win64.sh b/ci/test/00_setup_env_win64.sh
index 1e04c4287a..8f0c62a1a6 100644
--- a/ci/test/00_setup_env_win64.sh
+++ b/ci/test/00_setup_env_win64.sh
@@ -1,11 +1,12 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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
+export CONTAINER_NAME=ci_win64
export HOST=x86_64-w64-mingw32
export PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64"
export RUN_FUNCTIONAL_TESTS=false
diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh
index 4d5859e4d3..5dbf1b82f1 100755
--- a/ci/test/04_install.sh
+++ b/ci/test/04_install.sh
@@ -14,38 +14,19 @@ if [[ $QEMU_USER_CMD == qemu-s390* ]]; then
fi
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
- set +o errexit
- pushd /usr/local/Homebrew || exit 1
- git reset --hard origin/master
- popd || exit 1
- set -o errexit
- ${CI_RETRY_EXE} brew unlink python@2
- ${CI_RETRY_EXE} brew update
- # brew upgrade returns an error if any of the packages is already up to date
- # Failure is safe to ignore, unless we really need an update.
- brew upgrade $BREW_PACKAGES || true
-
- # install new packages (brew install returns an error if already installed)
- for i in $BREW_PACKAGES; do
- if ! brew list | grep -q $i; then
- ${CI_RETRY_EXE} brew install $i
- fi
- done
-
export PATH="/usr/local/opt/ccache/libexec:$PATH"
-
${CI_RETRY_EXE} pip3 install $PIP_PACKAGES
-
fi
-mkdir -p "${BASE_SCRATCH_DIR}"
+# Create folders that are mounted into the docker
mkdir -p "${CCACHE_DIR}"
+mkdir -p "${PREVIOUS_RELEASES_DIR}"
export ASAN_OPTIONS="detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1"
export LSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/lsan"
export TSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/tsan: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_|WINEDEBUG|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL|(ASAN|LSAN|TSAN|UBSAN)_OPTIONS)' | tee /tmp/env
+env | grep -E '^(BITCOIN_CONFIG|BASE_|QEMU_|CCACHE_|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL|(ASAN|LSAN|TSAN|UBSAN)_OPTIONS|TEST_PREVIOUS_RELEASES|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)
@@ -54,7 +35,7 @@ fi
export P_CI_DIR="$PWD"
-if [ -z "$RUN_CI_ON_HOST" ]; then
+if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
echo "Creating $DOCKER_NAME_TAG container to run in"
${CI_RETRY_EXE} docker pull "$DOCKER_NAME_TAG"
@@ -62,8 +43,10 @@ if [ -z "$RUN_CI_ON_HOST" ]; then
--mount type=bind,src=$BASE_ROOT_DIR,dst=/ro_base,readonly \
--mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR \
--mount type=bind,src=$DEPENDS_DIR,dst=$DEPENDS_DIR \
+ --mount type=bind,src=$PREVIOUS_RELEASES_DIR,dst=$PREVIOUS_RELEASES_DIR \
-w $BASE_ROOT_DIR \
--env-file /tmp/env \
+ --name $CONTAINER_NAME \
$DOCKER_NAME_TAG)
DOCKER_EXEC () {
@@ -75,6 +58,7 @@ else
bash -c "export PATH=$BASE_SCRATCH_DIR/bins/:\$PATH && cd $P_CI_DIR && $*"
}
fi
+export -f DOCKER_EXEC
if [ -n "$DPKG_ADD_ARCH" ]; then
DOCKER_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH"
@@ -83,7 +67,7 @@ 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
-elif [ "$TRAVIS_OS_NAME" != "osx" ]; then
+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
@@ -94,18 +78,21 @@ if [ "$TRAVIS_OS_NAME" == "osx" ]; then
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
if [ ! -d ${DIR_QA_ASSETS} ]; then
+ if [ "$RUN_FUZZ_TESTS" = "true" ]; then
DOCKER_EXEC git clone https://github.com/bitcoin-core/qa-assets ${DIR_QA_ASSETS}
+ fi
fi
export DIR_FUZZ_IN=${DIR_QA_ASSETS}/fuzz_seed_corpus/
DOCKER_EXEC mkdir -p "${BASE_SCRATCH_DIR}/sanitizer-output/"
-if [ -z "$RUN_CI_ON_HOST" ]; then
+if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
echo "Create $BASE_ROOT_DIR"
DOCKER_EXEC rsync -a /ro_base/ $BASE_ROOT_DIR
fi
diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh
index d8aa5c87a2..ab9d673101 100755
--- a/ci/test/05_before_script.sh
+++ b/ci/test/05_before_script.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
@@ -26,7 +26,7 @@ if [[ $HOST = *-mingw32 ]]; then
fi
if [ -z "$NO_DEPENDS" ]; then
if [[ $DOCKER_NAME_TAG == centos* ]]; then
- # CentOS has problems building the depends if the config shell is not explicitely set
+ # 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"
@@ -35,3 +35,8 @@ if [ -z "$NO_DEPENDS" ]; then
fi
DOCKER_EXEC $SHELL_OPTS make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
fi
+if [ "$TEST_PREVIOUS_RELEASES" = "true" ]; then
+ BEGIN_FOLD previous-versions
+ DOCKER_EXEC contrib/devtools/previous_release.sh -b -t "$PREVIOUS_RELEASES_DIR" v0.15.2 v0.16.3 v0.17.1 v0.18.1 v0.19.0.1
+ END_FOLD
+fi
diff --git a/ci/test/06_script_a.sh b/ci/test/06_script_a.sh
index b6043cd61e..b68cd9d3f8 100755
--- a/ci/test/06_script_a.sh
+++ b/ci/test/06_script_a.sh
@@ -1,15 +1,13 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
export LC_ALL=C.UTF-8
BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$DEPENDS_DIR/$HOST --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib"
-if [ -z "$NO_DEPENDS" ]; then
- DOCKER_EXEC ccache --max-size=$CCACHE_SIZE
-fi
+DOCKER_EXEC "ccache --zero-stats --max-size=$CCACHE_SIZE"
BEGIN_FOLD autogen
if [ -n "$CONFIG_SHELL" ]; then
@@ -19,20 +17,18 @@ else
fi
END_FOLD
-DOCKER_EXEC mkdir -p build
-export P_CI_DIR="$P_CI_DIR/build"
+DOCKER_EXEC mkdir -p "${BASE_BUILD_DIR}"
+export P_CI_DIR="${BASE_BUILD_DIR}"
BEGIN_FOLD configure
-DOCKER_EXEC ../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( (DOCKER_EXEC cat config.log) && false)
+DOCKER_EXEC "${BASE_ROOT_DIR}/configure" --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( (DOCKER_EXEC cat config.log) && false)
END_FOLD
BEGIN_FOLD distdir
-# Create folder on host and docker, so that `cd` works
-mkdir -p "bitcoin-$HOST"
DOCKER_EXEC make distdir VERSION=$HOST
END_FOLD
-export P_CI_DIR="$P_CI_DIR/bitcoin-$HOST"
+export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST"
BEGIN_FOLD configure
DOCKER_EXEC ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( (DOCKER_EXEC cat config.log) && false)
@@ -44,3 +40,9 @@ trap 'DOCKER_EXEC "cat ${BASE_SCRATCH_DIR}/sanitizer-output/* 2> /dev/null"' ERR
BEGIN_FOLD build
DOCKER_EXEC make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && DOCKER_EXEC make $GOAL V=1 ; false )
END_FOLD
+
+BEGIN_FOLD cache_stats
+DOCKER_EXEC "ccache --version | head -n 1 && ccache --show-stats"
+DOCKER_EXEC du -sh "${DEPENDS_DIR}"/*/
+DOCKER_EXEC du -sh "${PREVIOUS_RELEASES_DIR}"
+END_FOLD
diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh
index 537493a710..c8542862f2 100755
--- a/ci/test/06_script_b.sh
+++ b/ci/test/06_script_b.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
@@ -21,13 +21,20 @@ if [ -n "$USE_VALGRIND" ]; then
END_FOLD
fi
+bash -c "${CI_WAIT}" & # Print dots in case the tests take a long time to run
+
if [ "$RUN_UNIT_TESTS" = "true" ]; then
BEGIN_FOLD unit-tests
- bash -c "${CI_WAIT}" & # Print dots in case the unit tests take a long time to run
DOCKER_EXEC 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 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
+
if [ "$RUN_FUNCTIONAL_TESTS" = "true" ]; then
BEGIN_FOLD functional-tests
DOCKER_EXEC test/functional/test_runner.py --ci $MAKEJOBS --tmpdirprefix "${BASE_SCRATCH_DIR}/test_runner/" --ansi --combinedlogslen=4000 ${TEST_RUNNER_EXTRA} --quiet --failfast
@@ -36,6 +43,6 @@ fi
if [ "$RUN_FUZZ_TESTS" = "true" ]; then
BEGIN_FOLD fuzz-tests
- DOCKER_EXEC test/fuzz/test_runner.py -l DEBUG ${DIR_FUZZ_IN}
+ DOCKER_EXEC test/fuzz/test_runner.py ${FUZZ_TESTS_CONFIG} -l DEBUG ${DIR_FUZZ_IN}
END_FOLD
fi
diff --git a/ci/test/wrap-qemu.sh b/ci/test/wrap-qemu.sh
index f1d3088748..be7d7fcc1f 100755
--- a/ci/test/wrap-qemu.sh
+++ b/ci/test/wrap-qemu.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2018 The Bitcoin Core developers
+# Copyright (c) 2018-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.
diff --git a/configure.ac b/configure.ac
index 18f3104acb..b681f3f6de 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
AC_PREREQ([2.69])
define(_CLIENT_VERSION_MAJOR, 0)
-define(_CLIENT_VERSION_MINOR, 19)
+define(_CLIENT_VERSION_MINOR, 20)
define(_CLIENT_VERSION_REVISION, 99)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_RC, 0)
@@ -36,14 +36,14 @@ dnl faketime breaks configure and is only needed for make. Disable it here.
unset FAKETIME
dnl Automake init set-up and checks
-AM_INIT_AUTOMAKE([no-define subdir-objects foreign])
+AM_INIT_AUTOMAKE([1.13 no-define subdir-objects foreign])
dnl faketime messes with timestamps and causes configure to be re-run.
dnl --disable-maintainer-mode can be used to bypass this.
AM_MAINTAINER_MODE([enable])
dnl make the compilation flags quiet unless V=1 is used
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+AM_SILENT_RULES([yes])
dnl Compiler checks (here before libtool).
if test "x${CXXFLAGS+set}" = "xset"; then
@@ -61,8 +61,20 @@ case $host in
lt_cv_deplibs_check_method="pass_all"
;;
esac
-dnl Require C++11 compiler (no GNU extensions)
-AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory], [nodefault])
+
+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; then
+ AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
+else
+ AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
+fi
+
dnl Check if -latomic is required for <std::atomic>
CHECK_ATOMIC
@@ -134,12 +146,6 @@ AC_ARG_ENABLE(gui-tests,
[use_gui_tests=$enableval],
[use_gui_tests=$use_tests])
-AC_ARG_WITH([rapidcheck],
- [AS_HELP_STRING([--with-rapidcheck],
- [enable RapidCheck property-based tests (default is yes if librapidcheck is found)])],
- [use_rapidcheck=$withval],
- [use_rapidcheck=auto])
-
AC_ARG_ENABLE(bench,
AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
[use_bench=$enableval],
@@ -262,6 +268,13 @@ AC_ARG_ENABLE([gprof],
[enable_gprof=$enableval],
[enable_gprof=no])
+dnl Pass compiler & linker flags that make builds deterministic
+AC_ARG_ENABLE([determinism],
+ [AS_HELP_STRING([--enable-determinism],
+ [Enable compilation flags that make builds deterministic (default is no)])],
+ [enable_determinism=$enableval],
+ [enable_determinism=no])
+
dnl Turn warnings into errors
AC_ARG_ENABLE([werror],
[AS_HELP_STRING([--enable-werror],
@@ -330,6 +343,7 @@ if test "x$enable_werror" = "xyes"; then
AX_CHECK_COMPILE_FLAG([-Werror=thread-safety-analysis],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=thread-safety-analysis"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Werror=unused-variable],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=unused-variable"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Werror=date-time],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=date-time"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Werror=return-type],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=return-type"],,[[$CXXFLAG_WERROR]])
fi
if test "x$CXXFLAGS_overridden" = "xno"; then
@@ -355,7 +369,7 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]])
fi
-enable_hwcrc32=no
+enable_sse42=no
enable_sse41=no
enable_avx2=no
enable_shani=no
@@ -365,6 +379,8 @@ if test "x$use_asm" = "xyes"; then
dnl Check for optional instruction set support. Enabling these does _not_ imply that all code will
dnl be compiled with them, rather that specific objects/libs may use them after checking for runtime
dnl compatibility.
+
+dnl x86
AX_CHECK_COMPILE_FLAG([-msse4.2],[[SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-msse4.1],[[SSE41_CXXFLAGS="-msse4.1"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-mavx -mavx2],[[AVX2_CXXFLAGS="-mavx -mavx2"]],,[[$CXXFLAG_WERROR]])
@@ -372,7 +388,7 @@ AX_CHECK_COMPILE_FLAG([-msse4 -msha],[[SHANI_CXXFLAGS="-msse4 -msha"]],,[[$CXXFL
TEMP_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS"
-AC_MSG_CHECKING(for assembler crc32 support)
+AC_MSG_CHECKING(for SSE4.2 intrinsics)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdint.h>
#if defined(_MSC_VER)
@@ -387,7 +403,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
l = _mm_crc32_u64(l, 0);
return l;
]])],
- [ AC_MSG_RESULT(yes); enable_hwcrc32=yes],
+ [ AC_MSG_RESULT(yes); enable_sse42=yes],
[ AC_MSG_RESULT(no)]
)
CXXFLAGS="$TEMP_CXXFLAGS"
@@ -439,6 +455,24 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
)
CXXFLAGS="$TEMP_CXXFLAGS"
+# ARM
+AX_CHECK_COMPILE_FLAG([-march=armv8-a+crc+crypto],[[ARM_CRC_CXXFLAGS="-march=armv8-a+crc+crypto"]],,[[$CXXFLAG_WERROR]])
+
+TEMP_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS $ARM_CRC_CXXFLAGS"
+AC_MSG_CHECKING(for ARM CRC32 intrinsics)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <arm_acle.h>
+ #include <arm_neon.h>
+ ]],[[
+ __crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0);
+ vmull_p64(0, 0);
+ ]])],
+ [ AC_MSG_RESULT(yes); enable_arm_crc=yes; ],
+ [ AC_MSG_RESULT(no)]
+)
+CXXFLAGS="$TEMP_CXXFLAGS"
+
fi
CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
@@ -517,7 +551,6 @@ case $host in
fi
CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -D_WIN32_WINNT=0x0601"
- LEVELDB_TARGET_FLAGS="-DOS_WINDOWS"
if test "x$CXXFLAGS_overridden" = "xno"; then
CXXFLAGS="$CXXFLAGS -w"
fi
@@ -533,7 +566,6 @@ case $host in
;;
*darwin*)
TARGET_OS=darwin
- LEVELDB_TARGET_FLAGS="-DOS_MACOSX"
if test x$cross_compiling != xyes; then
BUILD_OS=darwin
AC_PATH_PROGS([RSVG_CONVERT], [rsvg-convert rsvg],rsvg-convert)
@@ -585,35 +617,9 @@ case $host in
*android*)
dnl make sure android stays above linux for hosts like *linux-android*
TARGET_OS=android
- LEVELDB_TARGET_FLAGS="-DOS_ANDROID"
;;
*linux*)
TARGET_OS=linux
- LEVELDB_TARGET_FLAGS="-DOS_LINUX"
- ;;
- *kfreebsd*)
- LEVELDB_TARGET_FLAGS="-DOS_KFREEBSD"
- ;;
- *freebsd*)
- LEVELDB_TARGET_FLAGS="-DOS_FREEBSD"
- ;;
- *openbsd*)
- LEVELDB_TARGET_FLAGS="-DOS_OPENBSD"
- ;;
- *netbsd*)
- LEVELDB_TARGET_FLAGS="-DOS_NETBSD"
- ;;
- *dragonfly*)
- LEVELDB_TARGET_FLAGS="-DOS_DRAGONFLYBSD"
- ;;
- *solaris*)
- LEVELDB_TARGET_FLAGS="-DOS_SOLARIS"
- ;;
- *hpux*)
- LEVELDB_TARGET_FLAGS="-DOS_HPUX"
- ;;
- *)
- AC_MSG_ERROR(Cannot build leveldb for $host. Please file a bug report.)
;;
esac
@@ -649,7 +655,6 @@ if test x$use_lcov = xyes; then
[AC_MSG_ERROR("lcov testing requested but --coverage linker flag does not work")])
AX_CHECK_COMPILE_FLAG([--coverage],[CXXFLAGS="$CXXFLAGS --coverage"],
[AC_MSG_ERROR("lcov testing requested but --coverage flag does not work")])
- AC_DEFINE(USE_COVERAGE, 1, [Define this symbol if coverage is enabled])
CXXFLAGS="$CXXFLAGS -Og"
fi
@@ -682,8 +687,6 @@ if test x$ac_cv_sys_large_files != x &&
CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files"
fi
-AX_CHECK_LINK_FLAG([[-Wl,--large-address-aware]], [LDFLAGS="$LDFLAGS -Wl,--large-address-aware"])
-
AX_GCC_FUNC_ATTRIBUTE([visibility])
AX_GCC_FUNC_ATTRIBUTE([dllexport])
AX_GCC_FUNC_ATTRIBUTE([dllimport])
@@ -766,13 +769,21 @@ if test x$use_hardening != xno; then
esac
fi
-dnl this flag screws up non-darwin gcc even when the check fails. special-case it.
+dnl These flags are specific to ld64, and may cause issues with other linkers.
+dnl For example: GNU ld will intepret -dead_strip as -de and then try and use
+dnl "ad_strip" as the symbol for the entry point.
if test x$TARGET_OS = xdarwin; then
AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"])
AX_CHECK_LINK_FLAG([[-Wl,-dead_strip_dylibs]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip_dylibs"])
AX_CHECK_LINK_FLAG([[-Wl,-bind_at_load]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-bind_at_load"])
fi
+if test x$enable_determinism = xyes; then
+ if test x$TARGET_OS = xwindows; then
+ AX_CHECK_LINK_FLAG([[-Wl,--no-insert-timestamp]], [LDFLAGS="$LDFLAGS -Wl,--no-insert-timestamp"])
+ fi
+fi
+
AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h sys/sysctl.h vm/vm_param.h sys/vmmeter.h sys/resources.h])
dnl FD_ZERO may be dependent on a declaration of memcpy, e.g. in SmartOS
@@ -847,6 +858,22 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <malloc.h>]],
[ AC_MSG_RESULT(no)]
)
+dnl Check for posix_fallocate
+AC_MSG_CHECKING(for posix_fallocate)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ // same as in src/util/system.cpp
+ #ifdef __linux__
+ #ifdef _POSIX_C_SOURCE
+ #undef _POSIX_C_SOURCE
+ #endif
+ #define _POSIX_C_SOURCE 200112L
+ #endif // __linux__
+ #include <fcntl.h>]],
+ [[ int f = posix_fallocate(0, 0, 0); ]])],
+ [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_POSIX_FALLOCATE, 1,[Define this symbol if you have posix_fallocate]) ],
+ [ AC_MSG_RESULT(no)]
+)
+
AC_MSG_CHECKING([for visibility attribute])
AC_LINK_IFELSE([AC_LANG_SOURCE([
int foo_def( void ) __attribute__((visibility("default")));
@@ -864,6 +891,9 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
]
)
+dnl thread_local is currently disabled when building with glibc back compat.
+dnl Our minimum supported glibc is 2.17, however support for thread_local
+dnl did not arrive in glibc until 2.18.
if test "x$use_thread_local" = xyes || { test "x$use_thread_local" = xauto && test "x$use_glibc_compat" = xno; }; then
TEMP_LDFLAGS="$LDFLAGS"
LDFLAGS="$TEMP_LDFLAGS $PTHREAD_CFLAGS"
@@ -885,11 +915,6 @@ if test "x$use_thread_local" = xyes || { test "x$use_thread_local" = xauto && te
dnl https://gist.github.com/jamesob/fe9a872051a88b2025b1aa37bfa98605
AC_MSG_RESULT(no)
;;
- *darwin*)
- dnl TODO enable thread_local on later versions of Darwin where it is
- dnl supported (per https://stackoverflow.com/a/29929949)
- AC_MSG_RESULT(no)
- ;;
*freebsd*)
dnl FreeBSD's implementation of thread_local is also buggy (per
dnl https://groups.google.com/d/msg/bsdmailinglist/22ncTZAbDp4/Dii_pII5AwAJ)
@@ -908,6 +933,22 @@ if test "x$use_thread_local" = xyes || { test "x$use_thread_local" = xauto && te
LDFLAGS="$TEMP_LDFLAGS"
fi
+dnl check for gmtime_r(), fallback to gmtime_s() if that is unavailable
+dnl fail if neither are available.
+AC_MSG_CHECKING(for gmtime_r)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <ctime>]],
+ [[ gmtime_r((const time_t *) nullptr, (struct tm *) nullptr); ]])],
+ [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_GMTIME_R, 1, [Define this symbol if gmtime_r is available]) ],
+ [ AC_MSG_RESULT(no);
+ AC_MSG_CHECKING(for gmtime_s);
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <ctime>]],
+ [[ gmtime_s((struct tm *) nullptr, (const time_t *) nullptr); ]])],
+ [ AC_MSG_RESULT(yes)],
+ [ AC_MSG_RESULT(no); AC_MSG_ERROR(Both gmtime_r and gmtime_s are unavailable) ]
+ )
+ ]
+)
+
dnl Check for different ways of gathering OS randomness
AC_MSG_CHECKING(for Linux getrandom syscall)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>
@@ -936,11 +977,10 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>
AC_MSG_CHECKING(for sysctl)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <sys/sysctl.h>]],
- [[ static const int name[2] = {CTL_KERN, KERN_VERSION};
- #ifdef __linux__
+ [[ #ifdef __linux__
#error "Don't use sysctl on Linux, it's deprecated even when it works"
#endif
- sysctl(name, 2, nullptr, nullptr, nullptr, 0); ]])],
+ sysctl(nullptr, 2, nullptr, nullptr, nullptr, 0); ]])],
[ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSCTL, 1,[Define this symbol if the BSD sysctl() is available]) ],
[ AC_MSG_RESULT(no)]
)
@@ -948,7 +988,10 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
AC_MSG_CHECKING(for sysctl KERN_ARND)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <sys/sysctl.h>]],
- [[ static const int name[2] = {CTL_KERN, KERN_ARND};
+ [[ #ifdef __linux__
+ #error "Don't use sysctl on Linux, it's deprecated even when it works"
+ #endif
+ static int name[2] = {CTL_KERN, KERN_ARND};
sysctl(name, 2, nullptr, nullptr, nullptr, 0); ]])],
[ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSCTL_ARND, 1,[Define this symbol if the BSD sysctl(KERN_ARND) is available]) ],
[ AC_MSG_RESULT(no)]
@@ -962,6 +1005,72 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdint.h>
[ AC_MSG_RESULT(no)]
)
+dnl LevelDB platform checks
+AC_MSG_CHECKING(for fdatasync)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>]],
+ [[ fdatasync(0); ]])],
+ [ AC_MSG_RESULT(yes); HAVE_FDATASYNC=1 ],
+ [ AC_MSG_RESULT(no); HAVE_FDATASYNC=0 ]
+)
+
+AC_MSG_CHECKING(for F_FULLFSYNC)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <fcntl.h>]],
+ [[ fcntl(0, F_FULLFSYNC, 0); ]])],
+ [ AC_MSG_RESULT(yes); HAVE_FULLFSYNC=1 ],
+ [ AC_MSG_RESULT(no); HAVE_FULLFSYNC=0 ]
+)
+
+AC_MSG_CHECKING(for O_CLOEXEC)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <fcntl.h>]],
+ [[ open("", O_CLOEXEC); ]])],
+ [ AC_MSG_RESULT(yes); HAVE_O_CLOEXEC=1 ],
+ [ AC_MSG_RESULT(no); HAVE_O_CLOEXEC=0 ]
+)
+
+dnl crc32c platform checks
+AC_MSG_CHECKING(for __builtin_prefetch)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[
+ char data = 0;
+ const char* address = &data;
+ __builtin_prefetch(address, 0, 0);
+ ]])],
+ [ AC_MSG_RESULT(yes); HAVE_BUILTIN_PREFETCH=1 ],
+ [ AC_MSG_RESULT(no); HAVE_BUILTIN_PREFETCH=0 ]
+)
+
+AC_MSG_CHECKING(for _mm_prefetch)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <xmmintrin.h>]], [[
+ char data = 0;
+ const char* address = &data;
+ _mm_prefetch(address, _MM_HINT_NTA);
+ ]])],
+ [ AC_MSG_RESULT(yes); HAVE_MM_PREFETCH=1 ],
+ [ AC_MSG_RESULT(no); HAVE_MM_PREFETCH=0 ]
+)
+
+AC_MSG_CHECKING(for strong getauxval support in the system headers)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <arm_acle.h>
+ #include <arm_neon.h>
+ #include <sys/auxv.h>
+ ]], [[
+ getauxval(AT_HWCAP);
+ ]])],
+ [ AC_MSG_RESULT(yes); HAVE_STRONG_GETAUXVAL=1 ],
+ [ AC_MSG_RESULT(no); HAVE_STRONG_GETAUXVAL=0 ]
+)
+
+AC_MSG_CHECKING(for weak getauxval support in the compiler)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ unsigned long getauxval(unsigned long type) __attribute__((weak));
+ #define AT_HWCAP 16
+ ]], [[
+ getauxval(AT_HWCAP);
+ ]])],
+ [ AC_MSG_RESULT(yes); HAVE_WEAK_GETAUXVAL=1 ],
+ [ AC_MSG_RESULT(no); HAVE_WEAK_GETAUXVAL=0 ]
+)
+
dnl Check for reduced exports
if test x$use_reduce_exports = xyes; then
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"],
@@ -1074,7 +1183,6 @@ fi
AX_BOOST_SYSTEM
AX_BOOST_FILESYSTEM
AX_BOOST_THREAD
-AX_BOOST_CHRONO
dnl Boost 1.56 through 1.62 allow using std::atomic instead of its own atomic
dnl counter implementations. In 1.63 and later the std::atomic approach is default.
@@ -1141,7 +1249,7 @@ fi
if test x$use_boost = xyes; then
-BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB"
+BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_THREAD_LIB"
dnl If boost (prior to 1.57) was built without c++11, it emulated scoped enums
@@ -1179,57 +1287,6 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
LIBS="$TEMP_LIBS"
CPPFLAGS="$TEMP_CPPFLAGS"
-dnl Boost >= 1.50 uses sleep_for rather than the now-deprecated sleep, however
-dnl it was broken from 1.50 to 1.52 when backed by nanosleep. Use sleep_for if
-dnl a working version is available, else fall back to sleep. sleep was removed
-dnl after 1.56.
-dnl If neither is available, abort.
-TEMP_LIBS="$LIBS"
-LIBS="$BOOST_LIBS $LIBS"
-TEMP_CPPFLAGS="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
-AC_LINK_IFELSE([AC_LANG_PROGRAM([[
- #include <boost/thread/thread.hpp>
- #include <boost/version.hpp>
- ]],[[
- #if BOOST_VERSION >= 105000 && (!defined(BOOST_HAS_NANOSLEEP) || BOOST_VERSION >= 105200)
- boost::this_thread::sleep_for(boost::chrono::milliseconds(0));
- #else
- choke me
- #endif
- ]])],
- [boost_sleep=yes;
- AC_DEFINE(HAVE_WORKING_BOOST_SLEEP_FOR, 1, [Define this symbol if boost sleep_for works])],
- [boost_sleep=no])
-LIBS="$TEMP_LIBS"
-CPPFLAGS="$TEMP_CPPFLAGS"
-
-if test x$boost_sleep != xyes; then
-TEMP_LIBS="$LIBS"
-LIBS="$BOOST_LIBS $LIBS"
-TEMP_CPPFLAGS="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
-AC_LINK_IFELSE([AC_LANG_PROGRAM([[
- #include <boost/version.hpp>
- #include <boost/thread.hpp>
- #include <boost/date_time/posix_time/posix_time_types.hpp>
- ]],[[
- #if BOOST_VERSION <= 105600
- boost::this_thread::sleep(boost::posix_time::milliseconds(0));
- #else
- choke me
- #endif
- ]])],
- [boost_sleep=yes; AC_DEFINE(HAVE_WORKING_BOOST_SLEEP, 1, [Define this symbol if boost sleep works])],
- [boost_sleep=no])
-LIBS="$TEMP_LIBS"
-CPPFLAGS="$TEMP_CPPFLAGS"
-fi
-
-if test x$boost_sleep != xyes; then
- AC_MSG_ERROR(No working boost sleep implementation found.)
-fi
-
fi
if test x$use_pkgconfig = xyes; then
@@ -1240,10 +1297,10 @@ if test x$use_pkgconfig = xyes; then
if test x$use_qr != xno; then
BITCOIN_QT_CHECK([PKG_CHECK_MODULES([QR], [libqrencode], [have_qrencode=yes], [have_qrencode=no])])
fi
- if test x$build_bitcoin_cli$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then
- PKG_CHECK_MODULES([EVENT], [libevent],, [AC_MSG_ERROR(libevent not found.)])
+ if test x$build_bitcoin_cli$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench != xnonononono; then
+ PKG_CHECK_MODULES([EVENT], [libevent >= 2.0.21], [use_libevent=yes], [AC_MSG_ERROR(libevent version 2.0.21 or greater not found.)])
if test x$TARGET_OS != xwindows; then
- PKG_CHECK_MODULES([EVENT_PTHREADS], [libevent_pthreads],, [AC_MSG_ERROR(libevent_pthreads not found.)])
+ PKG_CHECK_MODULES([EVENT_PTHREADS], [libevent_pthreads >= 2.0.21],, [AC_MSG_ERROR(libevent_pthreads version 2.0.21 or greater not found.)])
fi
fi
@@ -1260,8 +1317,8 @@ if test x$use_pkgconfig = xyes; then
)
else
- if test x$build_bitcoin_cli$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then
- AC_CHECK_HEADER([event2/event.h],, AC_MSG_ERROR(libevent headers missing),)
+ if test x$build_bitcoin_cli$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench != xnonononono; then
+ AC_CHECK_HEADER([event2/event.h], [use_libevent=yes], AC_MSG_ERROR(libevent headers missing),)
AC_CHECK_LIB([event],[main],EVENT_LIBS=-levent,AC_MSG_ERROR(libevent missing))
if test x$TARGET_OS != xwindows; then
AC_CHECK_LIB([event_pthreads],[main],EVENT_PTHREADS_LIBS=-levent_pthreads,AC_MSG_ERROR(libevent_pthreads missing))
@@ -1297,22 +1354,6 @@ else
fi
fi
-dnl RapidCheck property-based testing
-
-enable_property_tests=no
-if test "x$use_rapidcheck" = xauto; then
- AC_CHECK_HEADERS([rapidcheck.h], [enable_property_tests=yes])
-elif test "x$use_rapidcheck" != xno; then
- enable_property_tests=yes
-fi
-
-RAPIDCHECK_LIBS=
-if test "x$enable_property_tests" = xyes; then
- RAPIDCHECK_LIBS=-lrapidcheck
-fi
-AC_SUBST(RAPIDCHECK_LIBS)
-AM_CONDITIONAL([ENABLE_PROPERTY_TESTS], [test x$enable_property_tests = xyes])
-
dnl univalue check
need_bundled_univalue=yes
@@ -1515,13 +1556,16 @@ AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes])
AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes])
AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
+AM_CONDITIONAL([USE_LIBEVENT],[test x$use_libevent = xyes])
AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes])
AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes])
-AM_CONDITIONAL([ENABLE_HWCRC32],[test x$enable_hwcrc32 = xyes])
+AM_CONDITIONAL([ENABLE_SSE42],[test x$enable_sse42 = xyes])
AM_CONDITIONAL([ENABLE_SSE41],[test x$enable_sse41 = xyes])
AM_CONDITIONAL([ENABLE_AVX2],[test x$enable_avx2 = xyes])
AM_CONDITIONAL([ENABLE_SHANI],[test x$enable_shani = xyes])
+AM_CONDITIONAL([ENABLE_ARM_CRC],[test x$enable_arm_crc = xyes])
AM_CONDITIONAL([USE_ASM],[test x$use_asm = xyes])
+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])
@@ -1568,23 +1612,32 @@ AC_SUBST(SSE42_CXXFLAGS)
AC_SUBST(SSE41_CXXFLAGS)
AC_SUBST(AVX2_CXXFLAGS)
AC_SUBST(SHANI_CXXFLAGS)
+AC_SUBST(ARM_CRC_CXXFLAGS)
AC_SUBST(LIBTOOL_APP_LDFLAGS)
AC_SUBST(USE_UPNP)
AC_SUBST(USE_QRCODE)
AC_SUBST(BOOST_LIBS)
AC_SUBST(TESTDEFS)
-AC_SUBST(LEVELDB_TARGET_FLAGS)
AC_SUBST(MINIUPNPC_CPPFLAGS)
AC_SUBST(MINIUPNPC_LIBS)
AC_SUBST(EVENT_LIBS)
AC_SUBST(EVENT_PTHREADS_LIBS)
AC_SUBST(ZMQ_LIBS)
AC_SUBST(QR_LIBS)
+AC_SUBST(HAVE_GMTIME_R)
+AC_SUBST(HAVE_FDATASYNC)
+AC_SUBST(HAVE_FULLFSYNC)
+AC_SUBST(HAVE_O_CLOEXEC)
+AC_SUBST(HAVE_BUILTIN_PREFETCH)
+AC_SUBST(HAVE_MM_PREFETCH)
+AC_SUBST(HAVE_STRONG_GETAUXVAL)
+AC_SUBST(HAVE_WEAK_GETAUXVAL)
AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/config.ini])
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/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])
AC_CONFIG_LINKS([test/util/bitcoin-util-test.py:test/util/bitcoin-util-test.py])
AC_CONFIG_LINKS([test/util/rpcauth-test.py:test/util/rpcauth-test.py])
@@ -1638,7 +1691,6 @@ fi
echo " with zmq = $use_zmq"
echo " with test = $use_tests"
if test x$use_tests != xno; then
- echo " with prop = $enable_property_tests"
echo " with fuzz = $enable_fuzz"
fi
echo " with bench = $use_bench"
diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md
index 515a0d8fc6..f5533719c0 100644
--- a/contrib/devtools/README.md
+++ b/contrib/devtools/README.md
@@ -109,7 +109,7 @@ certain symbols and are only linked against allowed libraries.
For Linux this means checking for allowed gcc, glibc and libstdc++ version symbols.
This makes sure they are still compatible with the minimum supported distribution versions.
-For macOS we check that the executables are only linked against libraries we allow.
+For macOS and Windows we check that the executables are only linked against libraries we allow.
Example usage after a gitian build:
diff --git a/contrib/devtools/circular-dependencies.py b/contrib/devtools/circular-dependencies.py
index 6afa4351e7..bc5f09a3e2 100755
--- a/contrib/devtools/circular-dependencies.py
+++ b/contrib/devtools/circular-dependencies.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018 The Bitcoin Core developers
+# Copyright (c) 2018-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.
diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py
index 1b71245aab..084914f11a 100755
--- a/contrib/devtools/copyright_header.py
+++ b/contrib/devtools/copyright_header.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2019 The Bitcoin Core developers
+# Copyright (c) 2016-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.
@@ -34,6 +34,7 @@ EXCLUDE_DIRS = [
"src/leveldb/",
"src/secp256k1/",
"src/univalue/",
+ "src/crc32c/",
]
INCLUDE = ['*.h', '*.cpp', '*.cc', '*.c', '*.mm', '*.py', '*.sh', '*.bash-completion']
diff --git a/contrib/devtools/previous_release.sh b/contrib/devtools/previous_release.sh
new file mode 100755
index 0000000000..b2ecc274fb
--- /dev/null
+++ b/contrib/devtools/previous_release.sh
@@ -0,0 +1,152 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+# Build previous releases.
+
+export LC_ALL=C
+
+CONFIG_FLAGS=""
+FUNCTIONAL_TESTS=0
+DELETE_EXISTING=0
+USE_DEPENDS=0
+DOWNLOAD_BINARY=0
+CONFIG_FLAGS=""
+TARGET="releases"
+
+while getopts ":hfrdbt:" opt; do
+ case $opt in
+ h)
+ echo "Usage: .previous_release.sh [options] tag1 tag2"
+ echo " options:"
+ echo " -h Print this message"
+ echo " -f Configure for functional tests"
+ echo " -r Remove existing directory"
+ echo " -d Use depends"
+ echo " -b Download release binary"
+ echo " -t Target directory (default: releases)"
+ exit 0
+ ;;
+ f)
+ FUNCTIONAL_TESTS=1
+ CONFIG_FLAGS="$CONFIG_FLAGS --without-gui --disable-tests --disable-bench"
+ ;;
+ r)
+ DELETE_EXISTING=1
+ ;;
+ d)
+ USE_DEPENDS=1
+ ;;
+ b)
+ DOWNLOAD_BINARY=1
+ ;;
+ t)
+ TARGET=$OPTARG
+ ;;
+ \?)
+ echo "Invalid option: -$OPTARG" >&2
+ exit 1
+ ;;
+ esac
+done
+
+shift $((OPTIND-1))
+
+if [ -z "$1" ]; then
+ echo "Specify release tag(s), e.g.: .previous_release v0.15.1"
+ exit 1
+fi
+
+if [ ! -d "$TARGET" ]; then
+ mkdir -p $TARGET
+fi
+
+if [ "$DOWNLOAD_BINARY" -eq "1" ]; then
+ HOST="${HOST:-$(./depends/config.guess)}"
+ case "$HOST" in
+ x86_64-*-linux*)
+ PLATFORM=x86_64-linux-gnu
+ ;;
+ x86_64-apple-darwin*)
+ PLATFORM=osx64
+ ;;
+ *)
+ echo "Not sure which binary to download for $HOST."
+ exit 1
+ ;;
+ esac
+fi
+
+echo "Releases directory: $TARGET"
+pushd "$TARGET" || exit 1
+{
+ for tag in "$@"
+ do
+ if [ "$DELETE_EXISTING" -eq "1" ]; then
+ if [ -d "$tag" ]; then
+ rm -r "$tag"
+ fi
+ fi
+
+ if [ "$DOWNLOAD_BINARY" -eq "0" ]; then
+
+ if [ ! -d "$tag" ]; then
+ if [ -z $(git tag -l "$tag") ]; then
+ echo "Tag $tag not found"
+ exit 1
+ fi
+
+ git clone https://github.com/bitcoin/bitcoin "$tag"
+ pushd "$tag" || exit 1
+ {
+ git checkout "$tag"
+ if [ "$USE_DEPENDS" -eq "1" ]; then
+ pushd depends || exit 1
+ {
+ if [ "$FUNCTIONAL_TESTS" -eq "1" ]; then
+ make NO_QT=1
+ else
+ make
+ fi
+ HOST="${HOST:-$(./config.guess)}"
+ }
+ popd || exit 1
+ CONFIG_FLAGS="--prefix=$PWD/depends/$HOST $CONFIG_FLAGS"
+ fi
+ ./autogen.sh
+ ./configure $CONFIG_FLAGS
+ make
+ # Move binaries, so they're in the same place as in the release download:
+ mkdir bin
+ mv src/bitcoind src/bitcoin-cli src/bitcoin-tx bin
+ if [ "$FUNCTIONAL_TESTS" -eq "0" ]; then
+ mv src/qt/bitcoin-qt bin
+ fi
+ }
+ popd || exit 1
+ fi
+ else
+ if [ -d "$tag" ]; then
+ echo "Using cached $tag"
+ else
+ mkdir "$tag"
+ if [[ "$tag" =~ v(.*)(rc[0-9]+)$ ]]; then
+ BIN_PATH="bin/bitcoin-core-${BASH_REMATCH[1]}/test.${BASH_REMATCH[2]}"
+ else
+ BIN_PATH="bin/bitcoin-core-${tag:1}"
+ fi
+ URL="https://bitcoin.org/$BIN_PATH/bitcoin-${tag:1}-$PLATFORM.tar.gz"
+ echo "Fetching: $URL"
+ if ! curl -O -f $URL; then
+ echo "Download failed."
+ exit 1
+ fi
+ tar -zxf "bitcoin-${tag:1}-$PLATFORM.tar.gz" -C "$tag" --strip-components=1 "bitcoin-${tag:1}"
+ rm "bitcoin-${tag:1}-$PLATFORM.tar.gz"
+ fi
+ fi
+ done
+}
+popd || exit 1
diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py
index 21d64e893d..9444271bdc 100755
--- a/contrib/devtools/security-check.py
+++ b/contrib/devtools/security-check.py
@@ -158,6 +158,17 @@ def check_PE_HIGH_ENTROPY_VA(executable):
reqbits = 0
return (bits & reqbits) == reqbits
+def check_PE_RELOC_SECTION(executable) -> bool:
+ '''Check for a reloc section. This is required for functional ASLR.'''
+ p = subprocess.Popen([OBJDUMP_CMD, '-h', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+ for line in stdout.splitlines():
+ if '.reloc' in line:
+ return True
+ return False
+
def check_PE_NX(executable):
'''NX: DllCharacteristics bit 0x100 signifies nxcompat (DEP)'''
(arch,bits) = get_PE_dll_characteristics(executable)
@@ -197,6 +208,46 @@ def check_MACHO_NOUNDEFS(executable) -> bool:
return True
return False
+def check_MACHO_NX(executable) -> bool:
+ '''
+ Check for no stack execution
+ '''
+ flags = get_MACHO_executable_flags(executable)
+ if 'ALLOW_STACK_EXECUTION' in flags:
+ return False
+ return True
+
+def check_MACHO_LAZY_BINDINGS(executable) -> bool:
+ '''
+ Check for no lazy bindings.
+ We don't use or check for MH_BINDATLOAD. See #18295.
+ '''
+ p = subprocess.Popen([OTOOL_CMD, '-l', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+
+ for line in stdout.splitlines():
+ tokens = line.split()
+ if 'lazy_bind_off' in tokens or 'lazy_bind_size' in tokens:
+ if tokens[1] != '0':
+ return False
+ return True
+
+def check_MACHO_Canary(executable) -> bool:
+ '''
+ Check for use of stack canary
+ '''
+ p = subprocess.Popen([OTOOL_CMD, '-Iv', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+ ok = False
+ for line in stdout.splitlines():
+ if '___stack_chk_fail' in line:
+ ok = True
+ return ok
+
CHECKS = {
'ELF': [
('PIE', check_ELF_PIE),
@@ -207,11 +258,15 @@ CHECKS = {
'PE': [
('DYNAMIC_BASE', check_PE_DYNAMIC_BASE),
('HIGH_ENTROPY_VA', check_PE_HIGH_ENTROPY_VA),
- ('NX', check_PE_NX)
+ ('NX', check_PE_NX),
+ ('RELOC_SECTION', check_PE_RELOC_SECTION)
],
'MACHO': [
('PIE', check_MACHO_PIE),
('NOUNDEFS', check_MACHO_NOUNDEFS),
+ ('NX', check_MACHO_NX),
+ ('LAZY_BINDINGS', check_MACHO_LAZY_BINDINGS),
+ ('Canary', check_MACHO_Canary)
]
}
diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py
index f92d997621..6949cb7ced 100755
--- a/contrib/devtools/symbol-check.py
+++ b/contrib/devtools/symbol-check.py
@@ -3,9 +3,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
'''
-A script to check that the (Linux) executables produced by gitian only contain
-allowed gcc and glibc version symbols. This makes sure they are still compatible
-with the minimum supported Linux distribution versions.
+A script to check that the executables produced by gitian only contain
+certain symbols and are only linked against allowed libraries.
Example usage:
@@ -53,6 +52,7 @@ IGNORE_EXPORTS = {
}
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
+OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump')
OTOOL_CMD = os.getenv('OTOOL', '/usr/bin/otool')
# Allowed NEEDED libraries
@@ -101,6 +101,26 @@ MACHO_ALLOWED_LIBRARIES = {
'libobjc.A.dylib', # Objective-C runtime library
}
+PE_ALLOWED_LIBRARIES = {
+'ADVAPI32.dll', # security & registry
+'IPHLPAPI.DLL', # IP helper API
+'KERNEL32.dll', # win32 base APIs
+'msvcrt.dll', # C standard library for MSVC
+'SHELL32.dll', # shell API
+'USER32.dll', # user interface
+'WS2_32.dll', # sockets
+# bitcoin-qt only
+'dwmapi.dll', # desktop window manager
+'GDI32.dll', # graphics device interface
+'IMM32.dll', # input method editor
+'ole32.dll', # component object model
+'OLEAUT32.dll', # OLE Automation API
+'SHLWAPI.dll', # light weight shell API
+'UxTheme.dll',
+'VERSION.dll', # version checking
+'WINMM.dll', # WinMM audio API
+}
+
class CPPFilt(object):
'''
Demangle C++ symbol names.
@@ -218,6 +238,26 @@ def check_MACHO_libraries(filename) -> bool:
ok = False
return ok
+def pe_read_libraries(filename) -> List[str]:
+ p = subprocess.Popen([OBJDUMP_CMD, '-x', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+ libraries = []
+ for line in stdout.splitlines():
+ if 'DLL Name:' in line:
+ tokens = line.split(': ')
+ libraries.append(tokens[1])
+ return libraries
+
+def check_PE_libraries(filename) -> bool:
+ ok = True
+ for dylib in pe_read_libraries(filename):
+ if dylib not in PE_ALLOWED_LIBRARIES:
+ print('{} is not in ALLOWED_LIBRARIES!'.format(dylib))
+ ok = False
+ return ok
+
CHECKS = {
'ELF': [
('IMPORTED_SYMBOLS', check_imported_symbols),
@@ -226,6 +266,9 @@ CHECKS = {
],
'MACHO': [
('DYNAMIC_LIBRARIES', check_MACHO_libraries)
+],
+'PE' : [
+ ('DYNAMIC_LIBRARIES', check_PE_libraries)
]
}
diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py
index 438d5f6bf0..ea70b27941 100755
--- a/contrib/devtools/test-security-check.py
+++ b/contrib/devtools/test-security-check.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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.
'''
@@ -43,16 +43,41 @@ class TestSecurityChecks(unittest.TestCase):
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE']),
(0, ''))
- def test_64bit_PE(self):
+ def test_PE(self):
source = 'test1.c'
executable = 'test1.exe'
cc = 'x86_64-w64-mingw32-gcc'
write_testcode(source)
- self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--no-nxcompat','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va']), (1, executable+': failed DYNAMIC_BASE HIGH_ENTROPY_VA NX'))
- self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va']), (1, executable+': failed DYNAMIC_BASE HIGH_ENTROPY_VA'))
- self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--no-high-entropy-va']), (1, executable+': failed HIGH_ENTROPY_VA'))
- self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va']), (0, ''))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--no-nxcompat','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
+ (1, executable+': failed DYNAMIC_BASE HIGH_ENTROPY_VA NX RELOC_SECTION'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
+ (1, executable+': failed DYNAMIC_BASE HIGH_ENTROPY_VA RELOC_SECTION'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
+ (1, executable+': failed HIGH_ENTROPY_VA RELOC_SECTION'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va','-no-pie','-fno-PIE']),
+ (1, executable+': failed RELOC_SECTION'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va','-pie','-fPIE']),
+ (0, ''))
+
+ def test_MACHO(self):
+ source = 'test1.c'
+ executable = 'test1'
+ cc = 'clang'
+ write_testcode(source)
+
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fno-stack-protector']),
+ (1, executable+': failed PIE NOUNDEFS NX LAZY_BINDINGS Canary'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fstack-protector-all']),
+ (1, executable+': failed PIE NOUNDEFS NX LAZY_BINDINGS'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-fstack-protector-all']),
+ (1, executable+': failed PIE NOUNDEFS LAZY_BINDINGS'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-fstack-protector-all']),
+ (1, executable+': failed PIE LAZY_BINDINGS'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-bind_at_load','-fstack-protector-all']),
+ (1, executable+': failed PIE'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-pie','-Wl,-bind_at_load','-fstack-protector-all']),
+ (0, ''))
if __name__ == '__main__':
unittest.main()
diff --git a/contrib/devtools/test_deterministic_coverage.sh b/contrib/devtools/test_deterministic_coverage.sh
index f5cd05a2c3..95b1553215 100755
--- a/contrib/devtools/test_deterministic_coverage.sh
+++ b/contrib/devtools/test_deterministic_coverage.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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.
#
diff --git a/contrib/filter-lcov.py b/contrib/filter-lcov.py
index 75034616f7..e005cb96da 100755
--- a/contrib/filter-lcov.py
+++ b/contrib/filter-lcov.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2018 The Bitcoin Core developers
+# Copyright (c) 2017-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.
diff --git a/contrib/gitian-build.py b/contrib/gitian-build.py
index ade9e00d1b..4a3df93cea 100755
--- a/contrib/gitian-build.py
+++ b/contrib/gitian-build.py
@@ -209,7 +209,7 @@ def main():
args.macos = 'm' in args.os
# Disable for MacOS if no SDK found
- if args.macos and not os.path.isfile('gitian-builder/inputs/MacOSX10.11.sdk.tar.gz'):
+ if args.macos and not os.path.isfile('gitian-builder/inputs/MacOSX10.14.sdk.tar.gz'):
print('Cannot build for MacOS, SDK does not exist. Will build for other OSes')
args.macos = False
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index 257dd8ba30..f421372e10 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -1,5 +1,5 @@
---
-name: "bitcoin-core-linux-0.20"
+name: "bitcoin-core-linux-0.21"
enable_cache: true
distro: "ubuntu"
suites:
@@ -40,13 +40,13 @@ script: |
set -e -o pipefail
WRAP_DIR=$HOME/wrapped
- HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu"
+ HOSTS="x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu"
CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests"
FAKETIME_HOST_PROGS="gcc g++"
FAKETIME_PROGS="date ar ranlib nm"
HOST_CFLAGS="-O2 -g"
HOST_CXXFLAGS="-O2 -g"
- HOST_LDFLAGS_BASE="-static-libstdc++"
+ HOST_LDFLAGS_BASE="-static-libstdc++ -Wl,-O2"
export QT_RCC_TEST=1
export QT_RCC_SOURCE_DATE_OVERRIDE=1
@@ -140,25 +140,12 @@ script: |
create_per-host_faketime_wrappers "${REFERENCE_DATETIME}"
export PATH=${WRAP_DIR}:${PATH}
- # Create the release tarball using (arbitrarily) the first host
- ./autogen.sh
- CONFIG_SITE=${BASEPREFIX}/$(echo "${HOSTS}" | awk '{print $1;}')/share/config.site ./configure --prefix=/
- make dist
- SOURCEDIST=$(echo bitcoin-*.tar.gz)
- DISTNAME=${SOURCEDIST/%.tar.gz}
-
- # Correct tar file order
- mkdir -p temp
- pushd temp
- tar -xf ../$SOURCEDIST
- find bitcoin-* | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST
- popd
-
- # Workaround for tarball not building with the bare tag version (prep)
- make -C src obj/build.h
+ # Create the git archive, and define DISTNAME and GIT_ARCHIVE variables.
+ # shellcheck source=contrib/gitian-descriptors/make_git_archive
+ source contrib/gitian-descriptors/make_git_archive
ORIGPATH="$PATH"
- # Extract the release tarball into a dir for each host and build
+ # Extract the git archive into a dir for each host and build
for i in ${HOSTS}; do
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
if [ "${i}" = "riscv64-linux-gnu" ]; then
@@ -172,13 +159,9 @@ script: |
cd distsrc-${i}
INSTALLPATH="${PWD}/installed/${DISTNAME}"
mkdir -p ${INSTALLPATH}
- tar --strip-components=1 -xf ../$SOURCEDIST
-
- # Workaround for tarball not building with the bare tag version
- echo '#!/bin/true' >share/genbuild.sh
- mkdir src/obj
- cp ../src/obj/build.h src/obj/
+ tar -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}"
make ${MAKEOPTS}
make ${MAKEOPTS} -C src check-security
@@ -196,5 +179,3 @@ script: |
cd ../../
rm -rf distsrc-${i}
done
- mkdir -p $OUTDIR/src
- mv $SOURCEDIST $OUTDIR/src
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index 7c5abb9018..82f8f194fc 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -1,5 +1,5 @@
---
-name: "bitcoin-core-osx-0.20"
+name: "bitcoin-core-osx-0.21"
enable_cache: true
distro: "ubuntu"
suites:
@@ -32,7 +32,7 @@ remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
"dir": "bitcoin"
files:
-- "MacOSX10.11.sdk.tar.gz"
+- "MacOSX10.14.sdk.tar.gz"
script: |
set -e -o pipefail
@@ -90,7 +90,7 @@ script: |
BASEPREFIX="${PWD}/depends"
mkdir -p ${BASEPREFIX}/SDKs
- tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.11.sdk.tar.gz
+ tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.14.sdk.tar.gz
# Build dependencies for each host
for i in $HOSTS; do
@@ -103,38 +103,21 @@ script: |
create_per-host_faketime_wrappers "${REFERENCE_DATETIME}"
export PATH=${WRAP_DIR}:${PATH}
- # Create the release tarball using (arbitrarily) the first host
- ./autogen.sh
- CONFIG_SITE=${BASEPREFIX}/$(echo "${HOSTS}" | awk '{print $1;}')/share/config.site ./configure --prefix=/
- make dist
- SOURCEDIST=$(echo bitcoin-*.tar.gz)
- DISTNAME=${SOURCEDIST/%.tar.gz}
-
- # Correct tar file order
- mkdir -p temp
- pushd temp
- tar -xf ../$SOURCEDIST
- find bitcoin-* | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST
- popd
-
- # Workaround for tarball not building with the bare tag version (prep)
- make -C src obj/build.h
+ # Create the git archive, and define DISTNAME and GIT_ARCHIVE variables.
+ # shellcheck source=contrib/gitian-descriptors/make_git_archive
+ source contrib/gitian-descriptors/make_git_archive
ORIGPATH="$PATH"
- # Extract the release tarball into a dir for each host and build
+ # Extract the git archive into a dir for each host and build
for i in ${HOSTS}; do
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
mkdir -p distsrc-${i}
cd distsrc-${i}
INSTALLPATH="${PWD}/installed/${DISTNAME}"
mkdir -p ${INSTALLPATH}
- tar --strip-components=1 -xf ../$SOURCEDIST
-
- # Workaround for tarball not building with the bare tag version
- echo '#!/bin/true' >share/genbuild.sh
- mkdir src/obj
- cp ../src/obj/build.h src/obj/
+ tar -xf $GIT_ARCHIVE
+ ./autogen.sh
CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS}
make ${MAKEOPTS}
make ${MAKEOPTS} -C src check-security
@@ -166,6 +149,5 @@ script: |
find ${DISTNAME} | 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}-${i}.tar.gz
cd ../../
done
- mkdir -p $OUTDIR/src
- mv $SOURCEDIST $OUTDIR/src
+
mv ${OUTDIR}/${DISTNAME}-x86_64-*.tar.gz ${OUTDIR}/${DISTNAME}-osx64.tar.gz
diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml
index 9d96465742..6bcd126662 100644
--- a/contrib/gitian-descriptors/gitian-win-signer.yml
+++ b/contrib/gitian-descriptors/gitian-win-signer.yml
@@ -8,6 +8,7 @@ architectures:
packages:
- "libssl-dev"
- "autoconf"
+- "automake"
- "libtool"
- "pkg-config"
remotes:
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index de2e45190a..54ad68a2a3 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -1,5 +1,5 @@
---
-name: "bitcoin-core-win-0.20"
+name: "bitcoin-core-win-0.21"
enable_cache: true
distro: "ubuntu"
suites:
@@ -34,8 +34,8 @@ script: |
CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests"
FAKETIME_HOST_PROGS="ar ranlib nm windres strip objcopy"
FAKETIME_PROGS="date makensis zip"
- HOST_CFLAGS="-O2 -g"
- HOST_CXXFLAGS="-O2 -g"
+ HOST_CFLAGS="-O2 -g -fno-ident"
+ HOST_CXXFLAGS="-O2 -g -fno-ident"
export QT_RCC_TEST=1
export QT_RCC_SOURCE_DATE_OVERRIDE=1
@@ -76,13 +76,11 @@ script: |
function create_per-host_compiler_wrapper {
# -posix variant is required for c++11 threading.
for i in $HOSTS; do
- mkdir -p ${WRAP_DIR}/${i}
for prog in gcc g++; do
echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog}
echo "REAL=\`which -a ${i}-${prog}-posix | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo "export LD_PRELOAD='/usr/\$LIB/faketime/libfaketime.so.1'" >> ${WRAP_DIR}/${i}-${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
- echo "export COMPILER_PATH=${WRAP_DIR}/${i}" >> ${WRAP_DIR}/${i}-${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog}
chmod +x ${WRAP_DIR}/${i}-${prog}
done
@@ -110,44 +108,28 @@ script: |
create_per-host_compiler_wrapper "${REFERENCE_DATETIME}"
export PATH=${WRAP_DIR}:${PATH}
- # Create the release tarball using (arbitrarily) the first host
- ./autogen.sh
- CONFIG_SITE=${BASEPREFIX}/$(echo "${HOSTS}" | awk '{print $1;}')/share/config.site ./configure --prefix=/
- make dist
- SOURCEDIST=$(echo bitcoin-*.tar.gz)
- DISTNAME=${SOURCEDIST/%.tar.gz}
-
- # Correct tar file order
- mkdir -p temp
- pushd temp
- tar -xf ../$SOURCEDIST
- find bitcoin-* | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST
- popd
-
- # Workaround for tarball not building with the bare tag version (prep)
- make -C src obj/build.h
+ # Create the git archive, and define DISTNAME and GIT_ARCHIVE variables.
+ # shellcheck source=contrib/gitian-descriptors/make_git_archive
+ source contrib/gitian-descriptors/make_git_archive
ORIGPATH="$PATH"
- # Extract the release tarball into a dir for each host and build
+ # Extract the git archive into a dir for each host and build
for i in ${HOSTS}; do
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
mkdir -p distsrc-${i}
cd distsrc-${i}
INSTALLPATH="${PWD}/installed/${DISTNAME}"
mkdir -p ${INSTALLPATH}
- tar --strip-components=1 -xf ../$SOURCEDIST
-
- # Workaround for tarball not building with the bare tag version
- echo '#!/bin/true' >share/genbuild.sh
- mkdir src/obj
- cp ../src/obj/build.h src/obj/
+ tar -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}"
make ${MAKEOPTS}
make ${MAKEOPTS} -C src check-security
+ make ${MAKEOPTS} -C src check-symbols
make deploy
make install DESTDIR=${INSTALLPATH}
- cp -f --target-directory="${OUTDIR}" ./bitcoin-*-setup-unsigned.exe
+ cp -f ./bitcoin-*-win64-setup-unsigned.exe ${OUTDIR}/${DISTNAME}-win64-setup-unsigned.exe
cd installed
mv ${DISTNAME}/bin/*.dll ${DISTNAME}/lib/
find . -name "lib*.la" -delete
@@ -161,10 +143,9 @@ script: |
cd ../../
rm -rf distsrc-${i}
done
- mkdir -p $OUTDIR/src
- mv $SOURCEDIST $OUTDIR/src
+
cp -rf contrib/windeploy $BUILD_DIR
cd $BUILD_DIR/windeploy
mkdir unsigned
- cp $OUTDIR/bitcoin-*setup-unsigned.exe unsigned/
+ cp ${OUTDIR}/${DISTNAME}-win64-setup-unsigned.exe unsigned/
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}-win-unsigned.tar.gz
diff --git a/contrib/gitian-descriptors/make_git_archive b/contrib/gitian-descriptors/make_git_archive
new file mode 100755
index 0000000000..d922c94c60
--- /dev/null
+++ b/contrib/gitian-descriptors/make_git_archive
@@ -0,0 +1,20 @@
+# 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.
+#
+# A helper script to be sourced into the gitian descriptors
+
+mkdir -p ${OUTDIR}/src
+RECENT_TAG=$(git describe --abbrev=0 HEAD)
+if [ $RECENT_TAG = $(git describe HEAD) ]; then
+ if [[ $RECENT_TAG == v* ]]; then
+ VERSION=${RECENT_TAG:1}
+ else
+ VERSION=$RECENT_TAG
+ fi
+else
+ VERSION=$(git rev-parse --short HEAD)
+fi
+DISTNAME=bitcoin-${VERSION}
+GIT_ARCHIVE="${OUTDIR}/src/${DISTNAME}.tar.gz"
+git archive --output=$GIT_ARCHIVE HEAD
diff --git a/contrib/gitian-keys/keys.txt b/contrib/gitian-keys/keys.txt
index ba3036a89f..0a2c1302c8 100644
--- a/contrib/gitian-keys/keys.txt
+++ b/contrib/gitian-keys/keys.txt
@@ -13,6 +13,7 @@ D35176BE9264832E4ACA8986BF0792FBE95DC863 fivepiece
01CDF4627A3B88AAE4A571C87588242FBE38D3A8 Gavin Andresen
D1DBF2C4B96F2DEBF4C16654410108112E7EA81F Hennadii Stepanov (hebasto)
D3CC177286005BB8FF673294C5242A1AB3936517 jl2012
+82921A4B88FD454B7EB8CE3C796C4109063D4EAF Jon Atack
32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC Jonas Schnelli
4B4E840451149DD7FB0D633477DFAB5C3108B9A8 Jorge Timon
C42AFF7C61B3E44A1454CD3557AF762DB3353322 Karl-Johan Alm (kallewoof)
@@ -29,6 +30,7 @@ D762373D24904A3E42F33B08B9A408E71DAAC974 Pieter Wuille (Location: Leuven, Belgiu
133EAC179436F14A5CF1B794860FEB804E669320 Pieter Wuille
A8FC55F3B04BA3146F3492E79303B33A305224CB Sebastian Kung (TheCharlatan)
ED9BDF7AD6A55E232E84524257FF9BDBCC301009 Sjors Provoost
+9EDAFF80E080659604F4A76B2EBB056FD847F8A7 Stephan Oeste (Emzy)
AEC1884398647C47413C1C3FB1179EB7347DC10D Warren Togami
79D00BAC68B56D422F945A8F8E3A8F3247DBCBBF Willy Ko
71A3B16735405025D447E8F274810B012346C9A6 Wladimir J. van der Laan
diff --git a/contrib/guix/README.md b/contrib/guix/README.md
index 46d755886c..9f99b36f88 100644
--- a/contrib/guix/README.md
+++ b/contrib/guix/README.md
@@ -114,7 +114,7 @@ find output/ -type f -print0 | sort -z | xargs -r0 sha256sum
* _**HOSTS**_
Override the space-separated list of platform triples for which to perform a
- bootstrappable build. _(defaults to "i686-linux-gnu x86\_64-linux-gnu
+ bootstrappable build. _(defaults to "x86\_64-linux-gnu
arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu")_
> Windows and OS X platform triplet support are WIP.
@@ -220,8 +220,6 @@ repository and will likely put one up soon.
[guix/env-setup]: https://www.gnu.org/software/guix/manual/en/html_node/Build-Environment-Setup.html
[guix/substitutes]: https://www.gnu.org/software/guix/manual/en/html_node/Substitutes.html
[guix/substitute-server-auth]: https://www.gnu.org/software/guix/manual/en/html_node/Substitute-Server-Authorization.html
-[guix/inferiors]: https://www.gnu.org/software/guix/manual/en/html_node/Inferiors.html
-[guix/channels]: https://www.gnu.org/software/guix/manual/en/html_node/Channels.html
[guix/time-machine]: https://guix.gnu.org/manual/en/html_node/Invoking-guix-time_002dmachine.html
[debian/guix-package]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=850644
diff --git a/contrib/guix/guix-build.sh b/contrib/guix/guix-build.sh
index 5e0c681f29..e20b2a048d 100755
--- a/contrib/guix/guix-build.sh
+++ b/contrib/guix/guix-build.sh
@@ -13,33 +13,106 @@ make -C "${PWD}/depends" -j"$MAX_JOBS" download ${V:+V=1} ${SOURCES_PATH:+SOURCE
# Determine the reference time used for determinism (overridable by environment)
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(git log --format=%at -1)}"
+# Execute "$@" in a pinned, possibly older version of Guix, for reproducibility
+# across time.
time-machine() {
guix time-machine --url=https://github.com/dongcarl/guix.git \
- --commit=b3a7c72c8b2425f8ddb0fc6e3b1caeed40f86dee \
+ --commit=b066c25026f21fb57677aa34692a5034338e7ee3 \
-- "$@"
}
-# Deterministically build Bitcoin Core for HOSTs (overriable by environment)
-for host in ${HOSTS=i686-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu}; do
+# Function to be called when building for host ${1} and the user interrupts the
+# build
+int_trap() {
+cat << EOF
+** INT received while building ${1}, you may want to clean up the relevant
+ output, deploy, and distsrc-* directories before rebuilding
+
+Hint: To blow everything away, you may want to use:
+
+ $ git clean -xdff --exclude='/depends/SDKs/*'
+
+Specifically, this will remove all files without an entry in the index,
+excluding the SDK directory. Practically speaking, this means that all ignored
+and untracked files and directories will be wiped, allowing you to start anew.
+EOF
+}
+
+# Deterministically build Bitcoin Core for HOSTs (overridable by environment)
+# shellcheck disable=SC2153
+for host in ${HOSTS=x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu x86_64-w64-mingw32}; do
# Display proper warning when the user interrupts the build
- trap 'echo "** INT received while building ${host}, you may want to clean up the relevant output and distsrc-* directories before rebuilding"' INT
-
- # Run the build script 'contrib/guix/libexec/build.sh' in the build
- # container specified by 'contrib/guix/manifest.scm'
- # shellcheck disable=SC2086
- time-machine environment --manifest="${PWD}/contrib/guix/manifest.scm" \
- --container \
- --pure \
- --no-cwd \
- --share="$PWD"=/bitcoin \
- ${SOURCES_PATH:+--share="$SOURCES_PATH"} \
- ${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \
- -- env HOST="$host" \
- MAX_JOBS="$MAX_JOBS" \
- SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \
- ${V:+V=1} \
- ${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \
- bash -c "cd /bitcoin && bash contrib/guix/libexec/build.sh"
+ trap 'int_trap ${host}' INT
+
+ (
+ # Required for 'contrib/guix/manifest.scm' to output the right manifest
+ # for the particular $HOST we're building for
+ export HOST="$host"
+
+ # Run the build script 'contrib/guix/libexec/build.sh' in the build
+ # container specified by 'contrib/guix/manifest.scm'.
+ #
+ # Explanation of `guix environment` flags:
+ #
+ # --container run command within an isolated container
+ #
+ # Running in an isolated container minimizes build-time differences
+ # between machines and improves reproducibility
+ #
+ # --pure unset existing environment variables
+ #
+ # Same rationale as --container
+ #
+ # --no-cwd do not share current working directory with an
+ # isolated container
+ #
+ # When --container is specified, the default behavior is to share
+ # the current working directory with the isolated container at the
+ # same exact path (e.g. mapping '/home/satoshi/bitcoin/' to
+ # '/home/satoshi/bitcoin/'). This means that the $PWD inside the
+ # container becomes a source of irreproducibility. --no-cwd disables
+ # this behaviour.
+ #
+ # --share=SPEC for containers, share writable host file system
+ # according to SPEC
+ #
+ # --share="$PWD"=/bitcoin
+ #
+ # maps our current working directory to /bitcoin
+ # inside the isolated container, which we later cd
+ # into.
+ #
+ # While we don't want to map our current working directory to the
+ # same exact path (as this introduces irreproducibility), we do want
+ # it to be at a _fixed_ path _somewhere_ inside the isolated
+ # container so that we have something to build. '/bitcoin' was
+ # chosen arbitrarily.
+ #
+ # ${SOURCES_PATH:+--share="$SOURCES_PATH"}
+ #
+ # make the downloaded depends sources path available
+ # inside the isolated container
+ #
+ # The isolated container has no network access as it's in a
+ # different network namespace from the main machine, so we have to
+ # make the downloaded depends sources available to it. The sources
+ # should have been downloaded prior to this invocation.
+ #
+ # shellcheck disable=SC2086
+ time-machine environment --manifest="${PWD}/contrib/guix/manifest.scm" \
+ --container \
+ --pure \
+ --no-cwd \
+ --share="$PWD"=/bitcoin \
+ ${SOURCES_PATH:+--share="$SOURCES_PATH"} \
+ ${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \
+ -- env HOST="$host" \
+ MAX_JOBS="$MAX_JOBS" \
+ SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \
+ ${V:+V=1} \
+ ${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \
+ bash -c "cd /bitcoin && bash contrib/guix/libexec/build.sh"
+ )
done
diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh
index ee207a957c..550b1b8f40 100644
--- a/contrib/guix/libexec/build.sh
+++ b/contrib/guix/libexec/build.sh
@@ -1,6 +1,7 @@
#!/usr/bin/env bash
export LC_ALL=C
set -e -o pipefail
+export TZ=UTC
# Check that environment variables assumed to be set by the environment are set
echo "Building for platform triple ${HOST:?not set} with reference timestamp ${SOURCE_DATE_EPOCH:?not set}..."
@@ -36,23 +37,41 @@ store_path() {
--expression='s|"[[:space:]]*$||'
}
-# Determine output paths to use in CROSS_* environment variables
-CROSS_GLIBC="$(store_path glibc-cross-${HOST})"
-CROSS_GLIBC_STATIC="$(store_path glibc-cross-${HOST} static)"
-CROSS_KERNEL="$(store_path linux-libre-headers-cross-${HOST})"
-CROSS_GCC="$(store_path gcc-cross-${HOST})"
-CROSS_GCC_LIBS=( "${CROSS_GCC}/lib/gcc/${HOST}"/* ) # This expands to an array of directories...
-CROSS_GCC_LIB="${CROSS_GCC_LIBS[0]}" # ...we just want the first one (there should only be one)
-
# Set environment variables to point Guix's cross-toolchain to the right
# includes/libs for $HOST
-#
-# NOTE: CROSS_C_INCLUDE_PATH is missing ${CROSS_GCC_LIB}/include-fixed, because
-# the limits.h in it is missing a '#include_next <limits.h>'
-#
-export CROSS_C_INCLUDE_PATH="${CROSS_GCC_LIB}/include:${CROSS_GLIBC}/include:${CROSS_KERNEL}/include"
-export CROSS_CPLUS_INCLUDE_PATH="${CROSS_GCC}/include/c++:${CROSS_GCC}/include/c++/${HOST}:${CROSS_GCC}/include/c++/backward:${CROSS_C_INCLUDE_PATH}"
-export CROSS_LIBRARY_PATH="${CROSS_GCC}/lib:${CROSS_GCC}/${HOST}/lib:${CROSS_GCC_LIB}:${CROSS_GLIBC}/lib:${CROSS_GLIBC_STATIC}/lib"
+case "$HOST" in
+ *mingw*)
+ # Determine output paths to use in CROSS_* environment variables
+ CROSS_GLIBC="$(store_path "mingw-w64-x86_64-winpthreads")"
+ CROSS_GCC="$(store_path "gcc-cross-${HOST}")"
+ CROSS_GCC_LIBS=( "${CROSS_GCC}/lib/gcc/${HOST}"/* ) # This expands to an array of directories...
+ CROSS_GCC_LIB="${CROSS_GCC_LIBS[0]}" # ...we just want the first one (there should only be one)
+
+ NATIVE_GCC="$(store_path gcc-glibc-2.27-toolchain)"
+ export LIBRARY_PATH="${NATIVE_GCC}/lib:${NATIVE_GCC}/lib64"
+ export CPATH="${NATIVE_GCC}/include"
+
+ export CROSS_C_INCLUDE_PATH="${CROSS_GCC_LIB}/include:${CROSS_GCC_LIB}/include-fixed:${CROSS_GLIBC}/include"
+ export CROSS_CPLUS_INCLUDE_PATH="${CROSS_GCC}/include/c++:${CROSS_GCC}/include/c++/${HOST}:${CROSS_GCC}/include/c++/backward:${CROSS_C_INCLUDE_PATH}"
+ export CROSS_LIBRARY_PATH="${CROSS_GCC}/lib:${CROSS_GCC}/${HOST}/lib:${CROSS_GCC_LIB}:${CROSS_GLIBC}/lib"
+ ;;
+ *linux*)
+ CROSS_GLIBC="$(store_path "glibc-cross-${HOST}")"
+ CROSS_GLIBC_STATIC="$(store_path "glibc-cross-${HOST}" static)"
+ CROSS_KERNEL="$(store_path "linux-libre-headers-cross-${HOST}")"
+ CROSS_GCC="$(store_path "gcc-cross-${HOST}")"
+ CROSS_GCC_LIBS=( "${CROSS_GCC}/lib/gcc/${HOST}"/* ) # This expands to an array of directories...
+ CROSS_GCC_LIB="${CROSS_GCC_LIBS[0]}" # ...we just want the first one (there should only be one)
+
+ # NOTE: CROSS_C_INCLUDE_PATH is missing ${CROSS_GCC_LIB}/include-fixed, because
+ # the limits.h in it is missing a '#include_next <limits.h>'
+ export CROSS_C_INCLUDE_PATH="${CROSS_GCC_LIB}/include:${CROSS_GLIBC}/include:${CROSS_KERNEL}/include"
+ export CROSS_CPLUS_INCLUDE_PATH="${CROSS_GCC}/include/c++:${CROSS_GCC}/include/c++/${HOST}:${CROSS_GCC}/include/c++/backward:${CROSS_C_INCLUDE_PATH}"
+ export CROSS_LIBRARY_PATH="${CROSS_GCC}/lib:${CROSS_GCC}/${HOST}/lib:${CROSS_GCC_LIB}:${CROSS_GLIBC}/lib:${CROSS_GLIBC_STATIC}/lib"
+ ;;
+ *)
+ exit 1 ;;
+esac
# Sanity check CROSS_*_PATH directories
IFS=':' read -ra PATHS <<< "${CROSS_C_INCLUDE_PATH}:${CROSS_CPLUS_INCLUDE_PATH}:${CROSS_LIBRARY_PATH}"
@@ -74,16 +93,20 @@ export GUIX_LD_WRAPPER_DISABLE_RPATH=yes
[ -e /usr/bin/env ] || ln -s --no-dereference "$(command -v env)" /usr/bin/env
# Determine the correct value for -Wl,--dynamic-linker for the current $HOST
-glibc_dynamic_linker=$(
- case "$HOST" in
- i686-linux-gnu) echo /lib/ld-linux.so.2 ;;
- x86_64-linux-gnu) echo /lib64/ld-linux-x86-64.so.2 ;;
- arm-linux-gnueabihf) echo /lib/ld-linux-armhf.so.3 ;;
- aarch64-linux-gnu) echo /lib/ld-linux-aarch64.so.1 ;;
- riscv64-linux-gnu) echo /lib/ld-linux-riscv64-lp64d.so.1 ;;
- *) exit 1 ;;
- esac
-)
+case "$HOST" in
+ *linux*)
+ glibc_dynamic_linker=$(
+ case "$HOST" in
+ i686-linux-gnu) echo /lib/ld-linux.so.2 ;;
+ x86_64-linux-gnu) echo /lib64/ld-linux-x86-64.so.2 ;;
+ arm-linux-gnueabihf) echo /lib/ld-linux-armhf.so.3 ;;
+ aarch64-linux-gnu) echo /lib/ld-linux-aarch64.so.1 ;;
+ riscv64-linux-gnu) echo /lib/ld-linux-riscv64-lp64d.so.1 ;;
+ *) exit 1 ;;
+ esac
+ )
+ ;;
+esac
# Environment variables for determinism
export QT_RCC_TEST=1
@@ -136,11 +159,27 @@ DISTNAME="$(basename "$SOURCEDIST" '.tar.gz')"
# Binary Tarball Building #
###########################
-# Similar flags to Gitian
-CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests"
-HOST_CFLAGS="-O2 -g -ffile-prefix-map=${PWD}=."
-HOST_CXXFLAGS="-O2 -g -ffile-prefix-map=${PWD}=."
-HOST_LDFLAGS="-Wl,--as-needed -Wl,--dynamic-linker=$glibc_dynamic_linker -static-libstdc++"
+# CONFIGFLAGS
+CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests"
+case "$HOST" in
+ *linux*) CONFIGFLAGS+=" --enable-glibc-back-compat" ;;
+esac
+
+# CFLAGS
+HOST_CFLAGS="-O2 -g"
+case "$HOST" in
+ *linux*) HOST_CFLAGS+=" -ffile-prefix-map=${PWD}=." ;;
+ *mingw*) HOST_CFLAGS+=" -fno-ident" ;;
+esac
+
+# CXXFLAGS
+HOST_CXXFLAGS="$HOST_CFLAGS"
+
+# LDFLAGS
+case "$HOST" in
+ *linux*) HOST_LDFLAGS="-Wl,--as-needed -Wl,--dynamic-linker=$glibc_dynamic_linker -static-libstdc++ -Wl,-O2" ;;
+ *mingw*) HOST_LDFLAGS="-Wl,--no-insert-timestamp" ;;
+esac
# Make $HOST-specific native binaries from depends available in $PATH
export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
@@ -160,7 +199,7 @@ export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
${CONFIGFLAGS} \
CFLAGS="${HOST_CFLAGS}" \
CXXFLAGS="${HOST_CXXFLAGS}" \
- LDFLAGS="${HOST_LDFLAGS}"
+ ${HOST_LDFLAGS:+LDFLAGS="${HOST_LDFLAGS}"}
sed -i.old 's/-lstdc++ //g' config.status libtool src/univalue/config.status src/univalue/libtool
@@ -169,9 +208,21 @@ export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
# Perform basic ELF security checks on a series of executables.
make -C src --jobs=1 check-security ${V:+V=1}
- # Check that executables only contain allowed gcc, glibc and libstdc++
- # version symbols for Linux distro back-compatibility.
- make -C src --jobs=1 check-symbols ${V:+V=1}
+
+ case "$HOST" in
+ *linux*|*mingw*)
+ # Check that executables only contain allowed gcc, glibc and libstdc++
+ # version symbols for Linux distro back-compatibility.
+ make -C src --jobs=1 check-symbols ${V:+V=1}
+ ;;
+ esac
+
+ # Make the os-specific installers
+ case "$HOST" in
+ *mingw*)
+ make deploy ${V:+V=1}
+ ;;
+ esac
# Setup the directory where our Bitcoin Core build for HOST will be
# installed. This directory will also later serve as the input for our
@@ -180,9 +231,21 @@ export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
mkdir -p "${INSTALLPATH}"
# Install built Bitcoin Core to $INSTALLPATH
make install DESTDIR="${INSTALLPATH}" ${V:+V=1}
+
+ case "$HOST" in
+ *mingw*)
+ cp -f --target-directory="$OUTDIR" ./*-setup-unsigned.exe
+ ;;
+ esac
(
cd installed
+ case "$HOST" in
+ *mingw*)
+ mv --target-directory="$DISTNAME"/lib/ "$DISTNAME"/bin/*.dll
+ ;;
+ esac
+
# Prune libtool and object archives
find . -name "lib*.la" -delete
find . -name "lib*.a" -delete
@@ -196,19 +259,60 @@ export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
find "${DISTNAME}/lib" -type f -print0
} | xargs -0 -n1 -P"$MAX_JOBS" -I{} "${DISTSRC}/contrib/devtools/split-debug.sh" {} {} {}.dbg
- cp "${DISTSRC}/doc/README.md" "${DISTNAME}/"
+ case "$HOST" in
+ *mingw*)
+ cp "${DISTSRC}/doc/README_windows.txt" "${DISTNAME}/readme.txt"
+ ;;
+ *linux*)
+ cp "${DISTSRC}/doc/README.md" "${DISTNAME}/"
+ ;;
+ esac
# Finally, deterministically produce {non-,}debug binary tarballs ready
# for release
- find "${DISTNAME}" -not -name "*.dbg" -print0 \
- | sort --zero-terminated \
- | tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
- | gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" \
- || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" && exit 1 )
- find "${DISTNAME}" -name "*.dbg" -print0 \
- | sort --zero-terminated \
- | tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
- | gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" \
- || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" && exit 1 )
+ case "$HOST" in
+ *mingw*)
+ find "${DISTNAME}" -not -name "*.dbg" -print0 \
+ | xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}"
+ find "${DISTNAME}" -not -name "*.dbg" \
+ | sort \
+ | zip -X@ "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}.zip" \
+ || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}.zip" && exit 1 )
+ find "${DISTNAME}" -name "*.dbg" -print0 \
+ | xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}"
+ find "${DISTNAME}" -name "*.dbg" \
+ | sort \
+ | zip -X@ "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}-debug.zip" \
+ || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}-debug.zip" && exit 1 )
+ ;;
+ *linux*)
+ find "${DISTNAME}" -not -name "*.dbg" -print0 \
+ | sort --zero-terminated \
+ | tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
+ | gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" \
+ || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" && exit 1 )
+ find "${DISTNAME}" -name "*.dbg" -print0 \
+ | sort --zero-terminated \
+ | tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
+ | gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" \
+ || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" && exit 1 )
+ ;;
+ esac
)
)
+
+case "$HOST" in
+ *mingw*)
+ cp -rf --target-directory=. contrib/windeploy
+ (
+ cd ./windeploy
+ mkdir unsigned
+ cp --target-directory=unsigned/ "$OUTDIR"/bitcoin-*-setup-unsigned.exe
+ find . -print0 \
+ | sort --zero-terminated \
+ | tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
+ | gzip -9n > "${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz" \
+ || ( rm -f "${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz" && exit 1 )
+ )
+ ;;
+esac
diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm
index 23b656cad7..86c1a8d27f 100644
--- a/contrib/guix/manifest.scm
+++ b/contrib/guix/manifest.scm
@@ -10,11 +10,14 @@
(gnu packages file)
(gnu packages gawk)
(gnu packages gcc)
+ (gnu packages installers)
(gnu packages linux)
+ (gnu packages mingw)
(gnu packages perl)
(gnu packages pkg-config)
(gnu packages python)
(gnu packages shells)
+ (guix build-system gnu)
(guix build-system trivial)
(guix gexp)
(guix packages)
@@ -23,7 +26,10 @@
(define (make-ssp-fixed-gcc xgcc)
"Given a XGCC package, return a modified package that uses the SSP function
-from glibc instead of from libssp.so. Taken from:
+from glibc instead of from libssp.so. Our `symbol-check' script will complain if
+we link against libssp.so, and thus will ensure that this works properly.
+
+Taken from:
http://www.linuxfromscratch.org/hlfs/view/development/chapter05/gcc-pass1.html"
(package
(inherit xgcc)
@@ -104,8 +110,7 @@ chain for " target " development."))
(base-gcc-for-libc gcc-5)
(base-kernel-headers linux-libre-headers-4.19)
(base-libc glibc-2.27)
- (base-gcc (make-gcc-rpath-link
- (make-ssp-fixed-gcc gcc-9))))
+ (base-gcc (make-gcc-rpath-link gcc-9)))
"Convenience wrapper around MAKE-CROSS-TOOLCHAIN with default values
desirable for building Bitcoin Core release binaries."
(make-cross-toolchain target
@@ -114,45 +119,77 @@ desirable for building Bitcoin Core release binaries."
base-libc
base-gcc))
+(define (make-gcc-with-pthreads gcc)
+ (package-with-extra-configure-variable gcc "--enable-threads" "posix"))
+
+(define (make-mingw-pthreads-cross-toolchain target)
+ "Create a cross-compilation toolchain package for TARGET"
+ (let* ((xbinutils (cross-binutils target))
+ (pthreads-xlibc mingw-w64-x86_64-winpthreads)
+ (pthreads-xgcc (make-gcc-with-pthreads
+ (cross-gcc target
+ #:xgcc (make-ssp-fixed-gcc gcc-9)
+ #:xbinutils xbinutils
+ #:libc pthreads-xlibc))))
+ ;; Define a meta-package that propagates the resulting XBINUTILS, XLIBC, and
+ ;; XGCC
+ (package
+ (name (string-append target "-posix-toolchain"))
+ (version (package-version pthreads-xgcc))
+ (source #f)
+ (build-system trivial-build-system)
+ (arguments '(#:builder (begin (mkdir %output) #t)))
+ (propagated-inputs
+ `(("binutils" ,xbinutils)
+ ("libc" ,pthreads-xlibc)
+ ("gcc" ,pthreads-xgcc)))
+ (synopsis (string-append "Complete GCC tool chain for " target))
+ (description (string-append "This package provides a complete GCC tool
+chain for " target " development."))
+ (home-page (package-home-page pthreads-xgcc))
+ (license (package-license pthreads-xgcc)))))
+
+
(packages->manifest
- (list ;; The Basics
- bash-minimal
- which
- coreutils
- util-linux
- ;; File(system) inspection
- file
- grep
- diffutils
- findutils
- ;; File transformation
- patch
- gawk
- sed
- ;; Compression and archiving
- tar
- bzip2
- gzip
- xz
- zlib
- ;; Build tools
- gnu-make
- libtool
- autoconf
- automake
- pkg-config
- ;; Scripting
- perl
- python-3.7
- ;; Native gcc 9 toolchain targeting glibc 2.27
- (make-gcc-toolchain gcc-9 glibc-2.27)
- ;; Cross gcc 9 toolchains targeting glibc 2.27
- (make-bitcoin-cross-toolchain "i686-linux-gnu")
- (make-bitcoin-cross-toolchain "x86_64-linux-gnu")
- (make-bitcoin-cross-toolchain "aarch64-linux-gnu")
- (make-bitcoin-cross-toolchain "arm-linux-gnueabihf")
- ;; The glibc 2.27 for riscv64 needs gcc 7 to successfully build (see:
- ;; https://www.gnu.org/software/gcc/gcc-7/changes.html#riscv). The final
- ;; toolchain is still a gcc 9 toolchain targeting glibc 2.27.
- (make-bitcoin-cross-toolchain "riscv64-linux-gnu"
- #:base-gcc-for-libc gcc-7)))
+ (append
+ (list ;; The Basics
+ bash-minimal
+ which
+ coreutils
+ util-linux
+ ;; File(system) inspection
+ file
+ grep
+ diffutils
+ findutils
+ ;; File transformation
+ patch
+ gawk
+ sed
+ ;; Compression and archiving
+ tar
+ bzip2
+ gzip
+ xz
+ zlib
+ ;; Build tools
+ gnu-make
+ libtool
+ autoconf
+ automake
+ pkg-config
+ ;; Scripting
+ perl
+ python-3.7
+ ;; Native gcc 9 toolchain targeting glibc 2.27
+ (make-gcc-toolchain gcc-9 glibc-2.27))
+ (let ((target (getenv "HOST")))
+ (cond ((string-suffix? "-mingw32" target)
+ ;; Windows
+ (list zip (make-mingw-pthreads-cross-toolchain "x86_64-w64-mingw32") nsis-x86_64))
+ ((string-contains target "riscv64-linux-")
+ (list (make-bitcoin-cross-toolchain "riscv64-linux-gnu"
+ #:base-gcc-for-libc gcc-7)))
+ ((string-contains target "-linux-")
+ (list (make-bitcoin-cross-toolchain target)))
+ (else '())))))
diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py
index bcca3b7cea..73f54cd488 100755
--- a/contrib/linearize/linearize-data.py
+++ b/contrib/linearize/linearize-data.py
@@ -2,7 +2,7 @@
#
# linearize-data.py: Construct a linear, no-fork version of the chain.
#
-# Copyright (c) 2013-2019 The Bitcoin Core developers
+# Copyright (c) 2013-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.
#
diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md
index 29b49ebff4..68ebb5def1 100644
--- a/contrib/macdeploy/README.md
+++ b/contrib/macdeploy/README.md
@@ -1,15 +1,139 @@
-### MacDeploy ###
+# MacOS Deployment
-For Snow Leopard (which uses [Python 2.6](http://www.python.org/download/releases/2.6/)), you will need the param_parser package:
+The `macdeployqtplus` script should not be run manually. Instead, after building as usual:
- sudo easy_install argparse
+```bash
+make deploy
+```
-This script should not be run manually, instead, after building as usual:
+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.
- make deploy
+When complete, it will have produced `Bitcoin-Qt.dmg`.
-During the process, the disk image window will pop up briefly where the fancy
-settings are applied. This is normal, please do not interfere.
+## SDK Extraction
-When finished, it will produce `Bitcoin-Qt.dmg`.
+Our current macOS SDK (`macOSX10.14.sdk`) can be extracted from
+[Xcode_10.2.1.xip](https://download.developer.apple.com/Developer_Tools/Xcode_10.2.1/Xcode_10.2.1.xip).
+An Apple ID is needed to download this.
+`Xcode.app` is packaged in a `.xip` archive.
+This makes the SDK less-trivial to extract on non-macOS machines.
+One approach (tested on Debian Buster) is outlined below:
+
+```bash
+
+apt install clang cpio git liblzma-dev libxml2-dev libssl-dev make
+
+git clone https://github.com/tpoechtrager/xar
+pushd xar/xar
+./configure
+make
+make install
+popd
+
+git clone https://github.com/NiklasRosenstein/pbzx
+pushd pbzx
+clang -llzma -lxar pbzx.c -o pbzx -Wl,-rpath=/usr/local/lib
+popd
+
+xar -xf Xcode_10.2.1.xip -C .
+
+./pbzx/pbzx -n Content | cpio -i
+
+find Xcode.app -type d -name MacOSX.sdk -exec sh -c 'tar --transform="s/MacOSX.sdk/MacOSX10.14.sdk/" -c -C$(dirname {}) MacOSX.sdk/ | gzip -9n > MacOSX10.14.sdk.tar.gz' \;
+```
+
+on macOS the process is more straightforward:
+
+```bash
+xip -x Xcode_10.2.1.xip
+tar -s "/MacOSX.sdk/MacOSX10.14.sdk/" -C Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.14.sdk.tar.gz MacOSX.sdk
+```
+
+Our previously used macOS SDK (`MacOSX10.11.sdk`) can be extracted from
+[Xcode 7.3.1 dmg](https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/Xcode_7.3.1/Xcode_7.3.1.dmg).
+The script [`extract-osx-sdk.sh`](./extract-osx-sdk.sh) automates this. First
+ensure the DMG file is in the current directory, and then run the script. You
+may wish to delete the `intermediate 5.hfs` file and `MacOSX10.11.sdk` (the
+directory) when you've confirmed the extraction succeeded.
+
+```bash
+apt-get install p7zip-full sleuthkit
+contrib/macdeploy/extract-osx-sdk.sh
+rm -rf 5.hfs MacOSX10.11.sdk
+```
+
+## Deterministic macOS DMG Notes
+Working macOS DMGs are created in Linux by combining a recent `clang`, the Apple
+`binutils` (`ld`, `ar`, etc) and DMG authoring tools.
+
+Apple uses `clang` extensively for development and has upstreamed the necessary
+functionality so that a vanilla clang can take advantage. It supports the use of `-F`,
+`-target`, `-mmacosx-version-min`, and `--sysroot`, which are all necessary when
+building for macOS.
+
+Apple's version of `binutils` (called `cctools`) contains lots of functionality missing in the
+FSF's `binutils`. In addition to extra linker options for frameworks and sysroots, several
+other tools are needed as well such as `install_name_tool`, `lipo`, and `nmedit`. These
+do not build under Linux, so they have been patched to do so. The work here was used as
+a starting point: [mingwandroid/toolchain4](https://github.com/mingwandroid/toolchain4).
+
+In order to build a working toolchain, the following source packages are needed from
+Apple: `cctools`, `dyld`, and `ld64`.
+
+These tools inject timestamps by default, which produce non-deterministic binaries. The
+`ZERO_AR_DATE` environment variable is used to disable that.
+
+This version of `cctools` has been patched to use the current version of `clang`'s headers
+and its `libLTO.so` rather than those from `llvmgcc`, as it was originally done in `toolchain4`.
+
+To complicate things further, all builds must target an Apple SDK. These SDKs are free to
+download, but not redistributable. To obtain it, register for an Apple Developer Account,
+then download [Xcode 10.2.1](https://download.developer.apple.com/Developer_Tools/Xcode_10.2.1/Xcode_10.2.1.xip).
+
+This file is many gigabytes in size, but most (but not all) of what we need is
+contained only in a single directory:
+
+```bash
+Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk
+```
+
+See the SDK Extraction notes above for how to obtain it.
+
+The Gitian descriptors build 2 sets of files: Linux tools, then Apple binaries which are
+created using these tools. The build process has been designed to avoid including the
+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.
+
+`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.
+
+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.
+
+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`.
+
+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
+shared, we'll have to be a bit creative in order for the build process to remain somewhat
+deterministic. Here's how it works:
+
+- Builders use Gitian to create an unsigned release. This outputs an unsigned DMG which
+ users may choose to bless and run. It also outputs an unsigned app structure in the form
+ of a tarball, which also contains all of the tools that have been previously (deterministically)
+ built in order to create a final DMG.
+- The Apple keyholder uses this unsigned app to create a detached signature, using the
+ script that is also included there. Detached signatures are available from this [repository](https://github.com/bitcoin-core/bitcoin-detached-sigs).
+- Builders feed the unsigned app + detached signature back into Gitian. It uses the
+ pre-built tools to recombine the pieces into a deterministic DMG.
diff --git a/contrib/macdeploy/extract-osx-sdk.sh b/contrib/macdeploy/extract-osx-sdk.sh
index 21243ada04..3c7bdf4217 100755
--- a/contrib/macdeploy/extract-osx-sdk.sh
+++ b/contrib/macdeploy/extract-osx-sdk.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2016-2019 The Bitcoin Core developers
+# Copyright (c) 2016-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.
diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py
index d516ca10c1..e8698994f1 100755
--- a/contrib/seeds/makeseeds.py
+++ b/contrib/seeds/makeseeds.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2013-2019 The Bitcoin Core developers
+# Copyright (c) 2013-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.
#
@@ -33,7 +33,8 @@ PATTERN_AGENT = re.compile(
r"0.16.(0|1|2|3|99)|"
r"0.17.(0|0.1|1|2|99)|"
r"0.18.(0|1|99)|"
- r"0.19.99"
+ r"0.19.(0|1|99)|"
+ r"0.20.99"
r")")
def parseline(line):
diff --git a/contrib/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt
index 89eb1d1638..58f6ad10b5 100644
--- a/contrib/seeds/nodes_main.txt
+++ b/contrib/seeds/nodes_main.txt
@@ -1,645 +1,679 @@
-2.24.141.73:8333
+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.43.228.99:8333
-5.145.10.122:8333
-5.166.35.47:8333
+5.39.222.39:8333
+5.103.137.146:9333
+5.128.87.126:8333
+5.149.250.76:8333
+5.182.39.200: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.206.226.216:8333
-5.206.226.231:8333
-13.92.254.226:8335
-13.125.188.128:8333
-18.228.144.20:8333
-23.175.0.200:8333
-23.226.90.172:8333
-23.233.107.28:8333
+5.254.82.130:8333
+13.237.147.15:8333
+18.27.79.17:8333
+20.184.15.116:8433
+23.17.160.159:8333
+23.175.0.212:8333
23.245.24.154:8333
-24.121.16.35:8333
-24.150.94.79:8333
-24.188.200.170: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
-27.102.102.157:8333
31.6.98.94:8333
-31.20.226.115:8333
-31.21.182.79:8333
+31.14.201.156:8333
+31.25.241.224:8335
31.43.140.190:8333
-31.132.135.134:8333
+31.134.121.223:8333
31.173.48.61:8333
-32.214.183.114:8333
-34.231.234.150:8333
-35.209.114.159:8333
-35.213.18.190:8333
-37.97.228.224:8333
-37.116.95.41:8333
-37.123.132.33:8333
-37.133.140.169:8334
-37.134.165.205:8333
-37.191.253.125:8333
-39.108.68.237:7781
-40.78.19.149:8333
-42.60.217.183: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
-45.58.126.138: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
46.28.132.34: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.166.162.45:20001
-46.166.176.137:8333
-46.227.68.104:8333
-46.227.68.105:8333
-47.74.32.190:8885
-47.89.19.134:30303
-47.97.117.250:8333
-50.2.13.166:8333
-50.5.163.139:8333
-50.34.65.217:8333
-50.66.209.54:8333
-50.67.179.36:8333
-51.15.166.138:8333
-51.15.239.164:8333
+46.188.30.118:8333
+46.229.238.187: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.222.103.234:8333
+49.245.50.224:8333
+50.53.250.162:8333
+50.225.198.67:6000
51.154.60.34:8333
-51.154.136.60:8333
-52.116.159.247:8333
-54.167.232.37:8333
-58.22.123.120:8333
+54.242.17.7:8333
+58.146.222.198:8333
58.158.0.86:8333
-62.45.159.66:8333
-62.75.191.166:8333
-62.75.210.81: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.107.200.30:8333
+62.109.18.23:8333
+62.133.194.156:8333
62.138.0.217:8333
-62.213.214.207:8333
-64.98.18.21:8333
-65.79.145.209: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.51:8333
-66.248.206.86:8333
-67.40.207.169:8333
-67.149.252.79:8333
-67.193.189.42:8333
+66.206.13.70:8333
+66.240.237.155:8333
+66.240.237.172:8333
+67.205.140.145:8333
67.210.228.203:8333
-67.220.22.78:8333
+67.221.193.55:8333
67.222.131.151:8333
-68.168.122.2: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.70.170.178:8333
-69.132.150.43:8333
69.145.122.160:8333
-70.26.149.104:8333
-70.51.142.43:8333
-70.63.170.86:8333
-71.57.73.173:8333
-71.237.255.140:8333
-72.24.235.10:8333
-72.95.104.94:8333
-72.231.187.25:8333
-72.253.239.246:8333
-74.78.140.178:8333
-74.83.234.97: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
+72.53.134.182:8333
+73.126.97.99:8333
+74.83.126.150:8333
74.84.128.158:9333
-74.197.236.58:8333
-74.208.94.172:8333
+74.98.242.97:8333
+74.118.137.119:8333
74.220.255.190:8333
-75.101.96.6:8333
-75.157.77.34:8333
-76.93.183.209:8333
-76.174.129.203: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.85.204.149:8333
-77.120.119.27:8433
-77.134.172.81:8333
-78.42.12.201:8333
-78.58.140.102:8333
-78.108.108.162:8333
-78.119.180.62:8333
+77.119.229.106:8333
+77.120.122.22:8433
+77.120.122.114:8433
+77.163.136.136:8333
+77.220.140.74:8333
+77.247.178.130:8333
78.128.62.52:8333
-78.130.148.218:8885
-78.130.161.76:8333
+78.128.79.22:8333
+78.141.123.99:8333
78.143.214.223:8333
-79.77.33.128: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
-79.175.154.228:8333
-80.79.114.34:8333
+80.47.156.43:8333
80.89.203.172:8001
-80.100.128.128:8333
-80.122.43.78:8333
-80.151.124.127:8333
-80.167.79.174:8333
+80.93.213.246:8333
+80.111.142.213:8333
+80.147.82.165:8333
80.211.191.11:8333
-80.229.151.187:8333
+80.211.245.151:8333
+80.229.28.60:8333
+80.229.168.1:8333
+80.253.94.252:8333
81.4.102.69:8333
-81.4.102.91:8333
-81.6.34.154:8333
-81.7.16.182:8333
-81.7.17.202:8333
-81.25.71.68:8444
+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
-82.23.106.56:8333
82.29.58.109:8333
82.117.166.77:8333
-82.145.41.24:8333
+82.118.20.37:8333
+82.146.50.143:8333
82.146.153.130:8333
82.149.97.25:17567
-82.150.180.30:8333
-82.177.176.24:8333
+82.169.130.61:8333
+82.181.179.230:8333
+82.181.218.229:8333
82.194.153.233:8333
-82.197.215.125:8333
+82.195.237.253:8333
82.197.218.97:8333
+82.199.102.10:8333
82.199.102.133:8333
-82.200.205.30:8333
+82.202.197.224:8333
+82.217.245.7:8333
82.221.111.136:8333
-83.32.70.197:8333
-83.58.134.138:8333
-83.85.131.168:8333
-83.163.211.75:8333
+83.89.27.50:8333
+83.89.250.69:8333
+83.167.27.4:8333
83.208.254.182:8333
-83.243.191.199:8333
-84.46.116.71:8333
-84.52.255.147:8333
-84.56.105.17:8333
-84.59.243.22:8333
-84.197.198.167:8333
-84.214.74.65:8333
-84.217.160.164:8333
-84.227.14.62:8333
-84.246.200.122:8333
-85.14.79.26: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.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
+85.184.138.108:8333
85.190.0.5:8333
-85.192.173.14:8333
-85.214.80.203:8333
-85.214.204.63:8333
-85.229.166.15:8333
-85.233.38.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.241.106.203:8333
+86.15.38.61:8333
86.76.7.132:8333
-86.80.62.194:8333
-86.107.204.50:8333
-86.139.248.102:8333
87.79.68.86:8333
87.79.94.221:8333
-87.99.79.123:8333
-87.104.127.153:8333
-87.117.19.226:8333
+87.118.116.237:8333
87.120.8.5:20008
-87.224.163.66:8333
+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.141:8333
-88.86.243.241:8333
-88.87.93.52:1691
-88.98.198.130:8333
-88.99.109.66:8333
-88.119.128.36:8333
-88.129.253.46:8333
+88.86.116.142:8333
+88.88.13.249: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.23.35.9:8333
-89.47.217.222:8333
+89.25.80.42:8333
+89.28.117.31:8333
89.106.199.38:8333
89.142.75.60:8333
-89.179.126.97:8333
+89.190.19.162:8333
89.212.9.96:8333
-89.218.198.46:8333
-89.230.96.42:8333
-90.125.157.153:8333
-90.146.97.100:8333
+89.212.75.6:8333
+89.248.250.12:8333
+90.94.83.26:8333
90.182.165.18:8333
-90.227.130.6:8333
-91.92.128.32:8333
-91.123.82.15:8333
-91.135.0.187:8333
-91.152.121.138:8333
-91.178.131.108:8333
91.185.198.234:8333
-91.193.237.88:8333
-91.202.133.75:8885
+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.219.25.232:8333
91.222.128.59:8333
-92.62.231.253:8333
-92.63.192.206:8333
-92.63.197.243:8333
-92.63.197.245:8333
-92.119.112.59:8333
-92.243.244.101:8333
+92.18.180.225:8333
+92.53.89.123:8333
+92.240.69.195:8333
+92.249.143.44:8333
92.255.176.109:8333
-93.38.119.141:8333
-93.50.177.66:8333
-93.79.204.222:10333
-93.115.28.30:11100
-93.115.89.76: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.123.180.164:8333
-93.126.94.192:8333
-93.170.128.106:8333
-93.185.103.70:8333
-93.189.145.169:8333
-93.190.142.127:8333
-93.228.3.234:8333
-94.19.128.204:8333
-94.26.49.71:8333
-94.63.65.127:8333
-94.72.143.28:8333
-94.104.217.250:8333
-94.209.115.52:8333
-94.237.72.166:8333
+93.175.204.121:8333
+93.180.178.213:8333
+94.19.7.55: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
95.69.249.63:8333
95.79.35.133:8333
95.87.226.56:8333
-95.91.80.140:8333
-95.102.60.168:8333
-95.154.90.99:8333
+95.90.3.210:8333
+95.110.234.93:8333
95.156.252.34:8333
-95.165.175.75:8333
-95.174.125.24:18333
-95.183.54.101:12853
95.211.189.3:8333
-95.213.143.13:8333
-95.213.184.109:778
+95.217.9.207:8333
96.9.80.109:8333
-96.47.122.171:8333
-97.81.244.191:8333
-97.99.13.150:8333
+96.245.218.247:8333
97.104.206.3:8333
-98.116.105.49:8333
-99.224.131.4:8333
-101.92.39.116:8333
-101.100.163.118:8327
+98.29.195.204:8333
+99.231.196.126:8333
101.100.174.24:8333
-101.251.68.146:12337
-102.132.229.253:8333
+101.100.174.240:8333
103.14.244.190:8333
-103.16.128.63:8333
-103.59.144.135:8333
-103.59.144.238:8333
+103.37.205.47:8333
+103.60.109.184:20008
+103.84.84.250:8335
+103.85.190.218:20000
103.99.168.100:8333
103.99.168.130:8333
-103.100.220.46:8333
-103.105.56.82:8333
-103.106.208.207:8333
-103.106.211.107:8333
-103.108.228.51:8333
-104.11.144.71:8333
-104.128.228.252:8333
-104.152.204.204:8333
-104.153.30.236:8333
-104.155.233.13:8333
-104.198.126.116:8333
-104.245.125.251:8333
-106.12.57.72:8333
-106.72.36.96:46289
-106.163.158.127:8333
-107.150.41.179:8333
-107.191.116.103:8333
-108.15.243.207:8333
+103.214.146.86: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
-108.160.202.208:8333
-108.213.205.103:8333
+108.183.77.12:8333
109.72.83.127:8333
109.99.63.159:8333
-109.104.8.48:8333
-109.183.251.77:8333
-109.198.191.22:8333
-109.236.90.122:58333
+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.248.206.13:8333
-109.252.133.57:8333
-111.90.145.57:8333
-111.90.159.184:50001
-113.35.179.149:8333
+111.40.4.103:8333
+111.90.140.217:8333
+111.90.158.212:8333
+112.213.103.98:8333
113.52.135.125:8333
115.47.141.250:8885
115.70.110.4:8333
-116.58.171.67:8333
-118.1.96.81:8333
-118.103.126.140:28333
-119.29.54.159:8333
-119.207.78.152:8333
-121.211.151.99:8333
+116.87.15.244: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
122.112.148.153:8339
+122.116.42.140:8333
124.160.119.93:8333
-128.197.128.222:8333
+125.236.215.133:8333
129.13.189.212:8333
129.97.243.18:8333
130.185.77.105:8333
-130.255.187.86:8333
-131.114.10.236:8333
+131.114.10.233:8333
131.188.40.34:8333
132.249.239.163:8333
-133.18.1.114:8333
134.19.186.195:8333
-136.36.123.20:8333
-136.56.42.119:8333
+134.249.187.97:8333
+136.144.215.219:8333
137.226.34.46:8333
-138.68.20.137:8333
+139.9.249.234:8333
141.101.8.36:8333
-145.239.9.3:8333
-145.249.106.103:8333
-146.255.227.182:4033
-147.192.18.175:8333
-147.253.54.26:8333
-148.66.58.58:8333
-148.70.82.85:8333
-149.90.34.119:8333
-150.143.231.72:8333
+143.89.121.207:8333
+143.176.224.104: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
-153.124.187.220:8333
-154.209.1.138:8333
-154.211.159.200:8333
-155.4.52.45:8333
+154.52.98.2:8444
+155.4.116.169:8333
156.19.19.90:8333
-157.7.211.107:8333
+156.34.178.138:8333
+157.13.61.66:8333
+157.13.61.67:8333
+158.181.226.33:8333
+159.100.242.254:8333
159.100.248.234:8333
-159.138.45.220:22235
+159.253.98.209:8333
160.16.0.30:8333
-162.154.207.147:8333
-163.158.243.230:8333
-166.62.82.103:32771
+160.20.145.62:8333
+162.62.18.226:8333
+162.62.26.218:8333
+162.209.88.174:8333
+162.244.80.208:8333
+163.158.202.112:8333
+163.172.181.191:8333
166.62.100.55:8333
-167.179.136.11:8333
+167.114.35.12:8333
+168.62.167.209:8200
168.235.74.110:8333
-169.55.182.185:8333
-171.33.177.9:8333
+168.235.90.188:8333
+170.249.37.243:8333
172.99.120.113:8333
-172.105.112.233:8333
-172.110.30.81:8333
173.21.218.95:8333
-173.23.103.30:8000
173.51.177.2:8333
-173.89.28.137:8333
+173.95.72.234:8333
173.208.128.10:8333
-173.249.11.207:18333
+173.209.44.34:8333
+173.231.57.194:8333
+173.255.204.124:8333
174.65.135.60:8333
-176.38.7.43:8333
-176.92.150.12:8333
+174.94.155.224:8333
+174.115.120.186:8333
+176.53.160.170:8333
+176.85.188.213:8333
176.99.2.207:8333
-176.126.167.10:8333
-176.212.185.153:8333
-176.223.136.171:8333
-177.52.173.62:8333
-178.33.136.162:8333
-178.128.39.110:8333
-178.143.50.8:8333
-178.198.60.155:8333
-178.236.137.63: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
+178.255.42.126:8333
179.48.251.41:8333
-180.150.52.37:8333
+180.150.73.100:8333
+181.47.220.242:8333
+181.170.139.47:8333
+183.110.220.210:30301
183.230.93.139:8333
-184.80.255.250:8333
-184.95.58.166:8336
-184.180.129.98:8333
-185.19.28.195:8333
-185.25.48.184:8333
+184.95.58.164:8663
+184.164.147.82:41333
+185.15.92.18:20993
185.25.60.199:8333
-185.50.68.64:8333
-185.53.158.12:8333
-185.61.79.213:8333
+185.52.3.185:8333
+185.61.138.4:8333
185.64.116.15:8333
+185.83.110.53:8333
+185.83.214.123:8333
185.95.219.53:8333
-185.130.215.73:8333
-185.130.215.187:8333
-185.141.60.127:8333
-185.147.11.108:8333
-185.154.159.164:9992
-185.198.56.77: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.148.3.227:8333
+185.157.160.220:8333
+185.163.44.44:8333
+185.176.221.32:8333
+185.186.208.162:8333
+185.198.58.47:8333
185.198.59.183:8333
-185.216.140.33:8333
-185.217.241.142:8333
-185.249.199.106:8333
+185.215.224.22:8333
+185.232.28.254:8333
+185.239.236.116:8333
+185.251.161.54:8333
188.42.40.234:18333
188.65.212.138:8333
-188.65.212.211:8333
+188.65.212.157:8333
188.68.45.143:8333
-188.120.246.125:8333
-188.134.5.47:8333
-188.134.6.84:8333
-188.167.101.51:8333
-188.175.77.16:8333
-188.213.168.152:8333
-188.230.245.188:8333
-189.121.185.148:8333
+188.127.229.105:8333
+188.131.177.130: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
-190.184.198.34:8333
-190.210.234.38:8333
-190.218.190.85:8333
+191.209.21.188:8333
192.3.11.20:8333
192.3.11.24:8333
+192.34.56.59:8333
+192.65.170.15:8333
+192.65.170.50:8333
+192.146.137.18:8333
192.166.47.32:8333
-192.167.149.143:8333
192.169.94.29:8333
-192.169.94.70:8333
-192.198.90.98:8333
-192.254.89.134:8333
-192.254.89.220:8333
-193.41.78.125:8333
-193.46.83.8:8333
+192.227.80.83:8333
+192.254.65.126:8333
+193.10.203.23:8334
+193.29.57.4:8333
+193.58.196.212:8333
193.59.41.11:8333
-193.77.135.181:8333
193.84.116.22:8333
+193.108.131.43:8333
+193.148.71.10:8333
+193.169.244.190:8333
+193.194.163.35:8333
193.194.163.53:8333
-194.71.225.55:8333
+194.5.159.197:8333
+194.14.246.205:8333
+194.135.92.96:8333
194.135.135.69:8333
194.158.92.150:8333
-195.13.220.165:8333
+194.187.251.163:31239
+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.168.36.20:8333
-195.201.33.0:8333
-195.202.169.149:8333
-195.242.93.189:8333
+195.154.113.90:8333
+195.206.20.114:8333
+195.206.105.42:8333
+195.209.249.164:8333
+195.224.116.20:8333
198.1.231.6:8333
-198.44.231.160:6333
-198.54.113.59:8333
198.251.83.19:8333
-199.68.199.4:8333
-199.247.1.117:8333
-199.247.10.26: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
-201.241.2.85:8333
-202.185.45.110:8333
-203.86.207.53:8333
+200.87.116.213:8333
+202.28.194.82:8333
+202.55.87.45:8333
203.130.48.117:8885
+203.132.95.10:8333
204.14.245.180:8333
-204.111.241.195:8333
204.152.203.98:8333
-205.185.122.150:8333
-206.124.149.66:8333
-207.182.154.178:8333
-208.81.1.105:8333
-209.133.201.114:8333
-209.173.25.140:8333
-209.180.174.200:8333
-209.190.36.13:8333
-210.54.38.227:8333
-210.54.39.99:8333
-210.203.222.52:8223
-211.104.154.140:8333
-212.24.103.20:8333
-212.33.204.190:8333
-212.51.156.139:8333
-212.109.198.126:8333
-212.237.96.98:8333
+205.209.162.98:8333
+206.221.178.149:8333
+208.110.99.105: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.37.92.163:8333
-213.89.98.199:8333
-213.89.150.13:8333
-213.174.156.72:8333
-213.209.123.165:8333
+213.21.15.22:8333
+213.136.83.8:8333
213.227.152.108:8333
-216.38.129.164:8333
-216.86.154.215:8333
-216.93.139.63:8333
-216.186.250.53:8333
+213.254.23.116:8333
+216.108.236.180:8333
216.194.165.98:8333
-217.22.132.220:8333
-217.43.72.105:8333
+216.236.164.82:8333
+217.16.185.165:8333
+217.21.24.146:8333
+217.26.32.10:8333
217.64.47.138:8333
-217.69.145.234:8333
-217.158.9.102:8333
-220.130.142.178:33389
+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
-[2001:1ba8:401:32:b842:3891:5915:c68f]:8333
+221.130.29.230:18421
+222.122.49.40:8333
+222.186.169.1:8333
+222.222.43.29:8333
+223.16.30.175: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:4128:6135:e001:5054:ff:fe37:e9eb]:8333
-[2001:41d0:fc63:9c00:1acc:d22f:3f5c:ef7f]: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:470:a:c13::2]:8333
[2001:4800:7821:101:be76:4eff:fe04:9f50]:8333
-[2001:4801:7819:74:b745:b9d5:ff10:a61a]:8333
-[2001:4801:7821:77:be76:4eff:fe10:c7f6]:8333
+[2001:4801:7819:74:b745:b9d5:ff10:aaec]:8333
[2001:48d0:1:2163:0:ff:febe:5a80]:8333
-[2001:48f8:1003::3ba]:8333
[2001:4ba0:fffa:5d::93]:8333
-[2001:4c48:2:a328:d8a7:e0ff:fe96:403a]:8333
-[2001:56b:dda9:4b00:49f9:121b:aa9e:de30]:8333
[2001:638:a000:4140::ffff:191]:8333
[2001:678:7dc:8::2]:8333
[2001:678:ec:1:250:56ff:fea7:47e9]:8333
+[2001:67c:10ec:2a49:8000::1082]:8333
[2001:67c:16dc:1201:5054:ff:fe17:4dac]:8333
[2001:67c:21ec:1000::a]:8333
-[2001:67c:22fc:1337::5]:8333
-[2001:67c:2824:8001:225:90ff:fe67:9830]:7777
-[2001:67c:2b5c:101:216:3eff:fea3:5234]:8333
-[2001:67c:2db8:13::83]: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:718:801:311:5054:ff:fe19:c483]:8333
-[2001:8003:d136:1001::11:ffd1]:8333
-[2001:8d8:96a:9300::ad:ae2c]:8333
-[2001:8f1:1602:700:1b28:a3e3:bb08:a708]:9444
-[2001:8f8:1327:1587:3f10:5ab:804d:4039]:8333
+[2001:818:e245:f800:4df:2bdf:ecf5:eb60]: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:e42:103:100::30]:8333
-[2400:2650:480:bc00:bcaf:7c49:8c9e:7cdf]: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:4052:e20:4f00:69fe:bb33:7b1c:a1ca]:8333
-[2400:8902::f03c:91ff:fea5:ebb7]:8333
-[2401:1800:7800:102:be76:4eff:fe1c:a7d]:8333
[2401:2500:203:184::15]:8333
[2401:3900:2:1::2]:8333
-[2402:7340:1:56::d0d]:8333
-[2405:9800:ba01:251a:c53c:b80a:320d:5b41]:8333
+[2401:a400:3200:5600:14ee:f361:4bdc:1f7c]:8333
+[2401:d002:4402:0:8f28:591a:6ea0:c683]:8333
+[2402:cb40:1000:504::dead]:8333
[2405:aa00:2::40]:8333
[2409:10:ca20:1df0:224:e8ff:fe1f:60d9]:8333
-[2409:13:1200:d200:16da:e9ff:fee9:b19a]:8333
-[240d:1a:3c0:ab00:e9f1:87c:93ac:7687]:8333
-[2602:ffc5:1f::1f:9211]:8333
-[2604:2000:ffc0:0:5862:b6f8:fe72:762f]: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
+[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
[2604:4300:a:2e:21b:21ff:fe11:392]:8333
+[2604:5500:c134:4000::3fc]:32797
[2604:5500:c2a3:7b00:cc6:373b:44a8:caa4]:8333
-[2605:9880:201:17::4b7c]:8333
+[2604:6000:6e85:4a01:a82d:f9ff:fef5:28b9]:8333
+[2604:7780:303:80::80]:8333
+[2605:4d00::50]:8333
+[2605:9880:0:777:225:90ff:fefc:8958]: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:9280:b:73b:250:56ff:fe21:bf32]: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:f3a0:1000:9:f82a:fdff:fea1:3315]:8333
-[2607:f470:8:1048:ae1f:6bff:fe68:5e42]:8333
-[2607:fd70:4a:babe:b00b:1e5:1bd5:f78]:8333
-[2607:ff50:0:71::13]:8333
+[2607:f188:0:4:eef4:bbff:fecc:6668]:8333
+[2607:f2c0:e1e2:11:1044:9b7a:b81e:1d74]:8333
+[2607:f470:8:1048:ae1f:6bff:fe70:7240]: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
-[2a00:1328:e101:c00::163]: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
[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:2c::3e95]:8333
-[2a00:1b60:2:4:40d0:eff:fe88:ebd4]:8333
+[2a00:1838:36:142::ec73]: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:7b80:454:2000::101]:8333
[2a00:8a60:e012:a00::21]:8333
-[2a01:4240:5f52:9246::1]: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
[2a01:430:17:1::ffff:1153]:8333
[2a01:488:66:1000:53a9:1573:0:1]:8333
-[2a01:6f0:ffff:120::8dcb]: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:7a7:2:131b:20c:29ff:fe9a:3922]:8333
-[2a01:7c8:d002:318:5054:ff:febe:cbb1]:8333
+[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:d0:ffff:7368::2]:8333
-[2a01:e0a:182:1300:591e:529:b376:c654]:8333
+[2a01:d0:bef2::12]:8333
+[2a01:d0:f34f:1:1f67:e250:6aeb:b9c4]:8333
[2a01:e34:ee6b:2ab0:88c2:1c12:f4eb:c26c]:8333
-[2a02:1205:34c3:d890:c0e:741e:c45f:3605]:8333
-[2a02:2c8:1:400:34::184]:8333
-[2a02:2f0d:202:f900:5e9a:d8ff:fe57:8bc5]: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
+[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:390:9000:0:218:7dff:fe10:be33]:8333
-[2a02:4780:9:0:2:f928:f280:9a6f]:8333
+[2a02:4780:8:6:2:354e:1256:7a04]:8333
[2a02:578:4f07:24:76ad:cef7:93c1:b9b9]:8333
-[2a02:7aa0:1619::590:eba2]: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:c207:2014:9913::1]:18333
[2a02:e00:fff0:23f::1]:8333
-[2a02:f680:1:1100::5453]:8333
+[2a02:e00:fff0:23f::a]:8333
[2a03:1b20:1:f410:40::3e]:16463
-[2a03:2260:11e:301::8]:8333
-[2a03:2260:11e:302::3]:8333
-[2a03:4000:6:416c::43]:8333
+[2a03:6000:870:0:46:23:87:218]:8333
+[2a03:9da0:f6:1::2]:8333
+[2a03:e2c0:1ce::2]:8333
+[2a04:2180:0:2::f2]:8333
[2a04:2180:1:c:f000::15]:8333
-[2a04:3543:1000:2310:8492:b8ff:fe91:22e8]:8333
-[2a05:6d40:b94e:d100:225:90ff:fe0d:cfc2]:8333
-[2a05:fc87:4::6]:8333
+[2a04:52c0:101:97f::dcbe]: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
-[2a0b:2ac0:1:0:d6ae:52ff:fe7b:741c]:8333
-[2a0b:2ac0:1:0:d6ae:52ff:fe7b:88eb]:8333
-25lhwv6jaqbtek5x.onion:8333
+[2a07:b400:1:34c::2:1002]:8333
+[2a0b:ae40:3:4a0a::15]:8333
+[2a0e:b780::55d1:f05b]:8333
+[2c0f:fce8:0:400:b7c::1]:8333
2empatdfea6vwete.onion:8333
-2hpjn6ndxjafgoej.onion:8333
34aqcwnnuiqh234f.onion:8333
-3frtobxxkgkhwjx7.onion:8333
3gxqibajrtysyp5o.onion:8333
-3lf37sdzhpxh6fpv.onion:8333
-3q5iydjrrutqjb2y.onion:8333
-3qzrkpxduf44jqg5.onion:8333
3sami4tg4yhctjyc.onion:8333
3w77hrilg6q64opl.onion:8333
46xh2sbjsjiyl4fu.onion:8333
4ee44qsamrjpywju.onion:8333
-4gwvtoppsaffaxg7.onion:8333
4haplrtkprjqhm2j.onion:8333
4u3y3zf2emynt6ui.onion:8333
-4wx34hn3kybujklg.onion:8333
-56czufbruq46sb2c.onion:8333
57dytizbai7o4kq7.onion:8333
5guaeulc7xm4g2mm.onion:8334
5mtvd4dk62ccdk4v.onion:8333
-5nsfm4nqqzzprjrp.onion:8333
5pmjz6mmikyabaw5.onion:8333
6eurcxoqsa4qpiqq.onion:8333
6ivvkeseojsmpby4.onion:8333
-6luc7owlbbaj52lr.onion:8333
6tlha6njtcuwpfa3.onion:8333
6ymgbvnn6d5nfmv4.onion:8333
-6z5cyaswulhxcvhj.onion:8333
72y2n5rary4mywkz.onion:8333
-7a354g25lnvry4ic.onion:8333
7b75ub5dapphemit.onion:8333
7xaqpr7exrtlnjbb.onion:8333
a64haiqsl76l25gv.onion:8333
@@ -650,103 +684,64 @@ akinbo7tlegsnsxn.onion:8333
anem5aq4cr2zl7tz.onion:8333
at3w5qisczgguije.onion:8333
auo4zjsp44vydv6c.onion:8333
-b6vrxhrrle7jxiua.onion:8333
-bitcoinranliixsu.onion:8333
-blcktrgve5vetjsk.onion:8333
bowg4prf63givea4.onion:8333
-cj2nexmwocyy5unq.onion:8333
cjuek22p4vv4hzbu.onion:8333
cklaa2xdawrb75fg.onion:8333
coxiru76nnfw3vdj.onion:8333
-cqwcyvvk5xnqv3yw.onion:8333
cwq2fuc54mlp3ojc.onion:8333
dganr7dffsacayml.onion:8333
djbsspmvlc6ijiis.onion:8333
dmfwov5ycnpvulij.onion:8333
dp2ekfbxubpdfrt4.onion:8333
dw2ufbybrgtzssts.onion:4333
-dxv5u4xaeydpbrrp.onion:8333
edkmfeaapvavhtku.onion:8333
ejdoey3uay3cz7bs.onion:8333
eladlvwflaahxomr.onion:8333
ffhx6ttq7ejbodua.onion:8333
-fqdzxl4kjboae35b.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
-hz26wamjlbd7arrl.onion:8333
i5ellwzndjuke242.onion:8333
iapvpwzs4gpbl6fk.onion:8885
if7fsvgyqwowxkcn.onion:8333
ilukzjazxlxrbuwy.onion:8333
-ju5duo3r6p6diznc.onion:8333
-k3i3suxlg4w27uas.onion:8333
-k7omfveynnjg674e.onion:8333
-ko37ti7twplktxqu.onion:8333
kswfyurnglm65u7b.onion:8333
ldu2hbiorkvdymja.onion:8333
-lftugyhf6vnouikf.onion:8333
-ln3csnn6774nzgyn.onion:8333
-lvh7k53s62frc6ro.onion:8333
lvvgedppmpigudhz.onion:8333
-mbjkotfqcn5gnsrm.onion:8333
mk3bnep5ubou7i44.onion:8333
muhp42ytbwi6qf62.onion:8333
n5khsbd6whw7ooip.onion:8333
-na6otugfitr7pnlv.onion:8333
-nclrhbeertvin7cu.onion:8333
ndmbrjcvu2s6jcom.onion:8333
nf4iypnyjwfpcjm7.onion:8333
nkdw6ywzt3dqwxuf.onion:8333
-nqmxpgrpuysullkq.onion:8333
-ntml2aeumyglyjlk.onion:8333
o4sl5na6jeqgi3l6.onion:8333
opencubebqqx3buj.onion:8333
-oudab5q7ruclifdv.onion:8333
ovbkvgdllk3xxeah.onion:8333
pg2jeh62fkq3byps.onion:8333
-pgufebhe6mt7knqz.onion:8333
pkcgxf23ws3lwqvq.onion:8333
-po3j2hfkmf7sh36o.onion:8333
qdtau72ifwauot6b.onion:8333
qidnrqy2ozz3nzqq.onion:8333
-qpebweackyztorrm.onion:8333
-qsl3x63225alx4bt.onion:8333
readybit5veyche6.onion:8333
-rjw6vpw5ffoncxuh.onion:8333
s2epxac7ovy36ruj.onion:8333
-srkgyv5edn2pa7il.onion:8333
+satofxsc3xjadxsm.onion:8333
sv5oitfnsmfoc3wu.onion:8333
-tdlpmqnpfqehqj7c.onion:8333
-ttx7ddwltrixannm.onion:8333
uftbw4zi5wlzcwho.onion:8333
-uoailgcebjuws47e.onion:8333
-uqvucqhplwqbjrsb.onion:8333
uz3pvdhie3372vxw.onion:8333
v2x7gpj3shxfnl25.onion:8333
-vdhrg3k2akmf6kek.onion:8333
vov46htt6gyixdmb.onion:8333
-vrfs5jwtfzj2ss6n.onion:8333
-vwpcfguewxhky4iy.onion:8333
wg3b3qxcwcrraq2o.onion:8333
wgeecjm4w4ko66f7.onion:8333
wmxc6ask4a5xyaxh.onion:8333
wqrafn4zal3bbbhr.onion:8333
-xagzqmjgwgdvl2di.onion:8333
xhi5x5qc44elydk4.onion:8333
xk6bjlmgvwojvozj.onion:8333
xmgr7fsmp7bgburk.onion:8333
xocvz3dzyu2kzu6f.onion:8333
xv7pt6etwxiygss6.onion:8444
-xz563swdjd7yqymb.onion:8333
yumx7asj7feoozic.onion:8333
-yzmyolvp55rydnsm.onion:8333
-z3forfpyjyxxgfr5.onion:8333
-z5x2wes6mhbml2t5.onion:8333
zmaddsqelw2oywfb.onion:8444
-zqlojwtc4lsurgie.onion:8333
-zvwc7ad4m2dvc74x.onion:8333
diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh
index a26791f0d1..78873dc0c3 100755
--- a/contrib/verify-commits/pre-push-hook.sh
+++ b/contrib/verify-commits/pre-push-hook.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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.
diff --git a/contrib/windeploy/win-codesign.cert b/contrib/windeploy/win-codesign.cert
index 5bc5dc5809..4023a5b638 100644
--- a/contrib/windeploy/win-codesign.cert
+++ b/contrib/windeploy/win-codesign.cert
@@ -1,34 +1,34 @@
-----BEGIN CERTIFICATE-----
-MIIFcTCCBFmgAwIBAgIRALWcUnSOxv9FQW3xdaMDO6swDQYJKoZIhvcNAQELBQAw
+MIIFdDCCBFygAwIBAgIRAL98pqZb/N9LuNaNxKsHNGQwDQYJKoZIhvcNAQELBQAw
fDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQD
-ExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMTkwMzI3MDAwMDAwWhcN
-MjAwMzI2MjM1OTU5WjCBtDELMAkGA1UEBhMCQ0gxDTALBgNVBBEMBDgwMDUxCzAJ
-BgNVBAgMAlpIMRAwDgYDVQQHDAdaw7xyaWNoMRcwFQYDVQQJDA5NYXR0ZW5nYXNz
-ZSAyNzEuMCwGA1UECgwlQml0Y29pbiBDb3JlIENvZGUgU2lnbmluZyBBc3NvY2lh
-dGlvbjEuMCwGA1UEAwwlQml0Y29pbiBDb3JlIENvZGUgU2lnbmluZyBBc3NvY2lh
-dGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK04VDwiY1wxcW3E
-WTTGmnbciCwETwC96DG4qcoH2PPNsVy3dfwGh0C02Qj2vL64IfwIGUFSgREvyjZk
-CNhEuJO2e0nO0rKNNH5v/JO+P7/VYPZkF5a3uUz9ulmihULXioieHB/q0l6BmiJL
-+cYaMVfidL9Y+IJwgiTqjnpRhv1Ik083SPsu6GcfQT9MJfY/+xse2EP0l4GfdFE6
-DRcWjiC8UHpfpGYcImzSFZZpbFbqoAyhueCl28QU4f8QAbS6BqNfaAK9MMACWDcK
-eTz3C5JK6CiUxOnGIxilXhljuybFUjR4jGl5eTRpuPWk95NTTYS36q+bx/1nYelx
-0n4nnDMCAwEAAaOCAbMwggGvMB8GA1UdIwQYMBaAFA7hOqhTOjHVir7Bu61nGgOF
-rTQOMB0GA1UdDgQWBBRbN7ECrPCdVvh58enwy3Dix46h2jAOBgNVHQ8BAf8EBAMC
-B4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzARBglghkgBhvhC
-AQEEBAMCBBAwQAYDVR0gBDkwNzA1BgwrBgEEAbIxAQIBAwIwJTAjBggrBgEFBQcC
-ARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwQwYDVR0fBDwwOjA4oDagNIYyaHR0
-cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBQ29kZVNpZ25pbmdDQS5jcmww
-cwYIKwYBBQUHAQEEZzBlMD4GCCsGAQUFBzAChjJodHRwOi8vY3J0LnNlY3RpZ28u
-Y29tL1NlY3RpZ29SU0FDb2RlU2lnbmluZ0NBLmNydDAjBggrBgEFBQcwAYYXaHR0
-cDovL29jc3Auc2VjdGlnby5jb20wKwYDVR0RBCQwIoEgam9uYXNAYml0Y29pbmNv
-cmVjb2Rlc2lnbmluZy5vcmcwDQYJKoZIhvcNAQELBQADggEBAF/AIXcFBWCC2Red
-SHN4Cvko5mdSkDNgzjVFc+OwAJ5RdOgbERde4PnHm3Qmrnx+uMetVnmrC8Fv1Iwb
-kkR0bdbWBj6lF6zMsClIN6WJEfY+qfj1qi7wyucu+3OElYRC9bm5Lf0mEHQr8lJ1
-lGvAjPh+/hmxoVNbHFMZ1Ea+BrbjVwiSznt0gzdMh0CispBZKLWCIwRwi+hFjQrw
-Z7RLH8HeCJ5Ojl/OTDQqh6AylQ7l9w9KHsUt4Jqy/AnCCyAj2/6xjdwnuo3tCZwb
-g/9CydiAacD/83odphEeC2iBa+0wsj9bWmyYKY7S9n0u+wm3wBfZbSVMDDPk/la1
-3qCUDLk=
+ExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMjAwMzI0MDAwMDAwWhcN
+MjEwMzI0MjM1OTU5WjCBtzELMAkGA1UEBhMCQ0gxDTALBgNVBBEMBDgwMDUxDjAM
+BgNVBAgMBVN0YXRlMRAwDgYDVQQHDAdaw7xyaWNoMRcwFQYDVQQJDA5NYXR0ZW5n
+YXNzZSAyNzEuMCwGA1UECgwlQml0Y29pbiBDb3JlIENvZGUgU2lnbmluZyBBc3Nv
+Y2lhdGlvbjEuMCwGA1UEAwwlQml0Y29pbiBDb3JlIENvZGUgU2lnbmluZyBBc3Nv
+Y2lhdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMtxC8N4r/jE
+OGOdFy/0UtiUvEczPZf9WYZz/7paAkc75XopHIE5/ssmoEX27gG9K00tf3Q62QAx
+inZUPWkNTh8X0l+6uSGiIBFIV7dDgztIxnPcxaqw0k7Q2TEqKJvb5qm16zX6WfXJ
+R2r6O5utUdQ3AarHnQq9fwdM1j5+ywS5u52te74ENgDMTMKUuB2J3KH1ASg5PAtO
+CjPqPL+ZXJ7eT3M0Z+Lbu5ISZSqZB48BcCwOo/fOO0dAiLT9FE1iVtaCpBKHqGmd
+glRjPzZdgDv8g28etRmk8wQ5pQmfL2gBjt/LtIgMPTdHHETKLxJO5H3y0CNx1vzL
+ql7xNMxELxkCAwEAAaOCAbMwggGvMB8GA1UdIwQYMBaAFA7hOqhTOjHVir7Bu61n
+GgOFrTQOMB0GA1UdDgQWBBSHBbl82FUJiUkXyyYJog1awYRsxjAOBgNVHQ8BAf8E
+BAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzARBglghkgB
+hvhCAQEEBAMCBBAwQAYDVR0gBDkwNzA1BgwrBgEEAbIxAQIBAwIwJTAjBggrBgEF
+BQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwQwYDVR0fBDwwOjA4oDagNIYy
+aHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBQ29kZVNpZ25pbmdDQS5j
+cmwwcwYIKwYBBQUHAQEEZzBlMD4GCCsGAQUFBzAChjJodHRwOi8vY3J0LnNlY3Rp
+Z28uY29tL1NlY3RpZ29SU0FDb2RlU2lnbmluZ0NBLmNydDAjBggrBgEFBQcwAYYX
+aHR0cDovL29jc3Auc2VjdGlnby5jb20wKwYDVR0RBCQwIoEgam9uYXNAYml0Y29p
+bmNvcmVjb2Rlc2lnbmluZy5vcmcwDQYJKoZIhvcNAQELBQADggEBAAU59qJzQ2ED
+aTMIQTsU01zIhZJ/xwQh78i0v2Mnr46RvzYrZOev+btF3SyUYD8veNnbYlY6yEYq
+Vb+/PQnE3t1xlqR80qiTZCk/Wmxx/qKvQuWeRL5QQgvsCmWBpycQ7PNfwzOWxbPE
+b0Hb2/VFFZfR9iltkfeInRUrzS96CJGYtm7dMf2JtnXYBcwpn1N8BSMH4nXVyN8g
+VEE5KyjE7+/awYiSST7+e6Y7FE5AJ4f3FjqnRm+2XetTVqITwMLKZMoV283nSEeH
+fA4FNAMGz9QeV38ol65NNqFP2vSSgVoPK79orqH9OOW2LSobt2qun+euddJIQeYV
+CMP90b/2WPc=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
diff --git a/depends/Makefile b/depends/Makefile
index f81bc3001b..5f5247f881 100644
--- a/depends/Makefile
+++ b/depends/Makefile
@@ -10,7 +10,6 @@ BASE_CACHE ?= $(BASEDIR)/built
SDK_PATH ?= $(BASEDIR)/SDKs
NO_QT ?=
NO_QR ?=
-RAPIDCHECK ?=
NO_WALLET ?=
NO_ZMQ ?=
NO_UPNP ?=
@@ -109,8 +108,6 @@ wallet_packages_$(NO_WALLET) = $(wallet_packages)
upnp_packages_$(NO_UPNP) = $(upnp_packages)
zmq_packages_$(NO_ZMQ) = $(zmq_packages)
-rapidcheck_packages_$(RAPIDCHECK) = $(rapidcheck_packages)
-
packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(wallet_packages_) $(upnp_packages_)
native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages)
@@ -118,10 +115,6 @@ ifneq ($(zmq_packages_),)
packages += $(zmq_packages)
endif
-ifeq ($(rapidcheck_packages_),)
-packages += $(rapidcheck_packages)
-endif
-
all_packages = $(packages) $(native_packages)
meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk
diff --git a/depends/README.md b/depends/README.md
index 93f619983f..79865ff011 100644
--- a/depends/README.md
+++ b/depends/README.md
@@ -46,7 +46,7 @@ The paths are automatically configured and no other options are needed unless ta
sudo apt-get install curl librsvg2-bin libtiff-tools bsdmainutils cmake imagemagick libcap-dev libz-dev libbz2-dev python3-setuptools
-#### For Win32/Win64 cross compilation
+#### For Win64 cross compilation
- see [build-windows.md](../doc/build-windows.md#cross-compilation-for-ubuntu-and-windows-subsystem-for-linux)
@@ -92,7 +92,6 @@ The following can be set when running make: make FOO=bar
NO_WALLET: Don't download/build/cache libs needed to enable the wallet
NO_UPNP: Don't download/build/cache packages needed for enabling upnp
DEBUG: disable some optimizations and enable more runtime checking
- RAPIDCHECK: build rapidcheck (experimental, requires cmake)
HOST_ID_SALT: Optional salt to use when generating host package ids
BUILD_ID_SALT: Optional salt to use when generating build package ids
diff --git a/depends/config.site.in b/depends/config.site.in
index c5731e5269..fb9bf713cc 100644
--- a/depends/config.site.in
+++ b/depends/config.site.in
@@ -59,7 +59,7 @@ PKG_CONFIG="`which pkg-config` --static"
# avoid ruining the cache. Sigh.
export PKG_CONFIG_PATH=$depends_prefix/share/pkgconfig:$depends_prefix/lib/pkgconfig
if test -z "@allow_host_packages@"; then
- export PKGCONFIG_LIBDIR=
+ export PKG_CONFIG_LIBDIR=$depends_prefix/lib/pkgconfig
fi
CPPFLAGS="-I$depends_prefix/include/ $CPPFLAGS"
diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk
index 1f88c209cf..1bc4fb8189 100644
--- a/depends/hosts/darwin.mk
+++ b/depends/hosts/darwin.mk
@@ -1,9 +1,8 @@
OSX_MIN_VERSION=10.12
-OSX_SDK_VERSION=10.11
+OSX_SDK_VERSION=10.14
OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk
-LD64_VERSION=253.9
-darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION)
-darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -stdlib=libc++
+darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK)
+darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -stdlib=libc++
darwin_CFLAGS=-pipe
darwin_CXXFLAGS=$(darwin_CFLAGS)
diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk
index cd0e70fb1c..cbe4fe4d97 100644
--- a/depends/packages/boost.mk
+++ b/depends/packages/boost.mk
@@ -22,7 +22,7 @@ $(package)_config_opts_armv7a_android=address-model=32
$(package)_toolset_$(host_os)=gcc
$(package)_archiver_$(host_os)=$($(package)_ar)
$(package)_toolset_darwin=clang-darwin
-$(package)_config_libraries=chrono,filesystem,system,thread,test
+$(package)_config_libraries=filesystem,system,thread,test
$(package)_cxxflags=-std=c++11 -fvisibility=hidden
$(package)_cxxflags_linux=-fPIC
$(package)_cxxflags_android=-fPIC
diff --git a/depends/packages/native_cctools.mk b/depends/packages/native_cctools.mk
index a065256c1c..4195230b40 100644
--- a/depends/packages/native_cctools.mk
+++ b/depends/packages/native_cctools.mk
@@ -1,45 +1,55 @@
package=native_cctools
-$(package)_version=807d6fd1be5d2224872e381870c0a75387fe05e6
-$(package)_download_path=https://github.com/theuni/cctools-port/archive
+$(package)_version=3764b223c011574971ee3ae09ce968ba5dc2f00f
+$(package)_download_path=https://github.com/tpoechtrager/cctools-port/archive
$(package)_file_name=$($(package)_version).tar.gz
-$(package)_sha256_hash=a09c9ba4684670a0375e42d9d67e7f12c1f62581a27f28f7c825d6d7032ccc6a
+$(package)_sha256_hash=3e35907bf376269a844df08e03cbb43e345c88125374f2228e03724b5f9a2a04
$(package)_build_subdir=cctools
-$(package)_clang_version=3.7.1
-$(package)_clang_download_path=https://llvm.org/releases/$($(package)_clang_version)
+$(package)_clang_version=6.0.1
+$(package)_clang_download_path=https://releases.llvm.org/$($(package)_clang_version)
$(package)_clang_download_file=clang+llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz
$(package)_clang_file_name=clang-llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz
-$(package)_clang_sha256_hash=99b28a6b48e793705228a390471991386daa33a9717cd9ca007fcdde69608fd9
+$(package)_clang_sha256_hash=fa5416553ca94a8c071a27134c094a5fb736fe1bd0ecc5ef2d9bc02754e1bef0
+
+$(package)_libtapi_version=3efb201881e7a76a21e0554906cf306432539cef
+$(package)_libtapi_download_path=https://github.com/tpoechtrager/apple-libtapi/archive
+$(package)_libtapi_download_file=$($(package)_libtapi_version).tar.gz
+$(package)_libtapi_file_name=$($(package)_libtapi_version).tar.gz
+$(package)_libtapi_sha256_hash=380c1ca37cfa04a8699d0887a8d3ee1ad27f3d08baba78887c73b09485c0fbd3
+
$(package)_extra_sources=$($(package)_clang_file_name)
+$(package)_extra_sources += $($(package)_libtapi_file_name)
define $(package)_fetch_cmds
$(call fetch_file,$(package),$($(package)_download_path),$($(package)_download_file),$($(package)_file_name),$($(package)_sha256_hash)) && \
-$(call fetch_file,$(package),$($(package)_clang_download_path),$($(package)_clang_download_file),$($(package)_clang_file_name),$($(package)_clang_sha256_hash))
+$(call fetch_file,$(package),$($(package)_clang_download_path),$($(package)_clang_download_file),$($(package)_clang_file_name),$($(package)_clang_sha256_hash)) && \
+$(call fetch_file,$(package),$($(package)_libtapi_download_path),$($(package)_libtapi_download_file),$($(package)_libtapi_file_name),$($(package)_libtapi_sha256_hash))
endef
define $(package)_extract_cmds
mkdir -p $($(package)_extract_dir) && \
echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \
echo "$($(package)_clang_sha256_hash) $($(package)_source_dir)/$($(package)_clang_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ echo "$($(package)_libtapi_sha256_hash) $($(package)_source_dir)/$($(package)_libtapi_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
$(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \
- mkdir -p toolchain/bin toolchain/lib/clang/3.5/include && \
+ mkdir -p toolchain/bin toolchain/lib/clang/$($(package)_clang_version)/include && \
+ mkdir -p libtapi && \
+ tar --no-same-owner --strip-components=1 -C libtapi -xf $($(package)_source_dir)/$($(package)_libtapi_file_name) && \
tar --no-same-owner --strip-components=1 -C toolchain -xf $($(package)_source_dir)/$($(package)_clang_file_name) && \
rm -f toolchain/lib/libc++abi.so* && \
- echo "#!/bin/sh" > toolchain/bin/$(host)-dsymutil && \
- echo "exit 0" >> toolchain/bin/$(host)-dsymutil && \
- chmod +x toolchain/bin/$(host)-dsymutil && \
tar --no-same-owner --strip-components=1 -xf $($(package)_source)
endef
define $(package)_set_vars
-$(package)_config_opts=--target=$(host) --disable-lto-support
-$(package)_ldflags+=-Wl,-rpath=\\$$$$$$$$\$$$$$$$$ORIGIN/../lib
-$(package)_cc=$($(package)_extract_dir)/toolchain/bin/clang
-$(package)_cxx=$($(package)_extract_dir)/toolchain/bin/clang++
+ $(package)_config_opts=--target=$(host) --disable-lto-support --with-libtapi=$($(package)_extract_dir)
+ $(package)_ldflags+=-Wl,-rpath=\\$$$$$$$$\$$$$$$$$ORIGIN/../lib
+ $(package)_cc=$($(package)_extract_dir)/toolchain/bin/clang
+ $(package)_cxx=$($(package)_extract_dir)/toolchain/bin/clang++
endef
define $(package)_preprocess_cmds
- cd $($(package)_build_subdir); ./autogen.sh && \
- sed -i.old "/define HAVE_PTHREADS/d" ld64/src/ld/InputFiles.h
+ CC=$($(package)_cc) CXX=$($(package)_cxx) INSTALLPREFIX=$($(package)_extract_dir) ./libtapi/build.sh && \
+ CC=$($(package)_cc) CXX=$($(package)_cxx) INSTALLPREFIX=$($(package)_extract_dir) ./libtapi/install.sh && \
+ sed -i.old "/define HAVE_PTHREADS/d" $($(package)_build_subdir)/ld64/src/ld/InputFiles.h
endef
define $(package)_config_cmds
@@ -52,6 +62,9 @@ endef
define $(package)_stage_cmds
$(MAKE) DESTDIR=$($(package)_staging_dir) install && \
+ mkdir -p $($(package)_staging_prefix_dir)/lib/ && \
+ cd $($(package)_extract_dir) && \
+ cp lib/libtapi.so.6 $($(package)_staging_prefix_dir)/lib/ && \
cd $($(package)_extract_dir)/toolchain && \
mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include && \
mkdir -p $($(package)_staging_prefix_dir)/bin $($(package)_staging_prefix_dir)/include && \
diff --git a/depends/packages/native_libdmg-hfsplus.mk b/depends/packages/native_libdmg-hfsplus.mk
index 8493f1d979..c0f0ce74de 100644
--- a/depends/packages/native_libdmg-hfsplus.mk
+++ b/depends/packages/native_libdmg-hfsplus.mk
@@ -12,7 +12,7 @@ define $(package)_preprocess_cmds
endef
define $(package)_config_cmds
- cmake -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix) ..
+ cmake -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix) -DCMAKE_C_FLAGS="-Wl,--build-id=none" ..
endef
define $(package)_build_cmds
diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk
index d8ccb208cc..42dbaa77a6 100644
--- a/depends/packages/packages.mk
+++ b/depends/packages/packages.mk
@@ -7,8 +7,6 @@ qrencode_packages = qrencode
qt_linux_packages:=qt expat libxcb xcb_proto libXau xproto freetype fontconfig
qt_android_packages=qt
-rapidcheck_packages = rapidcheck
-
qt_darwin_packages=qt
qt_mingw32_packages=qt
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index efa76965d5..366b1d0c42 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -121,7 +121,6 @@ $(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 MAC_LD64_VERSION=$(LD64_VERSION)
endif
$(package)_config_opts_linux = -qt-xkbcommon-x11
diff --git a/depends/packages/rapidcheck.mk b/depends/packages/rapidcheck.mk
deleted file mode 100644
index a16fee270e..0000000000
--- a/depends/packages/rapidcheck.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-package=rapidcheck
-$(package)_version=d9482c683429fe79122e3dcab14c9655874aeb8e
-$(package)_download_path=https://github.com/emil-e/rapidcheck/archive
-$(package)_file_name=$($(package)_version).tar.gz
-$(package)_sha256_hash=b9ee8955b175fd3c0757ebd887bb075541761af08b0c28391b7c6c0685351f6b
-
-define $(package)_config_cmds
- cmake -DCMAKE_INSTALL_PREFIX=$($(package)_staging_dir)$(host_prefix) -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=true -DRC_ENABLE_BOOST_TEST=ON -B .
-endef
-
-define $(package)_preprocess_cmds
- sed -i.old 's/ -Wall//' CMakeLists.txt
-endef
-
-define $(package)_build_cmds
- $(MAKE) rapidcheck
-endef
-
-define $(package)_stage_cmds
- $(MAKE) rapidcheck install
-endef
diff --git a/depends/patches/qt/mac-qmake.conf b/depends/patches/qt/mac-qmake.conf
index 337d0eb9ca..4cd96df29f 100644
--- a/depends/patches/qt/mac-qmake.conf
+++ b/depends/patches/qt/mac-qmake.conf
@@ -18,7 +18,7 @@ QMAKE_APPLE_DEVICE_ARCHS=x86_64
!host_build: QMAKE_CFLAGS += -target $${MAC_TARGET}
!host_build: QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_CFLAGS
!host_build: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS
-!host_build: QMAKE_LFLAGS += -target $${MAC_TARGET} -mlinker-version=$${MAC_LD64_VERSION}
+!host_build: QMAKE_LFLAGS += -target $${MAC_TARGET}
QMAKE_AR = $${CROSS_COMPILE}ar cq
QMAKE_RANLIB=$${CROSS_COMPILE}ranlib
QMAKE_LIBTOOL=$${CROSS_COMPILE}libtool
diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in
index cd7ccf80ab..7e307ab7c8 100644
--- a/doc/Doxyfile.in
+++ b/doc/Doxyfile.in
@@ -861,7 +861,8 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE = src/leveldb \
+EXCLUDE = src/crc32c \
+ src/leveldb \
src/json \
src/test \
src/qt/test
diff --git a/doc/README.md b/doc/README.md
index 4dd21c4620..19d8204d83 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -30,7 +30,7 @@ Drag Bitcoin Core to your applications folder, and then run Bitcoin Core.
* See the documentation at the [Bitcoin Wiki](https://en.bitcoin.it/wiki/Main_Page)
for help and more information.
-* Ask for help on [#bitcoin](http://webchat.freenode.net?channels=bitcoin) on Freenode. If you don't have an IRC client, use [webchat here](http://webchat.freenode.net?channels=bitcoin).
+* Ask for help on [#bitcoin](https://webchat.freenode.net/#bitcoin) on Freenode. If you don't have an IRC client, use [webchat here](https://webchat.freenode.net/#bitcoin).
* Ask for help on the [BitcoinTalk](https://bitcointalk.org/) forums, in the [Technical Support board](https://bitcointalk.org/index.php?board=4.0).
Building
@@ -66,8 +66,8 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th
### Resources
* Discuss on the [BitcoinTalk](https://bitcointalk.org/) forums, in the [Development & Technical Discussion board](https://bitcointalk.org/index.php?board=6.0).
-* Discuss project-specific development on #bitcoin-core-dev on Freenode. If you don't have an IRC client, use [webchat here](http://webchat.freenode.net/?channels=bitcoin-core-dev).
-* Discuss general Bitcoin development on #bitcoin-dev on Freenode. If you don't have an IRC client, use [webchat here](http://webchat.freenode.net/?channels=bitcoin-dev).
+* Discuss project-specific development on #bitcoin-core-dev on Freenode. If you don't have an IRC client, use [webchat here](https://webchat.freenode.net/#bitcoin-core-dev).
+* Discuss general Bitcoin development on #bitcoin-dev on Freenode. If you don't have an IRC client, use [webchat here](https://webchat.freenode.net/#bitcoin-dev).
### Miscellaneous
- [Assets Attribution](assets-attribution.md)
diff --git a/doc/REST-interface.md b/doc/REST-interface.md
index a63391e01a..11e9c90f49 100644
--- a/doc/REST-interface.md
+++ b/doc/REST-interface.md
@@ -30,7 +30,7 @@ To query for a confirmed transaction, enable the transaction index via "txindex=
Given a block hash: returns a block, in binary, hex-encoded binary or JSON formats.
Responds with 404 if the block doesn't exist.
-The HTTP request and response are both handled entirely in-memory, thus making maximum memory usage at least 2.66MB (1 MB max block, plus hex encoding) per request.
+The HTTP request and response are both handled entirely in-memory.
With the /notxdetails/ option JSON response will only contain the transaction hash instead of the complete transaction details. The option only affects the JSON response.
diff --git a/doc/build-freebsd.md b/doc/build-freebsd.md
index 4831623504..f48855a344 100644
--- a/doc/build-freebsd.md
+++ b/doc/build-freebsd.md
@@ -10,7 +10,7 @@ This guide does not contain instructions for building the GUI.
You will need the following dependencies, which can be installed as root via pkg:
-```shell
+```bash
pkg install autoconf automake boost-libs git gmake libevent libtool pkgconf
git clone https://github.com/bitcoin/bitcoin.git
@@ -18,7 +18,7 @@ git clone https://github.com/bitcoin/bitcoin.git
In order to run the test suite (recommended), you will need to have Python 3 installed:
-```shell
+```bash
pkg install python3
```
@@ -29,32 +29,33 @@ See [dependencies.md](dependencies.md) for a complete overview.
BerkeleyDB is only necessary for the wallet functionality. To skip this, pass
`--disable-wallet` to `./configure` and skip to the next section.
-```shell
+```bash
./contrib/install_db4.sh `pwd`
export BDB_PREFIX="$PWD/db4"
```
## Building Bitcoin Core
-**Important**: Use `gmake` (the non-GNU `make` will exit with an error):
+**Important**: Use `gmake` (the non-GNU `make` will exit with an error).
With wallet:
-```shell
+```bash
./autogen.sh
./configure --with-gui=no \
BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" \
- BDB_CFLAGS="-I${BDB_PREFIX}/include"
+ BDB_CFLAGS="-I${BDB_PREFIX}/include" \
+ MAKE=gmake
```
Without wallet:
-```shell
+```bash
./autogen.sh
-./configure --with-gui=no --disable-wallet
+./configure --with-gui=no --disable-wallet MAKE=gmake
```
followed by:
-```shell
+```bash
gmake # use -jX here for parallelism
gmake check # Run tests if Python 3 is available
```
diff --git a/doc/build-netbsd.md b/doc/build-netbsd.md
index ab422f6aa7..47049a780e 100644
--- a/doc/build-netbsd.md
+++ b/doc/build-netbsd.md
@@ -37,13 +37,13 @@ from ports, for the same reason as boost above (g++/libstd++ incompatibility).
If you have to build it yourself, you can use [the installation script included
in contrib/](/contrib/install_db4.sh) like so:
-```shell
+```bash
./contrib/install_db4.sh `pwd`
```
from the root of the repository. Then set `BDB_PREFIX` for the next section:
-```shell
+```bash
export BDB_PREFIX="$PWD/db4"
```
@@ -52,24 +52,26 @@ export BDB_PREFIX="$PWD/db4"
**Important**: Use `gmake` (the non-GNU `make` will exit with an error).
With wallet:
-```
+```bash
./autogen.sh
./configure --with-gui=no CPPFLAGS="-I/usr/pkg/include" \
LDFLAGS="-L/usr/pkg/lib" \
BOOST_CPPFLAGS="-I/usr/pkg/include" \
BOOST_LDFLAGS="-L/usr/pkg/lib" \
BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" \
- BDB_CFLAGS="-I${BDB_PREFIX}/include"
+ BDB_CFLAGS="-I${BDB_PREFIX}/include" \
+ MAKE=gmake
```
Without wallet:
-```
+```bash
./autogen.sh
./configure --with-gui=no --disable-wallet \
CPPFLAGS="-I/usr/pkg/include" \
LDFLAGS="-L/usr/pkg/lib" \
BOOST_CPPFLAGS="-I/usr/pkg/include" \
- BOOST_LDFLAGS="-L/usr/pkg/lib"
+ BOOST_LDFLAGS="-L/usr/pkg/lib" \
+ MAKE=gmake
```
Build and run the tests:
diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md
index dad2566a6c..53c647ae34 100644
--- a/doc/build-openbsd.md
+++ b/doc/build-openbsd.md
@@ -38,19 +38,19 @@ from ports, for the same reason as boost above (g++/libstd++ incompatibility).
If you have to build it yourself, you can use [the installation script included
in contrib/](/contrib/install_db4.sh) like so:
-```shell
+```bash
./contrib/install_db4.sh `pwd` CC=cc CXX=c++
```
from the root of the repository. Then set `BDB_PREFIX` for the next section:
-```shell
+```bash
export BDB_PREFIX="$PWD/db4"
```
### Building Bitcoin Core
-**Important**: use `gmake`, not `make`. The non-GNU `make` will exit with a horrible error.
+**Important**: Use `gmake` (the non-GNU `make` will exit with an error).
Preparation:
```bash
@@ -70,12 +70,14 @@ Make sure `BDB_PREFIX` is set to the appropriate path from the above steps.
To configure with wallet:
```bash
./configure --with-gui=no CC=cc CXX=c++ \
- BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" BDB_CFLAGS="-I${BDB_PREFIX}/include"
+ BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" \
+ BDB_CFLAGS="-I${BDB_PREFIX}/include" \
+ MAKE=gmake
```
To configure without wallet:
```bash
-./configure --disable-wallet --with-gui=no CC=cc CXX=c++
+./configure --disable-wallet --with-gui=no CC=cc CXX=c++ MAKE=gmake
```
Build and run the tests:
diff --git a/doc/build-osx.md b/doc/build-osx.md
index bf655538c7..7b76117c8b 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -22,6 +22,7 @@ Then install [Homebrew](https://brew.sh).
brew install automake berkeley-db4 libtool boost miniupnpc pkg-config python qt libevent qrencode
```
+If you run into issues, check [Homebrew's troubleshooting page](https://docs.brew.sh/Troubleshooting).
See [dependencies.md](dependencies.md) for a complete overview.
If you want to build the disk image with `make deploy` (.dmg / optional), you need RSVG:
@@ -113,96 +114,3 @@ tail -f $HOME/Library/Application\ Support/Bitcoin/debug.log
* Tested on OS X 10.12 Sierra through macOS 10.15 Catalina 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).
-
-## Deterministic macOS DMG Notes
-Working macOS DMGs are created in Linux by combining a recent `clang`, the Apple
-`binutils` (`ld`, `ar`, etc) and DMG authoring tools.
-
-Apple uses `clang` extensively for development and has upstreamed the necessary
-functionality so that a vanilla clang can take advantage. It supports the use of `-F`,
-`-target`, `-mmacosx-version-min`, and `--sysroot`, which are all necessary when
-building for macOS.
-
-Apple's version of `binutils` (called `cctools`) contains lots of functionality missing in the
-FSF's `binutils`. In addition to extra linker options for frameworks and sysroots, several
-other tools are needed as well such as `install_name_tool`, `lipo`, and `nmedit`. These
-do not build under Linux, so they have been patched to do so. The work here was used as
-a starting point: [mingwandroid/toolchain4](https://github.com/mingwandroid/toolchain4).
-
-In order to build a working toolchain, the following source packages are needed from
-Apple: `cctools`, `dyld`, and `ld64`.
-
-These tools inject timestamps by default, which produce non-deterministic binaries. The
-`ZERO_AR_DATE` environment variable is used to disable that.
-
-This version of `cctools` has been patched to use the current version of `clang`'s headers
-and its `libLTO.so` rather than those from `llvmgcc`, as it was originally done in `toolchain4`.
-
-To complicate things further, all builds must target an Apple SDK. These SDKs are free to
-download, but not redistributable. To obtain it, register for an Apple Developer Account,
-then download the [Xcode 7.3.1 dmg](https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/Xcode_7.3.1/Xcode_7.3.1.dmg).
-
-This file is several gigabytes in size, but only a single directory inside is needed:
-```
-Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk
-```
-
-Unfortunately, the usual Linux tools (7zip, hpmount, loopback mount) are incapable of
-opening this file. To create a tarball suitable for Gitian input, there are two options:
-
-Using macOS, you can mount the DMG, and then create it with:
-```shell
-hdiutil attach Xcode_7.3.1.dmg
-tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.11.sdk.tar.gz MacOSX10.11.sdk
-```
-
-Alternatively, you can use 7zip and SleuthKit to extract the files one by one. The script
-[`extract-osx-sdk.sh`](./../contrib/macdeploy/extract-osx-sdk.sh) automates this. First
-ensure the DMG file is in the current directory, and then run the script. You may wish to
-delete the `intermediate 5.hfs` file and `MacOSX10.11.sdk` (the directory) when you've
-confirmed the extraction succeeded.
-
-```shell
-apt-get install p7zip-full sleuthkit
-contrib/macdeploy/extract-osx-sdk.sh
-rm -rf 5.hfs MacOSX10.11.sdk
-```
-
-The Gitian descriptors build 2 sets of files: Linux tools, then Apple binaries which are
-created using these tools. The build process has been designed to avoid including the
-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: [theuni/osx-cross-depends](https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff).
-No effort was made to fix this cleanly, so it likely leaks memory badly. But it's only used for
-a single invocation, so that's no real concern.
-
-`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. It has been forked and is available
-(with fixes) here: [theuni/libdmg-hfsplus](https://github.com/theuni/libdmg-hfsplus).
-
-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.
-
-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`.
-
-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
-shared, we'll have to be a bit creative in order for the build process to remain somewhat
-deterministic. Here's how it works:
-
-- Builders use Gitian to create an unsigned release. This outputs an unsigned DMG which
- users may choose to bless and run. It also outputs an unsigned app structure in the form
- of a tarball, which also contains all of the tools that have been previously (deterministically)
- built in order to create a final DMG.
-- The Apple keyholder uses this unsigned app to create a detached signature, using the
- script that is also included there. Detached signatures are available from this [repository](https://github.com/bitcoin-core/bitcoin-detached-sigs).
-- Builders feed the unsigned app + detached signature back into Gitian. It uses the
- pre-built tools to recombine the pieces into a deterministic DMG.
-
diff --git a/doc/build-unix.md b/doc/build-unix.md
index e799e709fa..6b51db5f55 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -80,7 +80,7 @@ Build requirements:
Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies:
- sudo apt-get install libevent-dev libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev
+ sudo apt-get install libevent-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev
BerkeleyDB is required for the wallet.
diff --git a/doc/dependencies.md b/doc/dependencies.md
index 51a2240107..0cb5311e8b 100644
--- a/doc/dependencies.md
+++ b/doc/dependencies.md
@@ -13,7 +13,7 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct
| 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) | | | |
| 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.22 | No | | |
+| 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 | | |
diff --git a/doc/descriptors.md b/doc/descriptors.md
index e31665b129..181ff77e50 100644
--- a/doc/descriptors.md
+++ b/doc/descriptors.md
@@ -17,6 +17,7 @@ Supporting RPCs are:
(`regtest` only, since v0.19).
- `utxoupdatepsbt` takes as input descriptors to add information to the psbt
(since v0.19).
+- `createmultisig` and `addmultisigaddress` return descriptors as well (since v0.20)
This document describes the language. For the specifics on usage, see the RPC
documentation for the functions mentioned above.
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 3ef35cfcfa..b33b3ad18a 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -43,6 +43,7 @@ Developer Notes
- [Suggestions and examples](#suggestions-and-examples)
- [Release notes](#release-notes)
- [RPC interface guidelines](#rpc-interface-guidelines)
+ - [Internal interface guidelines](#internal-interface-guidelines)
<!-- markdown-toc end -->
@@ -288,6 +289,7 @@ $ valgrind --suppressions=contrib/valgrind.supp src/test/test_bitcoin
$ valgrind --suppressions=contrib/valgrind.supp --leak-check=full \
--show-leak-kinds=all src/test/test_bitcoin --log_level=test_suite
$ valgrind -v --leak-check=full src/bitcoind -printtoconsole
+$ ./test/functional/test_runner.py --valgrind
```
### Compiling for test coverage
@@ -421,27 +423,52 @@ and its `cs_KeyStore` lock for example).
Threads
-------
-- ThreadScriptCheck : Verifies block scripts.
+- [Main thread (`bitcoind`)](https://doxygen.bitcoincore.org/bitcoind_8cpp.html#a0ddf1224851353fc92bfbff6f499fa97)
+ : Started from `main()` in `bitcoind.cpp`. Responsible for starting up and
+ shutting down the application.
-- ThreadImport : Loads blocks from `blk*.dat` files or `-loadblock=<file>`.
+- [ThreadImport (`b-loadblk`)](https://doxygen.bitcoincore.org/init_8cpp.html#ae9e290a0e829ec0198518de2eda579d1)
+ : Loads blocks from `blk*.dat` files or `-loadblock=<file>` on startup.
-- ThreadDNSAddressSeed : Loads addresses of peers from the DNS.
+- [ThreadScriptCheck (`b-scriptch.x`)](https://doxygen.bitcoincore.org/validation_8cpp.html#a925a33e7952a157922b0bbb8dab29a20)
+ : Parallel script validation threads for transactions in blocks.
-- ThreadMapPort : Universal plug-and-play startup/shutdown.
+- [ThreadHTTP (`b-http`)](https://doxygen.bitcoincore.org/httpserver_8cpp.html#abb9f6ea8819672bd9a62d3695070709c)
+ : Libevent thread to listen for RPC and REST connections.
-- ThreadSocketHandler : Sends/Receives data from peers on port 8333.
+- [HTTP worker threads(`b-httpworker.x`)](https://doxygen.bitcoincore.org/httpserver_8cpp.html#aa6a7bc27265043bc0193220c5ae3a55f)
+ : Threads to service RPC and REST requests.
-- ThreadOpenAddedConnections : Opens network connections to added nodes.
+- [Indexer threads (`b-txindex`, etc)](https://doxygen.bitcoincore.org/class_base_index.html#a96a7407421fbf877509248bbe64f8d87)
+ : One thread per indexer.
-- ThreadOpenConnections : Initiates new connections to peers.
+- [SchedulerThread (`b-scheduler`)](https://doxygen.bitcoincore.org/class_c_scheduler.html#a14d2800815da93577858ea078aed1fba)
+ : Does asynchronous background tasks like dumping wallet contents, dumping
+ addrman and running asynchronous validationinterface callbacks.
-- ThreadMessageHandler : Higher-level message handling (sending and receiving).
+- [TorControlThread (`b-torcontrol`)](https://doxygen.bitcoincore.org/torcontrol_8cpp.html#a4faed3692d57a0d7bdbecf3b37f72de0)
+ : Libevent thread for tor connections.
-- DumpAddresses : Dumps IP addresses of nodes to `peers.dat`.
+- Net threads:
-- ThreadRPCServer : Remote procedure call handler, listens on port 8332 for connections and services them.
+ - [ThreadMessageHandler (`b-msghand`)](https://doxygen.bitcoincore.org/class_c_connman.html#aacdbb7148575a31bb33bc345e2bf22a9)
+ : Application level message handling (sending and receiving). Almost
+ all net_processing and validation logic runs on this thread.
-- Shutdown : Does an orderly shutdown of everything.
+ - [ThreadDNSAddressSeed (`b-dnsseed`)](https://doxygen.bitcoincore.org/class_c_connman.html#aa7c6970ed98a4a7bafbc071d24897d13)
+ : Loads addresses of peers from the DNS.
+
+ - [ThreadMapPort (`b-upnp`)](https://doxygen.bitcoincore.org/net_8cpp.html#a63f82a71c4169290c2db1651a9bbe249)
+ : Universal plug-and-play startup/shutdown.
+
+ - [ThreadSocketHandler (`b-net`)](https://doxygen.bitcoincore.org/class_c_connman.html#a765597cbfe99c083d8fa3d61bb464e34)
+ : Sends/Receives data from peers on port 8333.
+
+ - [ThreadOpenAddedConnections (`b-addcon`)](https://doxygen.bitcoincore.org/class_c_connman.html#a0b787caf95e52a346a2b31a580d60a62)
+ : Opens network connections to added nodes.
+
+ - [ThreadOpenConnections (`b-opencon`)](https://doxygen.bitcoincore.org/class_c_connman.html#a55e9feafc3bab78e5c9d408c207faa45)
+ : Initiates new connections to peers.
Ignoring IDE/editor files
--------------------------
@@ -858,6 +885,10 @@ Current subtrees include:
- **Note**: Follow the instructions in [Upgrading LevelDB](#upgrading-leveldb) when
merging upstream changes to the LevelDB subtree.
+- src/crc32c
+ - Used by leveldb for hardware acceleration of CRC32C checksums for data integrity.
+ - Upstream at https://github.com/google/crc32c ; Maintained by Google.
+
- src/secp256k1
- Upstream at https://github.com/bitcoin-core/secp256k1/ ; actively maintained by Core contributors.
@@ -959,7 +990,7 @@ Some good examples of scripted-diff:
- [scripted-diff: Rename InitInterfaces to NodeContext](https://github.com/bitcoin/bitcoin/commit/301bd41a2e6765b185bd55f4c541f9e27aeea29d)
uses an elegant script to replace occurrences of multiple terms in all source files.
-- [scripted-diff: Remove g_connman, g_banman globals](https://github.com/bitcoin/bitcoin/commit/301bd41a2e6765b185bd55f4c541f9e27aeea29d)
+- [scripted-diff: Remove g_connman, g_banman globals](https://github.com/bitcoin/bitcoin/commit/8922d7f6b751a3e6b3b9f6fb7961c442877fb65a)
replaces specific terms in a list of specific source files.
- [scripted-diff: Replace fprintf with tfm::format](https://github.com/bitcoin/bitcoin/commit/fac03ec43a15ad547161e37e53ea82482cc508f9)
@@ -1085,7 +1116,8 @@ A few guidelines for introducing and reviewing new RPC interfaces:
new RPC is replacing a deprecated RPC, to avoid both RPCs confusingly
showing up in the command list.
-- Use *invalid* bech32 addresses for `RPCExamples` help documentation.
+- Use *invalid* bech32 addresses (e.g. in the constant array `EXAMPLE_ADDRESS`) for
+ `RPCExamples` help documentation.
- *Rationale*: Prevent accidental transactions by users and encourage the use
of bech32 addresses by default.
@@ -1094,3 +1126,124 @@ A few guidelines for introducing and reviewing new RPC interfaces:
timestamps in the documentation.
- *Rationale*: User-facing consistency.
+
+Internal interface guidelines
+-----------------------------
+
+Internal interfaces between parts of the codebase that are meant to be
+independent (node, wallet, GUI), are defined in
+[`src/interfaces/`](../src/interfaces/). The main interface classes defined
+there are [`interfaces::Chain`](../src/interfaces/chain.h), used by wallet to
+access the node's latest chain state,
+[`interfaces::Node`](../src/interfaces/node.h), used by the GUI to control the
+node, and [`interfaces::Wallet`](../src/interfaces/wallet.h), used by the GUI
+to control an individual wallet. There are also more specialized interface
+types like [`interfaces::Handler`](../src/interfaces/handler.h)
+[`interfaces::ChainClient`](../src/interfaces/chain.h) passed to and from
+various interface methods.
+
+Interface classes are written in a particular style so node, wallet, and GUI
+code doesn't need to run in the same process, and so the class declarations
+work more easily with tools and libraries supporting interprocess
+communication:
+
+- Interface classes should be abstract and have methods that are [pure
+ virtual](https://en.cppreference.com/w/cpp/language/abstract_class). This
+ allows multiple implementations to inherit from the same interface class,
+ particularly so one implementation can execute functionality in the local
+ process, and other implementations can forward calls to remote processes.
+
+- Interface method definitions should wrap existing functionality instead of
+ implementing new functionality. Any substantial new node or wallet
+ functionality should be implemented in [`src/node/`](../src/node/) or
+ [`src/wallet/`](../src/wallet/) and just exposed in
+ [`src/interfaces/`](../src/interfaces/) instead of being implemented there,
+ so it can be more modular and accessible to unit tests.
+
+- Interface method parameter and return types should either be serializable or
+ be other interface classes. Interface methods shouldn't pass references to
+ objects that can't be serialized or accessed from another process.
+
+ Examples:
+
+ ```c++
+ // Good: takes string argument and returns interface class pointer
+ virtual unique_ptr<interfaces::Wallet> loadWallet(std::string filename) = 0;
+
+ // Bad: returns CWallet reference that can't be used from another process
+ virtual CWallet& loadWallet(std::string filename) = 0;
+ ```
+
+ ```c++
+ // Good: accepts and returns primitive types
+ virtual bool findBlock(const uint256& hash, int& out_height, int64_t& out_time) = 0;
+
+ // Bad: returns pointer to internal node in a linked list inaccessible to
+ // other processes
+ virtual const CBlockIndex* findBlock(const uint256& hash) = 0;
+ ```
+
+ ```c++
+ // Good: takes plain callback type and returns interface pointer
+ using TipChangedFn = std::function<void(int block_height, int64_t block_time)>;
+ virtual std::unique_ptr<interfaces::Handler> handleTipChanged(TipChangedFn fn) = 0;
+
+ // Bad: returns boost connection specific to local process
+ using TipChangedFn = std::function<void(int block_height, int64_t block_time)>;
+ virtual boost::signals2::scoped_connection connectTipChanged(TipChangedFn fn) = 0;
+ ```
+
+- For consistency and friendliness to code generation tools, interface method
+ input and inout parameters should be ordered first and output parameters
+ should come last.
+
+ Example:
+
+ ```c++
+ // Good: error output param is last
+ virtual bool broadcastTransaction(const CTransactionRef& tx, CAmount max_fee, std::string& error) = 0;
+
+ // Bad: error output param is between input params
+ virtual bool broadcastTransaction(const CTransactionRef& tx, std::string& error, CAmount max_fee) = 0;
+ ```
+
+- For friendliness to code generation tools, interface methods should not be
+ overloaded:
+
+ Example:
+
+ ```c++
+ // Good: method names are unique
+ virtual bool disconnectByAddress(const CNetAddr& net_addr) = 0;
+ virtual bool disconnectById(NodeId id) = 0;
+
+ // Bad: methods are overloaded by type
+ virtual bool disconnect(const CNetAddr& net_addr) = 0;
+ virtual bool disconnect(NodeId id) = 0;
+ ```
+
+- For consistency and friendliness to code generation tools, interface method
+ names should be `lowerCamelCase` and standalone function names should be
+ `UpperCamelCase`.
+
+ Examples:
+
+ ```c++
+ // Good: lowerCamelCase method name
+ virtual void blockConnected(const CBlock& block, int height) = 0;
+
+ // Bad: uppercase class method
+ virtual void BlockConnected(const CBlock& block, int height) = 0;
+ ```
+
+ ```c++
+ // Good: UpperCamelCase standalone function name
+ std::unique_ptr<Node> MakeNode(LocalInit& init);
+
+ // Bad: lowercase standalone function
+ std::unique_ptr<Node> makeNode(LocalInit& init);
+ ```
+
+ Note: This last convention isn't generally followed outside of
+ [`src/interfaces/`](../src/interfaces/), though it did come up for discussion
+ before in [#14635](https://github.com/bitcoin/bitcoin/pull/14635).
diff --git a/doc/files.md b/doc/files.md
index c2296b45fa..cd23d547bb 100644
--- a/doc/files.md
+++ b/doc/files.md
@@ -78,6 +78,10 @@ Subdirectory | File(s) | Description
3. A wallet database path can be specified by `-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.
+
## 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 c34ca4cb59..419b1db44e 100644
--- a/doc/fuzzing.md
+++ b/doc/fuzzing.md
@@ -1,138 +1,157 @@
-Fuzz-testing Bitcoin Core
-==========================
-
-A special test harness in `src/test/fuzz/` is provided for each fuzz target to
-provide an easy entry point for fuzzers and the like. In this document we'll
-describe how to use it with AFL and libFuzzer.
-
-## Preparing fuzzing
-
-The fuzzer needs some inputs to work on, but the inputs or seeds can be used
-interchangeably between libFuzzer and AFL.
-
-Extract the example seeds (or other starting inputs) into the inputs
-directory before starting fuzzing.
-
-```
-git clone https://github.com/bitcoin-core/qa-assets
-export DIR_FUZZ_IN=$PWD/qa-assets/fuzz_seed_corpus
-```
-
-AFL needs an input directory with examples, and an output directory where it
-will place examples that it found. These can be anywhere in the file system,
-we'll define environment variables to make it easy to reference them.
-
-So, only for AFL you need to configure the outputs path:
-
-```
-mkdir outputs
-export AFLOUT=$PWD/outputs
-```
-
-libFuzzer will use the input directory as output directory.
-
-## AFL
-
-### Building AFL
-
-It is recommended to always use the latest version of afl:
-```
-wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz
-tar -zxvf afl-latest.tgz
-cd afl-<version>
-make
-export AFLPATH=$PWD
-```
+# Fuzzing Bitcoin Core using libFuzzer
+
+## Quickstart guide
+
+To quickly get started fuzzing Bitcoin Core using [libFuzzer](https://llvm.org/docs/LibFuzzer.html):
+
+```sh
+$ git clone https://github.com/bitcoin/bitcoin
+$ cd bitcoin/
+$ ./autogen.sh
+$ CC=clang CXX=clang++ ./configure --enable-fuzz --with-sanitizers=address,fuzzer,undefined
+# 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
+# abort fuzzing using ctrl-c
+```
+
+## Fuzzing harnesses, fuzzing output and fuzzing corpora
+
+[`process_message`](https://github.com/bitcoin/bitcoin/blob/master/src/test/fuzz/process_message.cpp) is a fuzzing harness for the [`ProcessMessage(...)` function (`net_processing`)](https://github.com/bitcoin/bitcoin/blob/master/src/net_processing.cpp). The available fuzzing harnesses are found in [`src/test/fuzz/`](https://github.com/bitcoin/bitcoin/tree/master/src/test/fuzz).
+
+The fuzzer will output `NEW` every time it has created a test input that covers new areas of the code under test. For more information on how to interpret the fuzzer output, see the [libFuzzer documentation](https://llvm.org/docs/LibFuzzer.html).
+
+If you specify a corpus directory then any new coverage increasing inputs will be saved there:
+
+```sh
+$ mkdir -p process_message-seeded-from-thin-air/
+$ src/test/fuzz/process_message 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),
+INFO: 0 files found in process_message-seeded-from-thin-air/
+INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
+INFO: A corpus is not provided, starting from an empty corpus
+#2 INITED cov: 94 ft: 95 corp: 1/1b exec/s: 0 rss: 150Mb
+#3 NEW cov: 95 ft: 96 corp: 2/3b lim: 4 exec/s: 0 rss: 150Mb L: 2/2 MS: 1 InsertByte-
+#4 NEW cov: 96 ft: 98 corp: 3/7b lim: 4 exec/s: 0 rss: 150Mb L: 4/4 MS: 1 CrossOver-
+#21 NEW cov: 96 ft: 100 corp: 4/11b lim: 4 exec/s: 0 rss: 150Mb L: 4/4 MS: 2 ChangeBit-CrossOver-
+#324 NEW cov: 101 ft: 105 corp: 5/12b lim: 6 exec/s: 0 rss: 150Mb L: 6/6 MS: 5 CrossOver-ChangeBit-CopyPart-ChangeBit-ChangeBinInt-
+#1239 REDUCE cov: 102 ft: 106 corp: 6/24b lim: 14 exec/s: 0 rss: 150Mb L: 13/13 MS: 5 ChangeBit-CrossOver-EraseBytes-ChangeBit-InsertRepeatedBytes-
+#1272 REDUCE cov: 102 ft: 106 corp: 6/23b lim: 14 exec/s: 0 rss: 150Mb L: 12/12 MS: 3 ChangeBinInt-ChangeBit-EraseBytes-
+ NEW_FUNC[1/677]: 0x55e11f456690 in std::_Function_base::~_Function_base() /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/std_function.h:255
+ NEW_FUNC[2/677]: 0x55e11f465800 in CDataStream::CDataStream(std::vector<unsigned char, std::allocator<unsigned char> > const&, int, int) src/./streams.h:248
+#2125 REDUCE cov: 4820 ft: 4867 corp: 7/29b lim: 21 exec/s: 0 rss: 155Mb L: 6/12 MS: 2 CopyPart-CMP- DE: "block"-
+ NEW_FUNC[1/9]: 0x55e11f64d790 in std::_Rb_tree<uint256, std::pair<uint256 const, std::chrono::duration<long, std::ratio<1l, 1000000l> > >, std::_Select1st<std::pair<uint256 const, std::chrono::duration<long, std::ratio<1l, 1000000l> > > >, std::less<uint256>, std::allocator<std::pair<uint256 const, std::chrono::duration<long, std::ratio<1l, 1000000l> > > > >::~_Rb_tree() /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_tree.h:972
+ NEW_FUNC[2/9]: 0x55e11f64d870 in std::_Rb_tree<uint256, std::pair<uint256 const, std::chrono::duration<long, std::ratio<1l, 1000000l> > >, std::_Select1st<std::pair<uint256 const, std::chrono::duration<long, std::ratio<1l, 1000000l> > > >, std::less<uint256>, std::allocator<std::pair<uint256 const, std::chrono::duration<long, std::ratio<1l, 1000000l> > > > >::_M_erase(std::_Rb_tree_node<std::pair<uint256 const, std::chrono::duration<long, std::ratio<1l, 1000000l> > > >*) /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_tree.h:1875
+#2228 NEW cov: 4898 ft: 4971 corp: 8/35b lim: 21 exec/s: 0 rss: 156Mb L: 6/12 MS: 3 EraseBytes-CopyPart-PersAutoDict- DE: "block"-
+ NEW_FUNC[1/5]: 0x55e11f46df70 in std::enable_if<__and_<std::allocator_traits<zero_after_free_allocator<char> >::__construct_helper<char, unsigned char const&>::type>::value, void>::type std::allocator_traits<zero_after_free_allocator<char> >::_S_construct<char, unsigned char const&>(zero_after_free_allocator<char>&, char*, unsigned char const&) /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/alloc_traits.h:243
+ NEW_FUNC[2/5]: 0x55e11f477390 in std::vector<unsigned char, std::allocator<unsigned char> >::data() /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_vector.h:1056
+#2456 NEW cov: 4933 ft: 5042 corp: 9/55b lim: 21 exec/s: 0 rss: 160Mb L: 20/20 MS: 3 ChangeByte-InsertRepeatedBytes-PersAutoDict- DE: "block"-
+#2467 NEW cov: 4933 ft: 5043 corp: 10/76b lim: 21 exec/s: 0 rss: 161Mb L: 21/21 MS: 1 InsertByte-
+#4215 NEW cov: 4941 ft: 5129 corp: 17/205b lim: 29 exec/s: 4215 rss: 350Mb L: 29/29 MS: 5 InsertByte-ChangeBit-CopyPart-InsertRepeatedBytes-CrossOver-
+#4567 REDUCE cov: 4941 ft: 5129 corp: 17/204b lim: 29 exec/s: 4567 rss: 404Mb L: 24/29 MS: 2 ChangeByte-EraseBytes-
+#6642 NEW cov: 4941 ft: 5138 corp: 18/244b lim: 43 exec/s: 2214 rss: 450Mb L: 43/43 MS: 3 CopyPart-CMP-CrossOver- DE: "verack"-
+# abort fuzzing using ctrl-c
+$ ls process_message-seeded-from-thin-air/
+349ac589fc66a09abc0b72bb4ae445a7a19e2cd8 4df479f1f421f2ea64b383cd4919a272604087a7
+a640312c98dcc55d6744730c33e41c5168c55f09 b135de16e4709558c0797c15f86046d31c5d86d7
+c000f7b41b05139de8b63f4cbf7d1ad4c6e2aa7f fc52cc00ec1eb1c08470e69f809ae4993fa70082
+$ cat --show-nonprinting process_message-seeded-from-thin-air/349ac589fc66a09abc0b72bb4ae445a7a19e2cd8
+block^@M-^?M-^?M-^?M-^?M-^?nM-^?M-^?
+```
+
+In this case the fuzzer managed to create a `block` message which when passed to `ProcessMessage(...)` increased coverage.
+
+The project's collection of seed corpora is found in the [`bitcoin-core/qa-assets`](https://github.com/bitcoin-core/qa-assets) repo.
+
+To fuzz `process_message` using the [`bitcoin-core/qa-assets`](https://github.com/bitcoin-core/qa-assets) seed corpus:
+
+```sh
+$ git clone https://github.com/bitcoin-core/qa-assets
+$ src/test/fuzz/process_message 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),
+INFO: 991 files found in qa-assets/fuzz_seed_corpus/process_message/
+INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
+INFO: seed corpus: files: 991 min: 1b max: 1858b total: 288291b rss: 150Mb
+#993 INITED cov: 7063 ft: 8236 corp: 25/3821b exec/s: 0 rss: 181Mb
+…
+```
+
+If you find coverage increasing inputs when fuzzing you are highly encouraged to submit them for inclusion in the [`bitcoin-core/qa-assets`](https://github.com/bitcoin-core/qa-assets) repo.
+
+Every single pull request submitted against the Bitcoin Core repo is automatically tested against all inputs in the [`bitcoin-core/qa-assets`](https://github.com/bitcoin-core/qa-assets) repo. Contributing new coverage increasing inputs is an easy way to help make Bitcoin Core more robust.
+
+## macOS hints for libFuzzer
+
+The default Clang/LLVM version supplied by Apple on macOS does not include
+fuzzing libraries, so macOS users will need to install a full version, for
+example using `brew install llvm`.
-For macOS you may need to ignore x86 compilation checks when running `make`:
-`AFL_NO_X86=1 make`.
+Should you run into problems with the address sanitizer, it is possible you
+may need to run `./configure` with `--disable-asm` to avoid errors
+with certain assembly code from Bitcoin Core's code. See [developer notes on sanitizers](https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#sanitizers)
+for more information.
-### Instrumentation
+You may also need to take care of giving the correct path for `clang` and
+`clang++`, like `CC=/path/to/clang CXX=/path/to/clang++` if the non-systems
+`clang` does not come first in your path.
-To build Bitcoin Core using AFL instrumentation (this assumes that the
-`AFLPATH` was set as above):
-```
-./configure --disable-ccache --disable-shared --enable-tests --enable-fuzz CC=${AFLPATH}/afl-gcc CXX=${AFLPATH}/afl-g++
-export AFL_HARDEN=1
-make
-```
+Full configure that was tested on macOS Catalina with `brew` installed `llvm`:
-If you are using clang you will need to substitute `afl-gcc` with `afl-clang`
-and `afl-g++` with `afl-clang++`, so the first line above becomes:
-```
-./configure --disable-ccache --disable-shared --enable-tests --enable-fuzz CC=${AFLPATH}/afl-clang CXX=${AFLPATH}/afl-clang++
+```sh
+./configure --enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=/usr/local/opt/llvm/bin/clang CXX=/usr/local/opt/llvm/bin/clang++ --disable-asm
```
-We disable ccache because we don't want to pollute the ccache with instrumented
-objects, and similarly don't want to use non-instrumented cached objects linked
-in.
+Read the [libFuzzer documentation](https://llvm.org/docs/LibFuzzer.html) for more information. This [libFuzzer tutorial](https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md) might also be of interest.
-The fuzzing can be sped up significantly (~200x) by using `afl-clang-fast` and
-`afl-clang-fast++` in place of `afl-gcc` and `afl-g++` when compiling. When
-compiling using `afl-clang-fast`/`afl-clang-fast++` the resulting
-binary will be instrumented in such a way that the AFL
-features "persistent mode" and "deferred forkserver" can be used. See
-https://github.com/google/AFL/tree/master/llvm_mode for details.
+# Fuzzing Bitcoin Core using american fuzzy lop (`afl-fuzz`)
-### Fuzzing
+## Quickstart guide
-To start the actual fuzzing use:
+To quickly get started fuzzing Bitcoin Core using [`afl-fuzz`](https://github.com/google/afl):
-```
-export FUZZ_TARGET=bech32 # Pick a fuzz_target
-mkdir ${AFLOUT}/${FUZZ_TARGET}
-$AFLPATH/afl-fuzz -i ${DIR_FUZZ_IN}/${FUZZ_TARGET} -o ${AFLOUT}/${FUZZ_TARGET} -m52 -- src/test/fuzz/${FUZZ_TARGET}
+```sh
+$ git clone https://github.com/bitcoin/bitcoin
+$ cd bitcoin/
+$ git clone https://github.com/google/afl
+$ make -C afl/
+$ make -C afl/llvm_mode/
+$ ./autogen.sh
+$ CC=$(pwd)/afl/afl-clang-fast CXX=$(pwd)/afl/afl-clang-fast++ ./configure --enable-fuzz
+$ make
+# For macOS you may need to ignore x86 compilation checks when running "make". If so,
+# 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
+# You may have to change a few kernel parameters to test optimally - afl-fuzz
+# will print an error and suggestion if so.
```
-You may have to change a few kernel parameters to test optimally - `afl-fuzz`
-will print an error and suggestion if so.
+Read the [`afl-fuzz` documentation](https://github.com/google/afl) for more information.
-On macOS you may need to set `AFL_NO_FORKSRV=1` to get the target to run.
-```
-export FUZZ_TARGET=bech32 # Pick a fuzz_target
-mkdir ${AFLOUT}/${FUZZ_TARGET}
-AFL_NO_FORKSRV=1 $AFLPATH/afl-fuzz -i ${DIR_FUZZ_IN}/${FUZZ_TARGET} -o ${AFLOUT}/${FUZZ_TARGET} -m52 -- src/test/fuzz/${FUZZ_TARGET}
-```
-
-## libFuzzer
+# Fuzzing Bitcoin Core using Honggfuzz
-A recent version of `clang`, the address/undefined sanitizers (ASan/UBSan) and
-libFuzzer is needed (all found in the `compiler-rt` runtime libraries package).
+## Quickstart guide
-To build all fuzz targets with libFuzzer, run
+To quickly get started fuzzing Bitcoin Core using [Honggfuzz](https://github.com/google/honggfuzz):
+```sh
+$ git clone https://github.com/bitcoin/bitcoin
+$ cd bitcoin/
+$ ./autogen.sh
+$ git clone https://github.com/google/honggfuzz
+$ cd honggfuzz/
+$ make
+$ 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
```
-./configure --disable-ccache --enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=clang CXX=clang++
-make
-```
-
-See https://llvm.org/docs/LibFuzzer.html#running on how to run the libFuzzer
-instrumented executable.
-
-Alternatively, you can run the script through the fuzzing test harness (only
-libFuzzer supported so far). You need to pass it the inputs directory and
-the specific test target you want to run.
-
-```
-./test/fuzz/test_runner.py ${DIR_FUZZ_IN} bech32
-```
-
-### macOS hints for libFuzzer
-The default clang/llvm version supplied by Apple on macOS does not include
-fuzzing libraries, so macOS users will need to install a full version, for
-example using `brew install llvm`.
-
-Should you run into problems with the address sanitizer, it is possible you
-may need to run `./configure` with `--disable-asm` to avoid errors
-with certain assembly code from Bitcoin Core's code. See [developer notes on sanitizers](https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#sanitizers)
-for more information.
-
-You may also need to take care of giving the correct path for clang and
-clang++, like `CC=/path/to/clang CXX=/path/to/clang++` if the non-systems
-clang does not come first in your path.
-
-Full configure that was tested on macOS Catalina with `brew` installed `llvm`:
-```
-./configure --disable-ccache --enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=/usr/local/opt/llvm/bin/clang CXX=/usr/local/opt/llvm/bin/clang++ --disable-asm
-```
+Read the [Honggfuzz documentation](https://github.com/google/honggfuzz/blob/master/docs/USAGE.md) for more information.
diff --git a/doc/init.md b/doc/init.md
index 0b327aab58..99aa0a0def 100644
--- a/doc/init.md
+++ b/doc/init.md
@@ -20,9 +20,9 @@ The macOS configuration assumes bitcoind will be set up for the current user.
Configuration
---------------------------------
-At a bare minimum, bitcoind requires that the rpcpassword setting be set
-when running as a daemon. If the configuration file does not exist or this
-setting is not set, bitcoind will shut down promptly after startup.
+Running bitcoind as a daemon does not require any manual configuration. You may
+set the `rpcauth` setting in the `bitcoin.conf` configuration file to override
+the default behaviour of using a special cookie for authentication.
This password does not have to be remembered or typed as it is mostly used
as a fixed token that bitcoind and client programs read from the configuration
diff --git a/doc/productivity.md b/doc/productivity.md
index b25ddc94e5..1bf3d9afb5 100644
--- a/doc/productivity.md
+++ b/doc/productivity.md
@@ -172,11 +172,11 @@ When looking at other's pull requests, it may make sense to add the following se
```
[remote "upstream-pull"]
- fetch = +refs/pull/*:refs/remotes/upstream-pull/*
+ fetch = +refs/pull/*/head:refs/remotes/upstream-pull/*
url = git@github.com:bitcoin/bitcoin.git
```
-This will add an `upstream-pull` remote to your git repository, which can be fetched using `git fetch --all` or `git fetch upstream-pull`. Afterwards, you can use `upstream-pull/NUMBER/head` in arguments to `git show`, `git checkout` and anywhere a commit id would be acceptable to see the changes from pull request NUMBER.
+This will add an `upstream-pull` remote to your git repository, which can be fetched using `git fetch --all` or `git fetch upstream-pull`. It will download and store on disk quite a lot of data (all PRs, including merged and closed ones). Afterwards, you can use `upstream-pull/NUMBER/head` in arguments to `git show`, `git checkout` and anywhere a commit id would be acceptable to see the changes from pull request NUMBER.
### Diff the diffs with `git range-diff`
diff --git a/doc/rapidcheck.md b/doc/rapidcheck.md
deleted file mode 100644
index 397a907f17..0000000000
--- a/doc/rapidcheck.md
+++ /dev/null
@@ -1,84 +0,0 @@
-# RapidCheck property-based testing for Bitcoin Core
-
-## Concept
-
-Property-based testing is experimentally being added to Bitcoin Core with
-[RapidCheck](https://github.com/emil-e/rapidcheck), a C++ framework for
-property-based testing inspired by the Haskell library
-[QuickCheck](https://hackage.haskell.org/package/QuickCheck).
-
-RapidCheck performs random testing of program properties. A specification of the
-program is given in the form of properties which functions should satisfy, and
-RapidCheck tests that the properties hold in a large number of randomly
-generated cases.
-
-If an exception is found, RapidCheck tries to find the smallest case, for some
-definition of smallest, for which the property is still false and displays it as
-a counter-example. For example, if the input is an integer, RapidCheck tries to
-find the smallest integer for which the property is false.
-
-## Running
-
-If RapidCheck is installed, Bitcoin Core will automatically run the
-property-based tests with the unit tests during `make check`, unless the
-`--without-rapidcheck` flag is passed when configuring.
-
-For more information, run `./configure --help` and see `--with-rapidcheck` under
-Optional Packages.
-
-## Setup
-
-The following instructions have been tested with Linux Debian and macOS.
-
-1. Clone the RapidCheck source code and cd into the repository.
-
- ```shell
- git clone https://github.com/emil-e/rapidcheck.git
- cd rapidcheck
- ```
-
-2. Build RapidCheck (requires CMake to be installed).
-
- ```shell
- cmake -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=true -DRC_ENABLE_BOOST_TEST=ON $(pwd)
- make && make install
- ```
-
-3. Configure Bitcoin Core with RapidCheck.
-
- `cd` to the directory of your local bitcoin repository and run
- `./configure`. In the output you should see:
-
- ```shell
- checking rapidcheck.h usability... yes
- checking rapidcheck.h presence... yes
- checking for rapidcheck.h... yes
- [...]
- Options used to compile and link:
- [...]
- with test = yes
- with prop = yes
- ```
-
-4. Build Bitcoin Core with RapidCheck.
-
- Now you can run `make` and should see the property-based tests compiled with
- the unit tests:
-
- ```shell
- Making all in src
- [...]
- CXX test/gen/test_bitcoin-crypto_gen.o
- CXX test/test_bitcoin-key_properties.o
- ```
-
-5. Run the unit tests with `make check`. The property-based tests will be run
- with the unit tests.
-
- ```shell
- Running tests: crypto_tests from test/crypto_tests.cpp
- [...]
- Running tests: key_properties from test/key_properties.cpp
- ```
-
-That's it! You are now running property-based tests in Bitcoin Core.
diff --git a/doc/reduce-memory.md b/doc/reduce-memory.md
index b0faf0825a..6e7a578ecc 100644
--- a/doc/reduce-memory.md
+++ b/doc/reduce-memory.md
@@ -24,8 +24,9 @@ The size of some in-memory caches can be reduced. As caches trade off memory usa
## Number of peers
-- `-maxconnections=<n>` - the maximum number of connections, this defaults to `125`. Each active connection takes up some memory. Only significant if incoming
- connections are enabled, otherwise the number of connections will never be more than `8`.
+- `-maxconnections=<n>` - the maximum number of connections, this defaults to 125. Each active connection takes up some
+ memory. This option applies only if incoming connections are enabled, otherwise the number of connections will never
+ be more than 10. Of the 10 outbound peers, there can be 8 full-relay connections and 2 block-relay-only ones.
## Thread configuration
diff --git a/doc/reduce-traffic.md b/doc/reduce-traffic.md
index 5a71f62e0f..e39e43df7a 100644
--- a/doc/reduce-traffic.md
+++ b/doc/reduce-traffic.md
@@ -3,8 +3,10 @@ Reduce Traffic
Some node operators need to deal with bandwidth caps imposed by their ISPs.
-By default, Bitcoin Core allows up to 125 connections to different peers, 8 of
-which are outbound. You can therefore, have at most 117 inbound connections.
+By default, Bitcoin Core allows up to 125 connections to different peers, 10 of
+which are outbound. You can therefore, have at most 115 inbound connections.
+Of the 10 outbound peers, there can be 8 full-relay connections and 2
+block-relay-only ones.
The default settings can result in relatively significant traffic consumption.
@@ -26,7 +28,7 @@ calculating the target.
## 2. Disable "listening" (`-listen=0`)
-Disabling listening will result in fewer nodes connected (remember the maximum of 8
+Disabling listening will result in fewer nodes connected (remember the maximum of 10
outbound peers). Fewer nodes will result in less traffic usage as you are relaying
blocks and transactions to fewer nodes.
@@ -44,7 +46,11 @@ with other peers, you can disable transaction relay.
Be reminded of the effects of this setting.
- Fee estimation will no longer work.
-- Not relaying other's transactions could hurt your privacy if used while a
- wallet is loaded or if you use the node to broadcast transactions.
+- It sets the flag "-walletbroadcast" to be "0", only if it is currently unset.
+ Doing so disables the automatic broadcasting of transactions from wallet. Not
+ relaying other's transactions could hurt your privacy if used while a wallet
+ is loaded or if you use the node to broadcast transactions.
+- If a peer is whitelisted and "-whitelistforcerelay" is set to "1" (which will
+ also set "whitelistrelay" to "1"), we will still receive and relay their transactions.
- It makes block propagation slower because compact block relay can only be
used when transaction relay is enabled.
diff --git a/doc/release-notes-15437.md b/doc/release-notes-15437.md
deleted file mode 100644
index 6614207757..0000000000
--- a/doc/release-notes-15437.md
+++ /dev/null
@@ -1,53 +0,0 @@
-P2P and network changes
------------------------
-
-#### Removal of reject network messages from Bitcoin Core (BIP61)
-
-The command line option to enable BIP61 (`-enablebip61`) has been removed.
-
-This feature has been disabled by default since Bitcoin Core version 0.18.0.
-Nodes on the network can not generally be trusted to send valid ("reject")
-messages, so this should only ever be used when connected to a trusted node.
-Please use the recommended alternatives if you rely on this deprecated feature:
-
-* Testing or debugging of implementations of the Bitcoin P2P network protocol
- should be done by inspecting the log messages that are produced by a recent
- version of Bitcoin Core. Bitcoin Core logs debug messages
- (`-debug=<category>`) to a stream (`-printtoconsole`) or to a file
- (`-debuglogfile=<debug.log>`).
-
-* Testing the validity of a block can be achieved by specific RPCs:
- - `submitblock`
- - `getblocktemplate` with `'mode'` set to `'proposal'` for blocks with
- potentially invalid POW
-
-* Testing the validity of a transaction can be achieved by specific RPCs:
- - `sendrawtransaction`
- - `testmempoolaccept`
-
-* Wallets should not use the absence of "reject" messages to indicate a
- transaction has propagated the network, nor should wallets use "reject"
- messages to set transaction fees. Wallets should rather use fee estimation
- to determine transaction fees and set replace-by-fee if desired. Thus, they
- could wait until the transaction has confirmed (taking into account the fee
- target they set (compare the RPC `estimatesmartfee`)) or listen for the
- transaction announcement by other network peers to check for propagation.
-
-The removal of BIP61 REJECT message support also has the following minor RPC
-and logging implications:
-
-* `testmempoolaccept` and `sendrawtransaction` no longer return the P2P REJECT
- code when a transaction is not accepted to the mempool. They still return the
- verbal reject reason.
-
-* Log messages that previously reported the REJECT code when a transaction was
- not accepted to the mempool now no longer report the REJECT code. The reason
- for rejection is still reported.
-
-Updated RPCs
-------------
-
-- `testmempoolaccept` and `sendrawtransaction` no longer return the P2P REJECT
- code when a transaction is not accepted to the mempool. See the Section
- _Removal of reject network messages from Bitcoin Core (BIP61)_ for details on
- the removal of BIP61 REJECT message support.
diff --git a/doc/release-notes-15954.md b/doc/release-notes-15954.md
deleted file mode 100644
index f4d2c5688c..0000000000
--- a/doc/release-notes-15954.md
+++ /dev/null
@@ -1,4 +0,0 @@
-Configuration option changes
------------------------------
-
-Importing blocks upon startup via the `bootstrap.dat` file no longer occurs by default. The file must now be specified with `-loadblock=<file>`.
diff --git a/doc/release-notes-17056.md b/doc/release-notes-17056.md
deleted file mode 100644
index 23d5a8c8cd..0000000000
--- a/doc/release-notes-17056.md
+++ /dev/null
@@ -1,4 +0,0 @@
-Low-level RPC Changes
-===
-
-- A new descriptor type `sortedmulti(...)` has been added to support multisig scripts where the public keys are sorted lexicographically in the resulting script.
diff --git a/doc/release-notes-17410.md b/doc/release-notes-17410.md
deleted file mode 100644
index 08ed353889..0000000000
--- a/doc/release-notes-17410.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Command-line options
---------------------
-
-- The `-debug=db` logging category has been renamed to `-debug=walletdb`, to distinguish it from `coindb`.
- `-debug=db` has been deprecated and will be removed in the next major release.
diff --git a/doc/release-notes-17437.md b/doc/release-notes-17437.md
deleted file mode 100644
index 3edfd00a38..0000000000
--- a/doc/release-notes-17437.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Low-level RPC Changes
-===
-
-- The RPC gettransaction, listtransactions and listsinceblock responses now also
-includes the height of the block that contains the wallet transaction, if any.
diff --git a/doc/release-notes-17578.md b/doc/release-notes-17578.md
deleted file mode 100644
index 664d17fd78..0000000000
--- a/doc/release-notes-17578.md
+++ /dev/null
@@ -1,13 +0,0 @@
-Deprecated or removed RPCs
---------------------------
-
-- RPC `getaddressinfo` changes:
-
- - the `label` field has been deprecated in favor of the `labels` field and
- will be removed in 0.21. It can be re-enabled in the interim by launching
- with `-deprecatedrpc=label`.
-
- - the `labels` behavior of returning an array of JSON objects containing name
- and purpose key/value pairs has been deprecated in favor of an array of
- label names and will be removed in 0.21. The previous behavior can be
- re-enabled in the interim by launching with `-deprecatedrpc=labelspurpose`.
diff --git a/doc/release-notes.md b/doc/release-notes.md
index eec1ef9c46..0d668a6302 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -62,44 +62,41 @@ distribution provides binaries for the RISC-V platform.
Notable changes
===============
-Build System
-------------
+P2P and network changes
+-----------------------
-- OpenSSL is no longer used by Bitcoin Core. The last usage of the library
-was removed in #17265.
+Updated RPCs
+------------
-- glibc 2.17 or greater is now required to run the release binaries. This
-retains compatibility with RHEL 7, CentOS 7, Debian 8 and Ubuntu 14.04 LTS.
-Further details can be found in #17538.
+Changes to Wallet or GUI related RPCs can be found in the GUI or Wallet section below.
New RPCs
--------
-New settings
+Build System
------------
-- RPC Whitelist system. It can give certain RPC users permissions to only some RPC calls.
-It can be set with two command line arguments (`rpcwhitelist` and `rpcwhitelistdefault`). (#12763)
-
Updated settings
----------------
-Updated RPCs
-------------
+Changes to Wallet or GUI related settings can be found in the GUI or Wallet section below.
-Note: some low-level RPC changes mainly useful for testing are described in the
-Low-level Changes section below.
-
-GUI changes
------------
-
-- The "Start Bitcoin Core on system login" option has been removed on macOS.
+New settings
+------------
Wallet
------
-- The wallet now by default uses bech32 addresses when using RPC, and creates native segwit change outputs.
-- The way that output trust was computed has been fixed in #16766, which impacts confirmed/unconfirmed balance status and coin selection.
+#### 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
+-----------
Low-level changes
=================
@@ -107,14 +104,6 @@ Low-level changes
Tests
-----
-- It is now an error to use an unqualified `walletdir=path` setting in the config file if running on testnet or regtest
- networks. The setting now needs to be qualified as `chain.walletdir=path` or placed in the appropriate `[chain]`
- section. (#17447)
-
-- `-fallbackfee` was 0 (disabled) by default for the main chain, but 0.0002 by default for the test chains. Now it is 0
- by default for all chains. Testnet and regtest users will have to add `fallbackfee=0.0002` to their configuration if
- they weren't setting it and they want it to keep working like before. (#16524)
-
Credits
=======
diff --git a/doc/release-notes/release-notes-0.19.1.md b/doc/release-notes/release-notes-0.19.1.md
new file mode 100644
index 0000000000..5746bebb0d
--- /dev/null
+++ b/doc/release-notes/release-notes-0.19.1.md
@@ -0,0 +1,115 @@
+0.19.1 Release Notes
+===============================
+
+Bitcoin Core version 0.19.1 is now available from:
+
+ <https://bitcoincore.org/bin/bitcoin-core-0.19.1/>
+
+This minor release includes various bug fixes and performance
+improvements, as well as updated translations.
+
+Please report bugs using the issue tracker at GitHub:
+
+ <https://github.com/bitcoin/bitcoin/issues>
+
+To receive security and update notifications, please subscribe to:
+
+ <https://bitcoincore.org/en/list/announcements/join/>
+
+How to Upgrade
+==============
+
+If you are running an older version, shut it down. Wait until it has completely
+shut down (which might take a few minutes for older versions), then run the
+installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on Mac)
+or `bitcoind`/`bitcoin-qt` (on Linux).
+
+Upgrading directly from a version of Bitcoin Core that has reached its EOL is
+possible, but it might take some time if the datadir needs to be migrated. Old
+wallet versions of Bitcoin Core are generally supported.
+
+Compatibility
+==============
+
+Bitcoin Core is supported and extensively tested on operating systems using
+the Linux kernel, macOS 10.10+, and Windows 7 and newer. It is not recommended
+to use Bitcoin Core on unsupported systems.
+
+Bitcoin Core should also work on most other Unix-like systems but is not
+as frequently tested on them.
+
+From Bitcoin Core 0.17.0 onwards, macOS versions earlier than 10.10 are no
+longer supported, as Bitcoin Core is now built using Qt 5.9.x which requires
+macOS 10.10+. Additionally, Bitcoin Core does not yet change appearance when
+macOS "dark mode" is activated.
+
+In addition to previously supported CPU platforms, this release's pre-compiled
+distribution provides binaries for the RISC-V platform.
+
+0.19.1 change log
+=================
+
+### Wallet
+- #17643 Fix origfee return for bumpfee with feerate arg (instagibbs)
+- #16963 Fix `unique_ptr` usage in boost::signals2 (promag)
+- #17258 Fix issue with conflicted mempool tx in listsinceblock (adamjonas, mchrostowski)
+- #17924 Bug: IsUsedDestination shouldn't use key id as script id for ScriptHash (instagibbs)
+- #17621 IsUsedDestination should count any known single-key address (instagibbs)
+- #17843 Reset reused transactions cache (fjahr)
+
+### RPC and other APIs
+- #17687 cli: Fix fatal leveldb error when specifying -blockfilterindex=basic twice (brakmic)
+- #17728 require second argument only for scantxoutset start action (achow101)
+- #17445 zmq: Fix due to invalid argument and multiple notifiers (promag)
+- #17524 psbt: handle unspendable psbts (achow101)
+- #17156 psbt: check that various indexes and amounts are within bounds (achow101)
+
+### GUI
+- #17427 Fix missing qRegisterMetaType for `size_t` (hebasto)
+- #17695 disable File-\>CreateWallet during startup (fanquake)
+- #17634 Fix comparison function signature (hebasto)
+- #18062 Fix unintialized WalletView::progressDialog (promag)
+
+### Tests and QA
+- #17416 Appveyor improvement - text file for vcpkg package list (sipsorcery)
+- #17488 fix "bitcoind already running" warnings on macOS (fanquake)
+- #17980 add missing #include to fix compiler errors (kallewoof)
+
+### Platform support
+- #17736 Update msvc build for Visual Studio 2019 v16.4 (sipsorcery)
+- #17364 Updates to appveyor config for VS2019 and Qt5.9.8 + msvc project fixes (sipsorcery)
+- #17887 bug-fix macos: give free bytes to `F_PREALLOCATE` (kallewoof)
+
+### Miscellaneous
+- #17897 init: Stop indexes on shutdown after ChainStateFlushed callback (jimpo)
+- #17450 util: Add missing headers to util/fees.cpp (hebasto)
+- #17654 Unbreak build with Boost 1.72.0 (jbeich)
+- #17857 scripts: Fix symbol-check & security-check argument passing (fanquake)
+- #17762 Log to net category for exceptions in ProcessMessages (laanwj)
+- #18100 Update univalue subtree (MarcoFalke)
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- Aaron Clauson
+- Adam Jonas
+- Andrew Chow
+- Fabian Jahr
+- fanquake
+- Gregory Sanders
+- Harris
+- Hennadii Stepanov
+- Jan Beich
+- Jim Posen
+- João Barbosa
+- Karl-Johan Alm
+- Luke Dashjr
+- MarcoFalke
+- Michael Chrostowski
+- Russell Yanofsky
+- Wladimir J. van der Laan
+
+As well as to everyone that helped with translations on
+[Transifex](https://www.transifex.com/bitcoin/bitcoin/).
diff --git a/doc/release-process.md b/doc/release-process.md
index 1ffef3e106..a61b67c35f 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -121,7 +121,7 @@ Ensure gitian-builder is up-to-date:
echo '5a60e0a4b3e0b4d655317b2f12a810211c50242138322b16e7e01c6fbb89d92f inputs/osslsigncode-2.0.tar.gz' | sha256sum -c
popd
-Create the macOS SDK tarball, see the [macOS build instructions](build-osx.md#deterministic-macos-dmg-notes) for details, and copy it into the inputs directory.
+Create the macOS SDK tarball, see the [macdeploy instructions](/contrib/macdeploy/README.md#deterministic-macos-dmg-notes) for details, and copy it into the inputs directory.
### Optional: Seed the Gitian sources cache and offline git repositories
@@ -219,7 +219,7 @@ Codesigner only: Commit the detached codesign payloads:
rm -rf *
tar xf signature-osx.tar.gz
tar xf signature-win.tar.gz
- git add -a
+ git add -A
git commit -m "point to ${VERSION}"
git tag -s v${VERSION} HEAD
git push the current branch and new tag
@@ -268,7 +268,6 @@ The list of files should be:
```
bitcoin-${VERSION}-aarch64-linux-gnu.tar.gz
bitcoin-${VERSION}-arm-linux-gnueabihf.tar.gz
-bitcoin-${VERSION}-i686-pc-linux-gnu.tar.gz
bitcoin-${VERSION}-riscv64-linux-gnu.tar.gz
bitcoin-${VERSION}-x86_64-linux-gnu.tar.gz
bitcoin-${VERSION}-osx64.tar.gz
@@ -329,8 +328,6 @@ bitcoin.org (see below for bitcoin.org update instructions).
- Update packaging repo
- - Notify BlueMatt so that he can start building [the PPAs](https://launchpad.net/~bitcoin/+archive/ubuntu/bitcoin)
-
- Push the flatpak to flathub, e.g. https://github.com/flathub/org.bitcoincore.bitcoin-qt/pull/2
- Push the latest version to master (if applicable), e.g. https://github.com/bitcoin-core/packaging/pull/32
diff --git a/share/genbuild.sh b/share/genbuild.sh
index 197787d5e0..81fa2ed5d0 100755
--- a/share/genbuild.sh
+++ b/share/genbuild.sh
@@ -18,13 +18,9 @@ else
exit 1
fi
-git_check_in_repo() {
- ! { git status --porcelain -uall --ignored "$@" 2>/dev/null || echo '??'; } | grep -q '?'
-}
-
DESC=""
SUFFIX=""
-if [ "${BITCOIN_GENBUILD_NO_GIT}" != "1" ] && [ -e "$(command -v git)" ] && [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] && git_check_in_repo share/genbuild.sh; then
+if [ "${BITCOIN_GENBUILD_NO_GIT}" != "1" ] && [ -e "$(command -v git)" ] && [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then
# clean 'dirty' status of touched files that haven't been modified
git diff >/dev/null 2>/dev/null
diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in
index 275078c88d..3befba3425 100644
--- a/share/qt/Info.plist.in
+++ b/share/qt/Info.plist.in
@@ -16,7 +16,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
- <key>CFBundleGetInfoString</key>
+ <key>NSHumanReadableCopyright</key>
<string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@, Copyright © 2009-@COPYRIGHT_YEAR@ @COPYRIGHT_HOLDERS_FINAL@</string>
<key>CFBundleShortVersionString</key>
diff --git a/share/setup.nsi.in b/share/setup.nsi.in
index dd9ee54d6d..4b2903a7c9 100644
--- a/share/setup.nsi.in
+++ b/share/setup.nsi.in
@@ -2,6 +2,11 @@ Name "@PACKAGE_NAME@ (64-bit)"
RequestExecutionLevel highest
SetCompressor /SOLID lzma
+SetDateSave off
+
+# Uncomment these lines when investigating reproducibility errors
+#SetCompress off
+#SetDatablockOptimize off
# General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)"
diff --git a/src/Makefile.am b/src/Makefile.am
index e58a89ca03..627df97cad 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -178,7 +178,6 @@ BITCOIN_CORE_H = \
random.h \
randomenv.h \
reverse_iterator.h \
- reverselock.h \
rpc/blockchain.h \
rpc/client.h \
rpc/protocol.h \
@@ -216,10 +215,12 @@ BITCOIN_CORE_H = \
util/check.h \
util/error.h \
util/fees.h \
+ util/golombrice.h \
util/spanparsing.h \
util/system.h \
util/macros.h \
util/memory.h \
+ util/message.h \
util/moneystr.h \
util/rbf.h \
util/settings.h \
@@ -228,7 +229,6 @@ BITCOIN_CORE_H = \
util/time.h \
util/translation.h \
util/url.h \
- util/validation.h \
util/vector.h \
validation.h \
validationinterface.h \
@@ -242,7 +242,6 @@ BITCOIN_CORE_H = \
wallet/fees.h \
wallet/ismine.h \
wallet/load.h \
- wallet/psbtwallet.h \
wallet/rpcwallet.h \
wallet/scriptpubkeyman.h \
wallet/wallet.h \
@@ -350,7 +349,6 @@ libbitcoin_wallet_a_SOURCES = \
wallet/feebumper.cpp \
wallet/fees.cpp \
wallet/load.cpp \
- wallet/psbtwallet.cpp \
wallet/rpcdump.cpp \
wallet/rpcwallet.cpp \
wallet/scriptpubkeyman.cpp \
@@ -517,6 +515,7 @@ libbitcoin_util_a_SOURCES = \
util/error.cpp \
util/fees.cpp \
util/system.cpp \
+ util/message.cpp \
util/moneystr.cpp \
util/rbf.cpp \
util/settings.cpp \
@@ -525,10 +524,12 @@ libbitcoin_util_a_SOURCES = \
util/strencodings.cpp \
util/string.cpp \
util/time.cpp \
- util/url.cpp \
- util/validation.cpp \
$(BITCOIN_CORE_H)
+if USE_LIBEVENT
+libbitcoin_util_a_SOURCES += util/url.cpp
+endif
+
if GLIBC_BACK_COMPAT
libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp
AM_LDFLAGS += $(COMPAT_LDFLAGS)
@@ -706,6 +707,11 @@ if TARGET_DARWIN
$(AM_V_at) OTOOL=$(OTOOL) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
endif
+if TARGET_WINDOWS
+ @echo "Checking Windows dynamic libraries..."
+ $(AM_V_at) OBJDUMP=$(OBJDUMP) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
+endif
+
if GLIBC_BACK_COMPAT
@echo "Checking glibc back compat..."
$(AM_V_at) READELF=$(READELF) CPPFILT=$(CPPFILT) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
@@ -718,10 +724,12 @@ if HARDEN
endif
if EMBEDDED_LEVELDB
+include Makefile.crc32c.include
include Makefile.leveldb.include
endif
include Makefile.test_util.include
+include Makefile.test_fuzz.include
if ENABLE_TESTS
include Makefile.test.include
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 1c97e22de8..766c0fca54 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -12,6 +12,7 @@ GENERATED_BENCH_FILES = $(RAW_BENCH_FILES:.raw=.raw.h)
bench_bench_bitcoin_SOURCES = \
$(RAW_BENCH_FILES) \
+ bench/addrman.cpp \
bench/bench_bitcoin.cpp \
bench/bench.cpp \
bench/bench.h \
@@ -43,12 +44,11 @@ bench_bench_bitcoin_SOURCES = \
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
-bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
+bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
bench_bench_bitcoin_LDADD = \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_WALLET) \
- $(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
diff --git a/src/Makefile.crc32c.include b/src/Makefile.crc32c.include
new file mode 100644
index 0000000000..802b3a2e4b
--- /dev/null
+++ b/src/Makefile.crc32c.include
@@ -0,0 +1,75 @@
+# Copyright (c) 2019 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+LIBCRC32C_INT = crc32c/libcrc32c.a
+LIBLEVELDB_SSE42_INT = leveldb/libleveldb_sse42.a
+
+EXTRA_LIBRARIES += $(LIBCRC32C_INT)
+
+LIBCRC32C = $(LIBCRC32C_INT)
+
+CRC32C_CPPFLAGS_INT =
+CRC32C_CPPFLAGS_INT += -I$(srcdir)/crc32c/include
+CRC32C_CPPFLAGS_INT += -DHAVE_BUILTIN_PREFETCH=@HAVE_BUILTIN_PREFETCH@
+CRC32C_CPPFLAGS_INT += -DHAVE_MM_PREFETCH=@HAVE_MM_PREFETCH@
+CRC32C_CPPFLAGS_INT += -DHAVE_STRONG_GETAUXVAL=@HAVE_STRONG_GETAUXVAL@
+CRC32C_CPPFLAGS_INT += -DHAVE_WEAK_GETAUXVAL=@HAVE_WEAK_GETAUXVAL@
+CRC32C_CPPFLAGS_INT += -DCRC32C_TESTS_BUILT_WITH_GLOG=0
+
+if ENABLE_SSE42
+CRC32C_CPPFLAGS_INT += -DHAVE_SSE42=1
+else
+CRC32C_CPPFLAGS_INT += -DHAVE_SSE42=0
+endif
+
+if ENABLE_ARM_CRC
+CRC32C_CPPFLAGS_INT += -DHAVE_ARM64_CRC32C=1
+else
+CRC32C_CPPFLAGS_INT += -DHAVE_ARM64_CRC32C=0
+endif
+
+if WORDS_BIGENDIAN
+CRC32C_CPPFLAGS_INT += -DBYTE_ORDER_BIG_ENDIAN=1
+else
+CRC32C_CPPFLAGS_INT += -DBYTE_ORDER_BIG_ENDIAN=0
+endif
+
+crc32c_libcrc32c_a_CPPFLAGS = $(AM_CPPFLAGS) $(CRC32C_CPPFLAGS_INT) $(CRC32C_CPPFLAGS)
+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_internal.h
+crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_prefetch.h
+crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_read_le.h
+crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_round_up.h
+crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_sse42_check.h
+crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_sse42.h
+
+crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c.cc
+crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_portable.cc
+
+if ENABLE_SSE42
+LIBCRC32C_SSE42_INT = crc32c/libcrc32c_sse42.a
+EXTRA_LIBRARIES += $(LIBCRC32C_SSE42_INT)
+LIBCRC32C += $(LIBCRC32C_SSE42_INT)
+
+crc32c_libcrc32c_sse42_a_CPPFLAGS = $(crc32c_libcrc32c_a_CPPFLAGS)
+crc32c_libcrc32c_sse42_a_CXXFLAGS = $(crc32c_libcrc32c_a_CXXFLAGS) $(SSE42_CXXFLAGS)
+
+crc32c_libcrc32c_sse42_a_SOURCES = crc32c/src/crc32c_sse42.cc
+endif
+
+if ENABLE_ARM_CRC
+LIBCRC32C_ARM_CRC_INT = crc32c/libcrc32c_arm_crc.a
+EXTRA_LIBRARIES += $(LIBCRC32C_ARM_CRC_INT)
+LIBCRC32C += $(LIBCRC32C_ARM_CRC_INT)
+
+crc32c_libcrc32c_arm_crc_a_CPPFLAGS = $(crc32c_libcrc32c_a_CPPFLAGS)
+crc32c_libcrc32c_arm_crc_a_CXXFLAGS = $(crc32c_libcrc32c_a_CXXFLAGS) $(ARM_CRC_CXXFLAGS)
+
+crc32c_libcrc32c_arm_crc_a_SOURCES = crc32c/src/crc32c_arm64.cc
+endif
diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include
index bd08bcb4ed..04b53471e4 100644
--- a/src/Makefile.leveldb.include
+++ b/src/Makefile.leveldb.include
@@ -4,27 +4,33 @@
LIBLEVELDB_INT = leveldb/libleveldb.a
LIBMEMENV_INT = leveldb/libmemenv.a
-LIBLEVELDB_SSE42_INT = leveldb/libleveldb_sse42.a
EXTRA_LIBRARIES += $(LIBLEVELDB_INT)
EXTRA_LIBRARIES += $(LIBMEMENV_INT)
-EXTRA_LIBRARIES += $(LIBLEVELDB_SSE42_INT)
-LIBLEVELDB += $(LIBLEVELDB_INT)
+LIBLEVELDB += $(LIBLEVELDB_INT) $(LIBCRC32C)
LIBMEMENV += $(LIBMEMENV_INT)
-LIBLEVELDB_SSE42 = $(LIBLEVELDB_SSE42_INT)
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv
LEVELDB_CPPFLAGS_INT =
LEVELDB_CPPFLAGS_INT += -I$(srcdir)/leveldb
-LEVELDB_CPPFLAGS_INT += $(LEVELDB_TARGET_FLAGS)
-LEVELDB_CPPFLAGS_INT += -DLEVELDB_ATOMIC_PRESENT
+LEVELDB_CPPFLAGS_INT += -I$(srcdir)/crc32c/include
LEVELDB_CPPFLAGS_INT += -D__STDC_LIMIT_MACROS
+LEVELDB_CPPFLAGS_INT += -DHAVE_SNAPPY=0 -DHAVE_CRC32C=1
+LEVELDB_CPPFLAGS_INT += -DHAVE_FDATASYNC=@HAVE_FDATASYNC@
+LEVELDB_CPPFLAGS_INT += -DHAVE_FULLFSYNC=@HAVE_FULLFSYNC@
+LEVELDB_CPPFLAGS_INT += -DHAVE_O_CLOEXEC=@HAVE_O_CLOEXEC@
+
+if WORDS_BIGENDIAN
+LEVELDB_CPPFLAGS_INT += -DLEVELDB_IS_BIG_ENDIAN=1
+else
+LEVELDB_CPPFLAGS_INT += -DLEVELDB_IS_BIG_ENDIAN=0
+endif
if TARGET_WINDOWS
-LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_WINDOWS -D__USE_MINGW_ANSI_STDIO=1
+LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_WINDOWS -D_UNICODE -DUNICODE -D__USE_MINGW_ANSI_STDIO=1
else
LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_POSIX
endif
@@ -33,12 +39,8 @@ leveldb_libleveldb_a_CPPFLAGS = $(AM_CPPFLAGS) $(LEVELDB_CPPFLAGS_INT) $(LEVELDB
leveldb_libleveldb_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
leveldb_libleveldb_a_SOURCES=
-leveldb_libleveldb_a_SOURCES += leveldb/port/atomic_pointer.h
-leveldb_libleveldb_a_SOURCES += leveldb/port/port_example.h
-leveldb_libleveldb_a_SOURCES += leveldb/port/port_posix.h
-leveldb_libleveldb_a_SOURCES += leveldb/port/win/stdint.h
+leveldb_libleveldb_a_SOURCES += leveldb/port/port_stdcxx.h
leveldb_libleveldb_a_SOURCES += leveldb/port/port.h
-leveldb_libleveldb_a_SOURCES += leveldb/port/port_win.h
leveldb_libleveldb_a_SOURCES += leveldb/port/thread_annotations.h
leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/db.h
leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/options.h
@@ -47,6 +49,7 @@ leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/filter_policy.h
leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/slice.h
leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/table_builder.h
leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/env.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/export.h
leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/c.h
leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/iterator.h
leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/cache.h
@@ -78,6 +81,7 @@ leveldb_libleveldb_a_SOURCES += leveldb/table/format.h
leveldb_libleveldb_a_SOURCES += leveldb/table/iterator_wrapper.h
leveldb_libleveldb_a_SOURCES += leveldb/util/crc32c.h
leveldb_libleveldb_a_SOURCES += leveldb/util/env_posix_test_helper.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/env_windows_test_helper.h
leveldb_libleveldb_a_SOURCES += leveldb/util/arena.h
leveldb_libleveldb_a_SOURCES += leveldb/util/random.h
leveldb_libleveldb_a_SOURCES += leveldb/util/posix_logger.h
@@ -87,7 +91,9 @@ leveldb_libleveldb_a_SOURCES += leveldb/util/coding.h
leveldb_libleveldb_a_SOURCES += leveldb/util/testutil.h
leveldb_libleveldb_a_SOURCES += leveldb/util/mutexlock.h
leveldb_libleveldb_a_SOURCES += leveldb/util/logging.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/no_destructor.h
leveldb_libleveldb_a_SOURCES += leveldb/util/testharness.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/windows_logger.h
leveldb_libleveldb_a_SOURCES += leveldb/db/builder.cc
leveldb_libleveldb_a_SOURCES += leveldb/db/c.cc
@@ -120,7 +126,6 @@ leveldb_libleveldb_a_SOURCES += leveldb/util/coding.cc
leveldb_libleveldb_a_SOURCES += leveldb/util/comparator.cc
leveldb_libleveldb_a_SOURCES += leveldb/util/crc32c.cc
leveldb_libleveldb_a_SOURCES += leveldb/util/env.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/env_posix.cc
leveldb_libleveldb_a_SOURCES += leveldb/util/filter_policy.cc
leveldb_libleveldb_a_SOURCES += leveldb/util/hash.cc
leveldb_libleveldb_a_SOURCES += leveldb/util/histogram.cc
@@ -129,21 +134,12 @@ leveldb_libleveldb_a_SOURCES += leveldb/util/options.cc
leveldb_libleveldb_a_SOURCES += leveldb/util/status.cc
if TARGET_WINDOWS
-leveldb_libleveldb_a_SOURCES += leveldb/util/env_win.cc
-leveldb_libleveldb_a_SOURCES += leveldb/port/port_win.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/env_windows.cc
else
-leveldb_libleveldb_a_SOURCES += leveldb/port/port_posix.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/env_posix.cc
endif
leveldb_libmemenv_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS)
leveldb_libmemenv_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS)
leveldb_libmemenv_a_SOURCES = leveldb/helpers/memenv/memenv.cc
leveldb_libmemenv_a_SOURCES += leveldb/helpers/memenv/memenv.h
-
-leveldb_libleveldb_sse42_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS)
-leveldb_libleveldb_sse42_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS)
-if ENABLE_HWCRC32
-leveldb_libleveldb_sse42_a_CPPFLAGS += -DLEVELDB_PLATFORM_POSIX_SSE
-leveldb_libleveldb_sse42_a_CXXFLAGS += $(SSE42_CXXFLAGS)
-endif
-leveldb_libleveldb_sse42_a_SOURCES = leveldb/port/port_posix_sse.cc
diff --git a/src/Makefile.qt_locale.include b/src/Makefile.qt_locale.include
index 79db5cd7b4..3ac21b1326 100644
--- a/src/Makefile.qt_locale.include
+++ b/src/Makefile.qt_locale.include
@@ -1,47 +1,39 @@
QT_TS = \
+ qt/locale/bitcoin_af.ts \
+ qt/locale/bitcoin_am.ts \
qt/locale/bitcoin_ar.ts \
- qt/locale/bitcoin_be_BY.ts \
+ qt/locale/bitcoin_be.ts \
+ qt/locale/bitcoin_bg.ts \
+ qt/locale/bitcoin_bn.ts \
+ qt/locale/bitcoin_bs.ts \
qt/locale/bitcoin_ca.ts \
qt/locale/bitcoin_cs.ts \
- qt/locale/bitcoin_cs_CZ.ts \
qt/locale/bitcoin_cy.ts \
qt/locale/bitcoin_da.ts \
qt/locale/bitcoin_de.ts \
- qt/locale/bitcoin_de_DE.ts \
qt/locale/bitcoin_el.ts \
- qt/locale/bitcoin_el_GR.ts \
qt/locale/bitcoin_en.ts \
- qt/locale/bitcoin_en_AU.ts \
qt/locale/bitcoin_en_GB.ts \
qt/locale/bitcoin_eo.ts \
qt/locale/bitcoin_es.ts \
qt/locale/bitcoin_es_CL.ts \
qt/locale/bitcoin_es_CO.ts \
qt/locale/bitcoin_es_DO.ts \
- qt/locale/bitcoin_es_ES.ts \
qt/locale/bitcoin_es_MX.ts \
qt/locale/bitcoin_es_VE.ts \
qt/locale/bitcoin_et.ts \
- qt/locale/bitcoin_et_EE.ts \
qt/locale/bitcoin_eu.ts \
qt/locale/bitcoin_fa.ts \
qt/locale/bitcoin_fi.ts \
qt/locale/bitcoin_fil.ts \
qt/locale/bitcoin_fr.ts \
- qt/locale/bitcoin_fr_CA.ts \
- qt/locale/bitcoin_fr_FR.ts \
- qt/locale/bitcoin_gl.ts \
qt/locale/bitcoin_he.ts \
- qt/locale/bitcoin_he_IL.ts \
qt/locale/bitcoin_hi.ts \
qt/locale/bitcoin_hr.ts \
qt/locale/bitcoin_hu.ts \
- qt/locale/bitcoin_hu_HU.ts \
qt/locale/bitcoin_id.ts \
- qt/locale/bitcoin_id_ID.ts \
qt/locale/bitcoin_is.ts \
qt/locale/bitcoin_it.ts \
- qt/locale/bitcoin_it_IT.ts \
qt/locale/bitcoin_ja.ts \
qt/locale/bitcoin_ka.ts \
qt/locale/bitcoin_kk.ts \
@@ -52,32 +44,26 @@ QT_TS = \
qt/locale/bitcoin_la.ts \
qt/locale/bitcoin_lt.ts \
qt/locale/bitcoin_lv.ts \
- qt/locale/bitcoin_lv_LV.ts \
qt/locale/bitcoin_mk.ts \
qt/locale/bitcoin_ml.ts \
qt/locale/bitcoin_mn.ts \
qt/locale/bitcoin_mr_IN.ts \
qt/locale/bitcoin_ms.ts \
- qt/locale/bitcoin_ms_MY.ts \
+ qt/locale/bitcoin_my.ts \
qt/locale/bitcoin_nb.ts \
qt/locale/bitcoin_ne.ts \
qt/locale/bitcoin_nl.ts \
- qt/locale/bitcoin_nl_NL.ts \
qt/locale/bitcoin_pam.ts \
qt/locale/bitcoin_pl.ts \
qt/locale/bitcoin_pt.ts \
qt/locale/bitcoin_pt_BR.ts \
- qt/locale/bitcoin_pt_PT.ts \
qt/locale/bitcoin_ro.ts \
- qt/locale/bitcoin_ro_RO.ts \
qt/locale/bitcoin_ru.ts \
- qt/locale/bitcoin_ru_RU.ts \
qt/locale/bitcoin_si.ts \
qt/locale/bitcoin_sk.ts \
- qt/locale/bitcoin_sk_SK.ts \
qt/locale/bitcoin_sl.ts \
- qt/locale/bitcoin_sl_SI.ts \
qt/locale/bitcoin_sn.ts \
+ qt/locale/bitcoin_sq.ts \
qt/locale/bitcoin_sr.ts \
qt/locale/bitcoin_sr@latin.ts \
qt/locale/bitcoin_sv.ts \
@@ -86,15 +72,14 @@ QT_TS = \
qt/locale/bitcoin_te.ts \
qt/locale/bitcoin_th.ts \
qt/locale/bitcoin_tr.ts \
- qt/locale/bitcoin_tr_TR.ts \
qt/locale/bitcoin_uk.ts \
- qt/locale/bitcoin_uk_UA.ts \
qt/locale/bitcoin_ur.ts \
qt/locale/bitcoin_uz@Cyrl.ts \
+ qt/locale/bitcoin_uz@Latn.ts \
qt/locale/bitcoin_vi.ts \
- qt/locale/bitcoin_vi_VN.ts \
qt/locale/bitcoin_yo.ts \
qt/locale/bitcoin_zh-Hans.ts \
+ qt/locale/bitcoin_zh.ts \
qt/locale/bitcoin_zh_CN.ts \
qt/locale/bitcoin_zh_HK.ts \
qt/locale/bitcoin_zh_TW.ts
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 9d782e7a04..1fe4df8059 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -2,11 +2,13 @@
# 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/banentry_deserialize \
test/fuzz/base_encode_decode \
test/fuzz/bech32 \
@@ -14,29 +16,50 @@ FUZZ_TARGETS = \
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/chain \
+ test/fuzz/checkqueue \
test/fuzz/coins_deserialize \
+ 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/locale \
test/fuzz/merkle_block_deserialize \
+ test/fuzz/merkleblock \
test/fuzz/messageheader_deserialize \
+ test/fuzz/multiplication_overflow \
+ 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 \
@@ -44,24 +67,68 @@ FUZZ_TARGETS = \
test/fuzz/parse_univalue \
test/fuzz/partial_merkle_tree_deserialize \
test/fuzz/partially_signed_transaction_deserialize \
+ test/fuzz/policy_estimator \
+ 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_deserialize \
test/fuzz/script_flags \
+ test/fuzz/script_ops \
+ test/fuzz/scriptnum_ops \
test/fuzz/service_deserialize \
+ test/fuzz/signature_checker \
+ 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/txundo_deserialize
+ test/fuzz/txundo_deserialize \
+ test/fuzz/uint160_deserialize \
+ test/fuzz/uint256_deserialize
if ENABLE_FUZZ
noinst_PROGRAMS += $(FUZZ_TARGETS:=)
@@ -92,16 +159,12 @@ BITCOIN_TEST_SUITE = \
test/main.cpp \
$(TEST_UTIL_H)
-FUZZ_SUITE = \
- test/fuzz/fuzz.cpp \
- test/fuzz/fuzz.h \
- test/fuzz/FuzzedDataProvider.h
-
FUZZ_SUITE_LD_COMMON = \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBTEST_UTIL) \
+ $(LIBTEST_FUZZ) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CLI) \
@@ -144,6 +207,7 @@ BITCOIN_TESTS =\
test/fs_tests.cpp \
test/getarg_tests.cpp \
test/hash_tests.cpp \
+ test/interfaces_tests.cpp \
test/key_io_tests.cpp \
test/key_tests.cpp \
test/limitedmap_tests.cpp \
@@ -188,18 +252,11 @@ BITCOIN_TESTS =\
test/uint256_tests.cpp \
test/util_tests.cpp \
test/validation_block_tests.cpp \
+ test/validation_chainstatemanager_tests.cpp \
test/validation_flush_tests.cpp \
+ test/validationinterface_tests.cpp \
test/versionbits_tests.cpp
-if ENABLE_PROPERTY_TESTS
-BITCOIN_TESTS += \
- test/key_properties.cpp
-
-BITCOIN_TEST_SUITE += \
- test/gen/crypto_gen.cpp \
- test/gen/crypto_gen.h
-endif
-
if ENABLE_WALLET
BITCOIN_TESTS += \
wallet/test/db_tests.cpp \
@@ -208,7 +265,8 @@ BITCOIN_TESTS += \
wallet/test/wallet_crypto_tests.cpp \
wallet/test/coinselector_tests.cpp \
wallet/test/init_tests.cpp \
- wallet/test/ismine_tests.cpp
+ wallet/test/ismine_tests.cpp \
+ wallet/test/scriptpubkeyman_tests.cpp
BITCOIN_TEST_SUITE += \
wallet/test/wallet_test_fixture.cpp \
@@ -228,7 +286,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_test_bitcoin_LDADD += $(BDB_LIBS) $(MINIUPNPC_LIBS) $(RAPIDCHECK_LIBS)
+test_test_bitcoin_LDADD += $(BDB_LIBS) $(MINIUPNPC_LIBS)
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
if ENABLE_ZMQ
@@ -237,353 +295,761 @@ endif
if ENABLE_FUZZ
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_addr_info_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_address_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_addrman_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_asmap_SOURCES = test/fuzz/asmap.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_banentry_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_banentry_deserialize_SOURCES = test/fuzz/deserialize.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_base_encode_decode_SOURCES = $(FUZZ_SUITE) test/fuzz/base_encode_decode.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_bech32_SOURCES = $(FUZZ_SUITE) test/fuzz/bech32.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_block_SOURCES = $(FUZZ_SUITE) test/fuzz/block.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_block_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_block_file_info_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_block_filter_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_block_header_and_short_txids_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_blockheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_blocklocator_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_blockmerkleroot_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_blocktransactions_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_blocktransactionsrequest_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_blockundo_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_bloomfilter_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_bloomfilter_deserialize_SOURCES = test/fuzz/deserialize.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_coins_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_coins_deserialize_SOURCES = test/fuzz/deserialize.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_decode_tx_SOURCES = $(FUZZ_SUITE) test/fuzz/decode_tx.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_descriptor_parse_SOURCES = $(FUZZ_SUITE) test/fuzz/descriptor_parse.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_diskblockindex_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_eval_script_SOURCES = $(FUZZ_SUITE) test/fuzz/eval_script.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_fee_rate_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_flat_file_pos_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_hex_SOURCES = $(FUZZ_SUITE) test/fuzz/hex.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_integer_SOURCES = $(FUZZ_SUITE) test/fuzz/integer.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_inv_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_key_origin_info_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_kitchen_sink_SOURCES = test/fuzz/kitchen_sink.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_merkle_block_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_merkleblock_SOURCES = test/fuzz/merkleblock.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_messageheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_multiplication_overflow_SOURCES = test/fuzz/multiplication_overflow.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_netaddr_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_out_point_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_parse_hd_keypath_SOURCES = $(FUZZ_SUITE) test/fuzz/parse_hd_keypath.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_parse_iso8601_SOURCES = $(FUZZ_SUITE) test/fuzz/parse_iso8601.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_parse_numbers_SOURCES = $(FUZZ_SUITE) test/fuzz/parse_numbers.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_parse_script_SOURCES = $(FUZZ_SUITE) test/fuzz/parse_script.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_parse_univalue_SOURCES = $(FUZZ_SUITE) test/fuzz/parse_univalue.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_partial_merkle_tree_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_partially_signed_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_policy_estimator_SOURCES = test/fuzz/policy_estimator.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_prefilled_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_psbt_SOURCES = $(FUZZ_SUITE) test/fuzz/psbt.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_psbt_input_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_psbt_output_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_pub_key_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_script_SOURCES = $(FUZZ_SUITE) test/fuzz/script.cpp
+test_fuzz_script_SOURCES = test/fuzz/script.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_script_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_script_flags_SOURCES = $(FUZZ_SUITE) test/fuzz/script_flags.cpp
+test_fuzz_script_flags_SOURCES = test/fuzz/script_flags.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_ops_SOURCES = test/fuzz/script_ops.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_scriptnum_ops_SOURCES = test/fuzz/scriptnum_ops.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_service_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_signature_checker_SOURCES = test/fuzz/signature_checker.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_spanparsing_SOURCES = $(FUZZ_SUITE) test/fuzz/spanparsing.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_strprintf_SOURCES = $(FUZZ_SUITE) test/fuzz/strprintf.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_sub_net_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_transaction_SOURCES = $(FUZZ_SUITE) test/fuzz/transaction.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_tx_in_SOURCES = $(FUZZ_SUITE) test/fuzz/tx_in.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_tx_in_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_tx_out_SOURCES = $(FUZZ_SUITE) test/fuzz/tx_out.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_txoutcompressor_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_txoutcompressor_deserialize_SOURCES = test/fuzz/deserialize.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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_txundo_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+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 = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_uint256_deserialize_SOURCES = test/fuzz/deserialize.cpp
endif # ENABLE_FUZZ
@@ -632,7 +1098,7 @@ 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) -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`" > $<.log 2>&1 || (cat $<.log && false)
+ $(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)
%.json.h: %.json
@$(MKDIR_P) $(@D)
diff --git a/src/Makefile.test_fuzz.include b/src/Makefile.test_fuzz.include
new file mode 100644
index 0000000000..4e858979fe
--- /dev/null
+++ b/src/Makefile.test_fuzz.include
@@ -0,0 +1,24 @@
+# Copyright (c) 2013-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.
+
+LIBTEST_FUZZ=libtest_fuzz.a
+
+EXTRA_LIBRARIES += \
+ $(LIBTEST_FUZZ)
+
+TEST_FUZZ_H = \
+ test/fuzz/fuzz.h \
+ test/fuzz/FuzzedDataProvider.h \
+ test/fuzz/util.h
+
+libtest_fuzz_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
+libtest_fuzz_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+libtest_fuzz_a_SOURCES = \
+ test/fuzz/fuzz.cpp \
+ $(TEST_FUZZ_H)
+
+LIBTEST_FUZZ += $(LIBBITCOIN_SERVER)
+LIBTEST_FUZZ += $(LIBBITCOIN_COMMON)
+LIBTEST_FUZZ += $(LIBBITCOIN_UTIL)
+LIBTEST_FUZZ += $(LIBBITCOIN_CRYPTO_BASE)
diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include
index 505d630b7d..d7bc73defb 100644
--- a/src/Makefile.test_util.include
+++ b/src/Makefile.test_util.include
@@ -11,6 +11,7 @@ TEST_UTIL_H = \
test/util/blockfilter.h \
test/util/logging.h \
test/util/mining.h \
+ test/util/net.h \
test/util/setup_common.h \
test/util/str.h \
test/util/transaction_utils.h \
@@ -22,6 +23,7 @@ libtest_util_a_SOURCES = \
test/util/blockfilter.cpp \
test/util/logging.cpp \
test/util/mining.cpp \
+ test/util/net.cpp \
test/util/setup_common.cpp \
test/util/str.cpp \
test/util/transaction_utils.cpp \
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 121ae4bf7e..02fb2fd491 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -1,13 +1,13 @@
// Copyright (c) 2012 Pieter Wuille
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <addrman.h>
#include <hash.h>
-#include <serialize.h>
#include <logging.h>
+#include <serialize.h>
int CAddrInfo::GetTriedBucket(const uint256& nKey, const std::vector<bool> &asmap) const
{
@@ -15,7 +15,7 @@ int CAddrInfo::GetTriedBucket(const uint256& nKey, const std::vector<bool> &asma
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup(asmap) << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetCheapHash();
int tried_bucket = hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
uint32_t mapped_as = GetMappedAS(asmap);
- LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to tried bucket %i.\n", ToStringIP(), mapped_as, tried_bucket);
+ LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to tried bucket %i\n", ToStringIP(), mapped_as, tried_bucket);
return tried_bucket;
}
@@ -26,7 +26,7 @@ int CAddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src, const std:
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetCheapHash();
int new_bucket = hash2 % ADDRMAN_NEW_BUCKET_COUNT;
uint32_t mapped_as = GetMappedAS(asmap);
- LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to new bucket %i.\n", ToStringIP(), mapped_as, new_bucket);
+ LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to new bucket %i\n", ToStringIP(), mapped_as, new_bucket);
return new_bucket;
}
@@ -630,12 +630,12 @@ std::vector<bool> CAddrMan::DecodeAsmap(fs::path path)
FILE *filestr = fsbridge::fopen(path, "rb");
CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
if (file.IsNull()) {
- LogPrintf("Failed to open asmap file from disk.\n");
+ LogPrintf("Failed to open asmap file from disk\n");
return bits;
}
fseek(filestr, 0, SEEK_END);
int length = ftell(filestr);
- LogPrintf("Opened asmap file %s (%d bytes) from disk.\n", path, length);
+ LogPrintf("Opened asmap file %s (%d bytes) from disk\n", path, length);
fseek(filestr, 0, SEEK_SET);
char cur_byte;
for (int i = 0; i < length; ++i) {
diff --git a/src/addrman.h b/src/addrman.h
index 5901611bee..8e82020df0 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -6,23 +6,22 @@
#ifndef BITCOIN_ADDRMAN_H
#define BITCOIN_ADDRMAN_H
+#include <clientversion.h>
#include <netaddress.h>
#include <protocol.h>
#include <random.h>
#include <sync.h>
#include <timedata.h>
#include <util/system.h>
-#include <clientversion.h>
+#include <fs.h>
+#include <hash.h>
+#include <iostream>
#include <map>
#include <set>
#include <stdint.h>
-#include <vector>
-#include <iostream>
#include <streams.h>
-#include <fs.h>
-#include <hash.h>
-
+#include <vector>
/**
* Extended statistics about a CAddress
diff --git a/src/banman.h b/src/banman.h
index 8984874914..6bea2e75e9 100644
--- a/src/banman.h
+++ b/src/banman.h
@@ -5,16 +5,19 @@
#ifndef BITCOIN_BANMAN_H
#define BITCOIN_BANMAN_H
-#include <cstdint>
-#include <memory>
-
#include <addrdb.h>
#include <fs.h>
#include <net_types.h> // For banmap_t
#include <sync.h>
+#include <chrono>
+#include <cstdint>
+#include <memory>
+
// NOTE: When adjusting this, update rpcnet:setban's help ("24h")
static constexpr unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; // Default 24-hour ban
+// How often to dump addresses to banlist.dat
+static constexpr std::chrono::minutes DUMP_BANS_INTERVAL{15};
class CClientUIInterface;
class CNetAddr;
diff --git a/src/bench/addrman.cpp b/src/bench/addrman.cpp
new file mode 100644
index 0000000000..cc260df2b8
--- /dev/null
+++ b/src/bench/addrman.cpp
@@ -0,0 +1,140 @@
+// Copyright (c) 2020-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 <addrman.h>
+#include <bench/bench.h>
+#include <random.h>
+#include <util/time.h>
+
+#include <vector>
+
+/* A "source" is a source address from which we have received a bunch of other addresses. */
+
+static constexpr size_t NUM_SOURCES = 64;
+static constexpr size_t NUM_ADDRESSES_PER_SOURCE = 256;
+
+static std::vector<CAddress> g_sources;
+static std::vector<std::vector<CAddress>> g_addresses;
+
+static void CreateAddresses()
+{
+ if (g_sources.size() > 0) { // already created
+ return;
+ }
+
+ FastRandomContext rng(uint256(std::vector<unsigned char>(32, 123)));
+
+ auto randAddr = [&rng]() {
+ in6_addr addr;
+ memcpy(&addr, rng.randbytes(sizeof(addr)).data(), sizeof(addr));
+
+ uint16_t port;
+ memcpy(&port, rng.randbytes(sizeof(port)).data(), sizeof(port));
+ if (port == 0) {
+ port = 1;
+ }
+
+ CAddress ret(CService(addr, port), NODE_NETWORK);
+
+ ret.nTime = GetAdjustedTime();
+
+ return ret;
+ };
+
+ for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
+ g_sources.emplace_back(randAddr());
+ g_addresses.emplace_back();
+ for (size_t addr_i = 0; addr_i < NUM_ADDRESSES_PER_SOURCE; ++addr_i) {
+ g_addresses[source_i].emplace_back(randAddr());
+ }
+ }
+}
+
+static void AddAddressesToAddrMan(CAddrMan& addrman)
+{
+ for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
+ addrman.Add(g_addresses[source_i], g_sources[source_i]);
+ }
+}
+
+static void FillAddrMan(CAddrMan& addrman)
+{
+ CreateAddresses();
+
+ AddAddressesToAddrMan(addrman);
+}
+
+/* Benchmarks */
+
+static void AddrManAdd(benchmark::State& state)
+{
+ CreateAddresses();
+
+ CAddrMan addrman;
+
+ while (state.KeepRunning()) {
+ AddAddressesToAddrMan(addrman);
+ addrman.Clear();
+ }
+}
+
+static void AddrManSelect(benchmark::State& state)
+{
+ CAddrMan addrman;
+
+ FillAddrMan(addrman);
+
+ while (state.KeepRunning()) {
+ const auto& address = addrman.Select();
+ assert(address.GetPort() > 0);
+ }
+}
+
+static void AddrManGetAddr(benchmark::State& state)
+{
+ CAddrMan addrman;
+
+ FillAddrMan(addrman);
+
+ while (state.KeepRunning()) {
+ const auto& addresses = addrman.GetAddr();
+ assert(addresses.size() > 0);
+ }
+}
+
+static void AddrManGood(benchmark::State& state)
+{
+ /* Create many CAddrMan objects - one to be modified at each loop iteration.
+ * This is necessary because the CAddrMan::Good() method modifies the
+ * object, affecting the timing of subsequent calls to the same method and
+ * we want to do the same amount of work in every loop iteration. */
+
+ const uint64_t numLoops = state.m_num_iters * state.m_num_evals;
+
+ std::vector<CAddrMan> addrmans(numLoops);
+ for (auto& addrman : addrmans) {
+ FillAddrMan(addrman);
+ }
+
+ auto markSomeAsGood = [](CAddrMan& addrman) {
+ for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
+ for (size_t addr_i = 0; addr_i < NUM_ADDRESSES_PER_SOURCE; ++addr_i) {
+ if (addr_i % 32 == 0) {
+ addrman.Good(g_addresses[source_i][addr_i]);
+ }
+ }
+ }
+ };
+
+ uint64_t i = 0;
+ while (state.KeepRunning()) {
+ markSomeAsGood(addrmans.at(i));
+ ++i;
+ }
+}
+
+BENCHMARK(AddrManAdd, 5);
+BENCHMARK(AddrManSelect, 1000000);
+BENCHMARK(AddrManGetAddr, 500);
+BENCHMARK(AddrManGood, 2);
diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp
index f2fc3999fe..2107840a3a 100644
--- a/src/bench/bech32.cpp
+++ b/src/bench/bech32.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
@@ -7,8 +7,8 @@
#include <bech32.h>
#include <util/strencodings.h>
-#include <vector>
#include <string>
+#include <vector>
static void Bech32Encode(benchmark::State& state)
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index 5cf7e43f4b..7b93ef688d 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -15,7 +15,6 @@
#include <numeric>
#include <regex>
-const RegTestingSetup* g_testing_setup = nullptr;
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
void benchmark::ConsolePrinter::header()
@@ -115,18 +114,7 @@ void benchmark::BenchRunner::RunAll(Printer& printer, uint64_t num_evals, double
printer.header();
for (const auto& p : benchmarks()) {
- RegTestingSetup test{};
- assert(g_testing_setup == nullptr);
- g_testing_setup = &test;
- {
- LOCK(cs_main);
- assert(::ChainActive().Height() == 0);
- const bool witness_enabled{IsWitnessEnabled(::ChainActive().Tip(), Params().GetConsensus())};
- assert(witness_enabled);
- }
-
if (!std::regex_match(p.first, baseMatch, reFilter)) {
- g_testing_setup = nullptr;
continue;
}
@@ -139,7 +127,6 @@ void benchmark::BenchRunner::RunAll(Printer& printer, uint64_t num_evals, double
p.second.func(state);
}
printer.result(state);
- g_testing_setup = nullptr;
}
printer.footer();
diff --git a/src/bench/bench.h b/src/bench/bench.h
index 6b7a0f76d1..629bca9a73 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -5,18 +5,15 @@
#ifndef BITCOIN_BENCH_BENCH_H
#define BITCOIN_BENCH_BENCH_H
+#include <chrono>
#include <functional>
#include <map>
#include <string>
#include <vector>
-#include <chrono>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
-struct RegTestingSetup;
-extern const RegTestingSetup* g_testing_setup; //!< A pointer to the current testing setup
-
// Simple micro-benchmarking framework; API mostly matches a subset of the Google Benchmark
// framework (see https://github.com/google/benchmark)
// Why not use the Google Benchmark framework? Because adding Yet Another Dependency
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index 9235d5fe6a..1b75854210 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -17,39 +17,40 @@ static const char* DEFAULT_PLOT_PLOTLYURL = "https://cdn.plot.ly/plotly-latest.m
static const int64_t DEFAULT_PLOT_WIDTH = 1024;
static const int64_t DEFAULT_PLOT_HEIGHT = 768;
-static void SetupBenchArgs()
+static void SetupBenchArgs(ArgsManager& argsman)
{
- SetupHelpOptions(gArgs);
+ SetupHelpOptions(argsman);
- gArgs.AddArg("-list", "List benchmarks without executing them. Can be combined with -scaling and -filter", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- gArgs.AddArg("-evals=<n>", strprintf("Number of measurement evaluations to perform. (default: %u)", DEFAULT_BENCH_EVALUATIONS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- gArgs.AddArg("-filter=<regex>", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- gArgs.AddArg("-scaling=<n>", strprintf("Scaling factor for benchmark's runtime (default: %u)", DEFAULT_BENCH_SCALING), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- gArgs.AddArg("-printer=(console|plot)", strprintf("Choose printer format. console: print data to console. plot: Print results as HTML graph (default: %s)", DEFAULT_BENCH_PRINTER), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- gArgs.AddArg("-plot-plotlyurl=<uri>", strprintf("URL to use for plotly.js (default: %s)", DEFAULT_PLOT_PLOTLYURL), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- gArgs.AddArg("-plot-width=<x>", strprintf("Plot width in pixel (default: %u)", DEFAULT_PLOT_WIDTH), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- gArgs.AddArg("-plot-height=<x>", strprintf("Plot height in pixel (default: %u)", DEFAULT_PLOT_HEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-list", "List benchmarks without executing them. Can be combined with -scaling and -filter", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-evals=<n>", strprintf("Number of measurement evaluations to perform. (default: %u)", DEFAULT_BENCH_EVALUATIONS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-filter=<regex>", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-scaling=<n>", strprintf("Scaling factor for benchmark's runtime (default: %u)", DEFAULT_BENCH_SCALING), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-printer=(console|plot)", strprintf("Choose printer format. console: print data to console. plot: Print results as HTML graph (default: %s)", DEFAULT_BENCH_PRINTER), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-plot-plotlyurl=<uri>", strprintf("URL to use for plotly.js (default: %s)", DEFAULT_PLOT_PLOTLYURL), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-plot-width=<x>", strprintf("Plot width in pixel (default: %u)", DEFAULT_PLOT_WIDTH), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-plot-height=<x>", strprintf("Plot height in pixel (default: %u)", DEFAULT_PLOT_HEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
}
int main(int argc, char** argv)
{
- SetupBenchArgs();
+ ArgsManager argsman;
+ SetupBenchArgs(argsman);
std::string error;
- if (!gArgs.ParseParameters(argc, argv, error)) {
+ if (!argsman.ParseParameters(argc, argv, error)) {
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);
return EXIT_FAILURE;
}
- if (HelpRequested(gArgs)) {
- std::cout << gArgs.GetHelpMessage();
+ if (HelpRequested(argsman)) {
+ std::cout << argsman.GetHelpMessage();
return EXIT_SUCCESS;
}
- int64_t evaluations = gArgs.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS);
- std::string regex_filter = gArgs.GetArg("-filter", DEFAULT_BENCH_FILTER);
- std::string scaling_str = gArgs.GetArg("-scaling", DEFAULT_BENCH_SCALING);
- bool is_list_only = gArgs.GetBoolArg("-list", false);
+ int64_t evaluations = argsman.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS);
+ std::string regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER);
+ std::string scaling_str = argsman.GetArg("-scaling", DEFAULT_BENCH_SCALING);
+ bool is_list_only = argsman.GetBoolArg("-list", false);
if (evaluations == 0) {
return EXIT_SUCCESS;
@@ -65,12 +66,12 @@ int main(int argc, char** argv)
}
std::unique_ptr<benchmark::Printer> printer = MakeUnique<benchmark::ConsolePrinter>();
- std::string printer_arg = gArgs.GetArg("-printer", DEFAULT_BENCH_PRINTER);
+ std::string printer_arg = argsman.GetArg("-printer", DEFAULT_BENCH_PRINTER);
if ("plot" == printer_arg) {
printer.reset(new benchmark::PlotlyPrinter(
- gArgs.GetArg("-plot-plotlyurl", DEFAULT_PLOT_PLOTLYURL),
- gArgs.GetArg("-plot-width", DEFAULT_PLOT_WIDTH),
- gArgs.GetArg("-plot-height", DEFAULT_PLOT_HEIGHT)));
+ argsman.GetArg("-plot-plotlyurl", DEFAULT_PLOT_PLOTLYURL),
+ argsman.GetArg("-plot-width", DEFAULT_PLOT_WIDTH),
+ argsman.GetArg("-plot-height", DEFAULT_PLOT_HEIGHT)));
}
benchmark::BenchRunner::RunAll(*printer, evaluations, scaling_factor, regex_filter, is_list_only);
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index a113a73828..268f67cada 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -16,6 +16,14 @@
static void AssembleBlock(benchmark::State& state)
{
+ TestingSetup test_setup{
+ CBaseChainParams::REGTEST,
+ /* extra_args */ {
+ "-nodebuglogfile",
+ "-nodebug",
+ },
+ };
+
const std::vector<unsigned char> op_true{OP_TRUE};
CScriptWitness witness;
witness.stack.push_back(op_true);
@@ -30,7 +38,7 @@ static void AssembleBlock(benchmark::State& state)
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
for (size_t b{0}; b < NUM_BLOCKS; ++b) {
CMutableTransaction tx;
- tx.vin.push_back(MineBlock(g_testing_setup->m_node, SCRIPT_PUB));
+ tx.vin.push_back(MineBlock(test_setup.m_node, SCRIPT_PUB));
tx.vin.back().scriptWitness = witness;
tx.vout.emplace_back(1337, SCRIPT_PUB);
if (NUM_BLOCKS - b >= COINBASE_MATURITY)
@@ -41,13 +49,13 @@ static void AssembleBlock(benchmark::State& state)
for (const auto& txr : txs) {
TxValidationState state;
- bool ret{::AcceptToMemoryPool(::mempool, state, txr, nullptr /* plTxnReplaced */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
+ bool ret{::AcceptToMemoryPool(*test_setup.m_node.mempool, state, txr, nullptr /* plTxnReplaced */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
assert(ret);
}
}
while (state.KeepRunning()) {
- PrepareBlock(g_testing_setup->m_node, SCRIPT_PUB);
+ PrepareBlock(test_setup.m_node, SCRIPT_PUB);
}
}
diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp
index c313029ea8..d658976c3c 100644
--- a/src/bench/ccoins_caching.cpp
+++ b/src/bench/ccoins_caching.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -6,47 +6,10 @@
#include <coins.h>
#include <policy/policy.h>
#include <script/signingprovider.h>
+#include <test/util/transaction_utils.h>
#include <vector>
-// FIXME: Dedup with SetupDummyInputs in test/transaction_tests.cpp.
-//
-// Helper: create two dummy transactions, each with
-// two outputs. The first has 11 and 50 COIN outputs
-// paid to a TX_PUBKEY, the second 21 and 22 COIN outputs
-// paid to a TX_PUBKEYHASH.
-//
-static std::vector<CMutableTransaction>
-SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet)
-{
- std::vector<CMutableTransaction> dummyTransactions;
- dummyTransactions.resize(2);
-
- // Add some keys to the keystore:
- CKey key[4];
- for (int i = 0; i < 4; i++) {
- key[i].MakeNewKey(i % 2);
- keystoreRet.AddKey(key[i]);
- }
-
- // Create some dummy input transactions
- dummyTransactions[0].vout.resize(2);
- dummyTransactions[0].vout[0].nValue = 11 * COIN;
- dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
- dummyTransactions[0].vout[1].nValue = 50 * COIN;
- dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
- AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0);
-
- dummyTransactions[1].vout.resize(2);
- dummyTransactions[1].vout[0].nValue = 21 * COIN;
- dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey()));
- dummyTransactions[1].vout[1].nValue = 22 * COIN;
- dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey()));
- AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0);
-
- return dummyTransactions;
-}
-
// Microbenchmark for simple accesses to a CCoinsViewCache database. Note from
// laanwj, "replicating the actual usage patterns of the client is hard though,
// many times micro-benchmarks of the database showed completely different
@@ -55,10 +18,14 @@ SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
static void CCoinsCaching(benchmark::State& state)
{
+ const ECCVerifyHandle verify_handle;
+ ECC_Start();
+
FillableSigningProvider keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
- std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+ std::vector<CMutableTransaction> dummyTransactions =
+ SetupDummyInputs(keystore, coins, {11 * COIN, 50 * COIN, 21 * COIN, 22 * COIN});
CMutableTransaction t1;
t1.vin.resize(3);
@@ -83,6 +50,7 @@ static void CCoinsCaching(benchmark::State& state)
CAmount value = coins.GetValueIn(tx_1);
assert(value == (50 + 21 + 22) * COIN);
}
+ ECC_Stop();
}
BENCHMARK(CCoinsCaching, 170 * 1000);
diff --git a/src/bench/chacha_poly_aead.cpp b/src/bench/chacha_poly_aead.cpp
index a02a5315a4..df10f27d03 100644
--- a/src/bench/chacha_poly_aead.cpp
+++ b/src/bench/chacha_poly_aead.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -8,8 +8,8 @@
#include <crypto/poly1305.h> // for the POLY1305_TAGLEN constant
#include <hash.h>
-#include <limits>
#include <assert.h>
+#include <limits>
/* Number of bytes to process per iteration */
static constexpr uint64_t BUFFER_SIZE_TINY = 64;
diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp
index 55786126b3..2b2c78905e 100644
--- a/src/bench/checkblock.cpp
+++ b/src/bench/checkblock.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -6,9 +6,9 @@
#include <bench/data.h>
#include <chainparams.h>
-#include <validation.h>
-#include <streams.h>
#include <consensus/validation.h>
+#include <streams.h>
+#include <validation.h>
// These are the two major time-sinks which happen after we have fully received
// a block off the wire, but before we can relay the block on to peers using
diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp
index f5f96a0136..e052681181 100644
--- a/src/bench/checkqueue.cpp
+++ b/src/bench/checkqueue.cpp
@@ -1,14 +1,18 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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 <bench/bench.h>
-#include <util/system.h>
#include <checkqueue.h>
+#include <key.h>
#include <prevector.h>
-#include <vector>
-#include <boost/thread/thread.hpp>
+#include <pubkey.h>
#include <random.h>
+#include <util/system.h>
+
+#include <boost/thread/thread.hpp>
+
+#include <vector>
static const int MIN_CORES = 2;
@@ -22,6 +26,9 @@ static const unsigned int QUEUE_BATCH_SIZE = 128;
// and there is a little bit of work done between calls to Add.
static void CCheckQueueSpeedPrevectorJob(benchmark::State& state)
{
+ const ECCVerifyHandle verify_handle;
+ ECC_Start();
+
struct PrevectorJob {
prevector<PREVECTOR_SIZE, uint8_t> p;
PrevectorJob(){
@@ -57,5 +64,6 @@ static void CCheckQueueSpeedPrevectorJob(benchmark::State& state)
}
tg.interrupt_all();
tg.join_all();
+ ECC_Stop();
}
BENCHMARK(CCheckQueueSpeedPrevectorJob, 1400);
diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
index a9d4d78888..ddcef5121e 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.cpp
@@ -1,17 +1,17 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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 <bench/bench.h>
-#include <hash.h>
-#include <random.h>
-#include <uint256.h>
#include <crypto/ripemd160.h>
#include <crypto/sha1.h>
#include <crypto/sha256.h>
#include <crypto/sha512.h>
#include <crypto/siphash.h>
+#include <hash.h>
+#include <random.h>
+#include <uint256.h>
/* Number of bytes to hash per iteration */
static const uint64_t BUFFER_SIZE = 1000*1000;
diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp
index a783370b4e..e87f15042b 100644
--- a/src/bench/duplicate_inputs.cpp
+++ b/src/bench/duplicate_inputs.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -7,13 +7,21 @@
#include <consensus/merkle.h>
#include <consensus/validation.h>
#include <pow.h>
+#include <test/util/setup_common.h>
#include <txmempool.h>
#include <validation.h>
-
static void DuplicateInputs(benchmark::State& state)
{
+ TestingSetup test_setup{
+ CBaseChainParams::REGTEST,
+ /* extra_args */ {
+ "-nodebuglogfile",
+ "-nodebug",
+ },
+ };
+
const CScript SCRIPT_PUB{CScript(OP_TRUE)};
const CChainParams& chainparams = Params();
diff --git a/src/bench/examples.cpp b/src/bench/examples.cpp
index 60a4fbf0ba..f88150200a 100644
--- a/src/bench/examples.cpp
+++ b/src/bench/examples.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -10,7 +10,7 @@
static void Sleep100ms(benchmark::State& state)
{
while (state.KeepRunning()) {
- MilliSleep(100);
+ UninterruptibleSleep(std::chrono::milliseconds{100});
}
}
diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp
index 1c9c106666..69483f2914 100644
--- a/src/bench/mempool_eviction.cpp
+++ b/src/bench/mempool_eviction.cpp
@@ -4,6 +4,7 @@
#include <bench/bench.h>
#include <policy/policy.h>
+#include <test/util/setup_common.h>
#include <txmempool.h>
@@ -15,8 +16,8 @@ static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& po
unsigned int sigOpCost = 4;
LockPoints lp;
pool.addUnchecked(CTxMemPoolEntry(
- tx, nFee, nTime, nHeight,
- spendsCoinbase, sigOpCost, lp));
+ tx, nFee, nTime, nHeight,
+ spendsCoinbase, sigOpCost, lp));
}
// Right now this is only testing eviction performance in an extremely small
@@ -24,6 +25,14 @@ static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& po
// unique transactions for a more meaningful performance measurement.
static void MempoolEviction(benchmark::State& state)
{
+ TestingSetup test_setup{
+ CBaseChainParams::REGTEST,
+ /* extra_args */ {
+ "-nodebuglogfile",
+ "-nodebug",
+ },
+ };
+
CMutableTransaction tx1 = CMutableTransaction();
tx1.vin.resize(1);
tx1.vin[0].scriptSig = CScript() << OP_1;
diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp
index 389e2c096f..38d8632318 100644
--- a/src/bench/mempool_stress.cpp
+++ b/src/bench/mempool_stress.cpp
@@ -4,6 +4,7 @@
#include <bench/bench.h>
#include <policy/policy.h>
+#include <test/util/setup_common.h>
#include <txmempool.h>
#include <vector>
@@ -73,6 +74,7 @@ static void ComplexMemPool(benchmark::State& state)
ordered_coins.emplace_back(MakeTransactionRef(tx));
available_coins.emplace_back(ordered_coins.back(), tx_counter++);
}
+ TestingSetup test_setup;
CTxMemPool pool;
LOCK2(cs_main, pool.cs);
while (state.KeepRunning()) {
diff --git a/src/bench/merkle_root.cpp b/src/bench/merkle_root.cpp
index bdb2bdbe3d..e84f92feae 100644
--- a/src/bench/merkle_root.cpp
+++ b/src/bench/merkle_root.cpp
@@ -1,12 +1,12 @@
-// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Copyright (c) 2016-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 <bench/bench.h>
-#include <uint256.h>
-#include <random.h>
#include <consensus/merkle.h>
+#include <random.h>
+#include <uint256.h>
static void MerkleRoot(benchmark::State& state)
{
diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp
index 2fc6f116a4..511573abac 100644
--- a/src/bench/rpc_blockchain.cpp
+++ b/src/bench/rpc_blockchain.cpp
@@ -1,13 +1,13 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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 <bench/bench.h>
#include <bench/data.h>
-#include <validation.h>
-#include <streams.h>
#include <rpc/blockchain.h>
+#include <streams.h>
+#include <validation.h>
#include <univalue.h>
diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp
index 31e166cc27..14bca5f7d1 100644
--- a/src/bench/verify_script.cpp
+++ b/src/bench/verify_script.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -18,6 +18,9 @@
// modified to measure performance of other types of scripts.
static void VerifyScriptBench(benchmark::State& state)
{
+ const ECCVerifyHandle verify_handle;
+ ECC_Start();
+
const int flags = SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH;
const int witnessversion = 0;
@@ -69,6 +72,30 @@ static void VerifyScriptBench(benchmark::State& state)
assert(csuccess == 1);
#endif
}
+ ECC_Stop();
+}
+
+static void VerifyNestedIfScript(benchmark::State& state) {
+ std::vector<std::vector<unsigned char>> stack;
+ CScript script;
+ for (int i = 0; i < 100; ++i) {
+ script << OP_1 << OP_IF;
+ }
+ for (int i = 0; i < 1000; ++i) {
+ script << OP_1;
+ }
+ for (int i = 0; i < 100; ++i) {
+ script << OP_ENDIF;
+ }
+ while (state.KeepRunning()) {
+ auto stack_copy = stack;
+ ScriptError error;
+ bool ret = EvalScript(stack_copy, script, 0, BaseSignatureChecker(), SigVersion::BASE, &error);
+ assert(ret);
+ }
}
+
BENCHMARK(VerifyScriptBench, 6300);
+
+BENCHMARK(VerifyNestedIfScript, 100);
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
index 62568a9da5..810c344ab5 100644
--- a/src/bench/wallet_balance.cpp
+++ b/src/bench/wallet_balance.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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.
@@ -14,6 +14,14 @@
static void WalletBalance(benchmark::State& state, const bool set_dirty, const bool add_watchonly, const bool add_mine)
{
+ TestingSetup test_setup{
+ CBaseChainParams::REGTEST,
+ /* extra_args */ {
+ "-nodebuglogfile",
+ "-nodebug",
+ },
+ };
+
const auto& ADDRESS_WATCHONLY = ADDRESS_BCRT1_UNSPENDABLE;
NodeContext node;
@@ -23,16 +31,15 @@ static void WalletBalance(benchmark::State& state, const bool set_dirty, const b
wallet.SetupLegacyScriptPubKeyMan();
bool first_run;
if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false);
- wallet.handleNotifications();
}
-
+ auto handler = 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);
for (int i = 0; i < 100; ++i) {
- generatetoaddress(g_testing_setup->m_node, address_mine.get_value_or(ADDRESS_WATCHONLY));
- generatetoaddress(g_testing_setup->m_node, ADDRESS_WATCHONLY);
+ generatetoaddress(test_setup.m_node, address_mine.get_value_or(ADDRESS_WATCHONLY));
+ generatetoaddress(test_setup.m_node, ADDRESS_WATCHONLY);
}
SyncWithValidationInterfaceQueue();
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index c085095a2b..cdaabd6fab 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -15,6 +15,7 @@
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
+#include <util/url.h>
#include <functional>
#include <memory>
@@ -29,6 +30,7 @@
#include <compat/stdin.h>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
+UrlDecodeFn* const URL_DECODE = urlDecode;
static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
@@ -228,6 +230,7 @@ public:
const int ID_NETWORKINFO = 0;
const int ID_BLOCKCHAININFO = 1;
const int ID_WALLETINFO = 2;
+ const int ID_BALANCES = 3;
/** Create a simulated `getinfo` request. */
UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
@@ -239,6 +242,7 @@ public:
result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
result.push_back(JSONRPCRequestObj("getblockchaininfo", NullUniValue, ID_BLOCKCHAININFO));
result.push_back(JSONRPCRequestObj("getwalletinfo", NullUniValue, ID_WALLETINFO));
+ result.push_back(JSONRPCRequestObj("getbalances", NullUniValue, ID_BALANCES));
return result;
}
@@ -246,9 +250,9 @@ public:
UniValue ProcessReply(const UniValue &batch_in) override
{
UniValue result(UniValue::VOBJ);
- std::vector<UniValue> batch = JSONRPCProcessBatchReply(batch_in, 3);
- // Errors in getnetworkinfo() and getblockchaininfo() are fatal, pass them on
- // getwalletinfo() is allowed to fail in case there is no wallet.
+ std::vector<UniValue> batch = JSONRPCProcessBatchReply(batch_in, batch_in.size());
+ // Errors in getnetworkinfo() and getblockchaininfo() are fatal, pass them on;
+ // getwalletinfo() and getbalances() are allowed to fail if there is no wallet.
if (!batch[ID_NETWORKINFO]["error"].isNull()) {
return batch[ID_NETWORKINFO];
}
@@ -265,13 +269,15 @@ public:
result.pushKV("difficulty", batch[ID_BLOCKCHAININFO]["result"]["difficulty"]);
result.pushKV("chain", UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"]));
if (!batch[ID_WALLETINFO]["result"].isNull()) {
- result.pushKV("balance", batch[ID_WALLETINFO]["result"]["balance"]);
result.pushKV("keypoolsize", batch[ID_WALLETINFO]["result"]["keypoolsize"]);
if (!batch[ID_WALLETINFO]["result"]["unlocked_until"].isNull()) {
result.pushKV("unlocked_until", batch[ID_WALLETINFO]["result"]["unlocked_until"]);
}
result.pushKV("paytxfee", batch[ID_WALLETINFO]["result"]["paytxfee"]);
}
+ if (!batch[ID_BALANCES]["result"].isNull()) {
+ result.pushKV("balance", batch[ID_BALANCES]["result"]["mine"]["trusted"]);
+ }
result.pushKV("relayfee", batch[ID_NETWORKINFO]["result"]["relayfee"]);
result.pushKV("warnings", batch[ID_NETWORKINFO]["result"]["warnings"]);
return JSONRPCReplyObj(result, NullUniValue, 1);
@@ -524,7 +530,7 @@ static int CommandLineRPC(int argc, char *argv[])
}
catch (const CConnectionFailed&) {
if (fWait)
- MilliSleep(1000);
+ UninterruptibleSleep(std::chrono::milliseconds{1000});
else
throw;
}
@@ -545,11 +551,19 @@ static int CommandLineRPC(int argc, char *argv[])
return nRet;
}
-int main(int argc, char* argv[])
-{
#ifdef WIN32
+// Export main() and ensure working ASLR on Windows.
+// Exporting a symbol will prevent the linker from stripping
+// the .reloc section from the binary, which is a requirement
+// for ASLR. This is a temporary workaround until a fixed
+// version of binutils is used for releases.
+__declspec(dllexport) int main(int argc, char* argv[])
+{
util::WinCmdLineArgs winArgs;
std::tie(argc, argv) = winArgs.get();
+#else
+int main(int argc, char* argv[])
+{
#endif
SetupEnvironment();
if (!SetupNetworking()) {
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 735f55fba7..f54a299a36 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -20,6 +20,7 @@
#include <util/moneystr.h>
#include <util/rbf.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <util/system.h>
#include <util/translation.h>
@@ -357,7 +358,7 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
if (required < 1 || required > MAX_PUBKEYS_PER_MULTISIG || numkeys < 1 || numkeys > MAX_PUBKEYS_PER_MULTISIG || numkeys < required)
throw std::runtime_error("multisig parameter mismatch. Required " \
- + std::to_string(required) + " of " + std::to_string(numkeys) + "signatures.");
+ + ToString(required) + " of " + ToString(numkeys) + "signatures.");
// extract and validate PUBKEYs
std::vector<CPubKey> pubkeys;
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index 7f1a4a114b..7f9439788a 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -11,11 +11,13 @@
#include <logging.h>
#include <util/system.h>
#include <util/translation.h>
+#include <util/url.h>
#include <wallet/wallettool.h>
#include <functional>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
+UrlDecodeFn* const URL_DECODE = nullptr;
static void SetupWalletToolArgs()
{
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 4b5cea4849..2aa416ca44 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -20,16 +20,18 @@
#include <util/system.h>
#include <util/threadnames.h>
#include <util/translation.h>
+#include <util/url.h>
#include <functional>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
+UrlDecodeFn* const URL_DECODE = urlDecode;
static void WaitForShutdown(NodeContext& node)
{
while (!ShutdownRequested())
{
- MilliSleep(200);
+ UninterruptibleSleep(std::chrono::milliseconds{200});
}
Interrupt(node);
}
@@ -51,7 +53,7 @@ static bool AppInit(int argc, char* argv[])
// Parameters
//
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
- SetupServerArgs();
+ SetupServerArgs(node);
std::string error;
if (!gArgs.ParseParameters(argc, argv, error)) {
return InitError(strprintf("Error parsing command line arguments: %s\n", error));
diff --git a/src/blockencodings.h b/src/blockencodings.h
index 55ed8989bb..377ac3a1a6 100644
--- a/src/blockencodings.h
+++ b/src/blockencodings.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -10,18 +10,29 @@
class CTxMemPool;
-// Dumb helper to handle CTransaction compression at serialize-time
-struct TransactionCompressor {
-private:
- CTransactionRef& tx;
-public:
- explicit TransactionCompressor(CTransactionRef& txIn) : tx(txIn) {}
+// Transaction compression schemes for compact block relay can be introduced by writing
+// an actual formatter here.
+using TransactionCompression = DefaultFormatter;
- ADD_SERIALIZE_METHODS;
+class DifferenceFormatter
+{
+ uint64_t m_shift = 0;
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(tx); //TODO: Compress tx encoding
+public:
+ template<typename Stream, typename I>
+ void Ser(Stream& s, I v)
+ {
+ if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) throw std::ios_base::failure("differential value overflow");
+ WriteCompactSize(s, v - m_shift);
+ m_shift = uint64_t(v) + 1;
+ }
+ template<typename Stream, typename I>
+ void Unser(Stream& s, I& v)
+ {
+ uint64_t n = ReadCompactSize(s);
+ m_shift += n;
+ if (m_shift < n || m_shift >= std::numeric_limits<uint64_t>::max() || m_shift < std::numeric_limits<I>::min() || m_shift > std::numeric_limits<I>::max()) throw std::ios_base::failure("differential value overflow");
+ v = I(m_shift++);
}
};
@@ -31,39 +42,9 @@ public:
uint256 blockhash;
std::vector<uint16_t> indexes;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(blockhash);
- uint64_t indexes_size = (uint64_t)indexes.size();
- READWRITE(COMPACTSIZE(indexes_size));
- if (ser_action.ForRead()) {
- size_t i = 0;
- while (indexes.size() < indexes_size) {
- indexes.resize(std::min((uint64_t)(1000 + indexes.size()), indexes_size));
- for (; i < indexes.size(); i++) {
- uint64_t index = 0;
- READWRITE(COMPACTSIZE(index));
- if (index > std::numeric_limits<uint16_t>::max())
- throw std::ios_base::failure("index overflowed 16 bits");
- indexes[i] = index;
- }
- }
-
- int32_t offset = 0;
- for (size_t j = 0; j < indexes.size(); j++) {
- if (int32_t(indexes[j]) + offset > std::numeric_limits<uint16_t>::max())
- throw std::ios_base::failure("indexes overflowed 16 bits");
- indexes[j] = indexes[j] + offset;
- offset = int32_t(indexes[j]) + 1;
- }
- } else {
- for (size_t i = 0; i < indexes.size(); i++) {
- uint64_t index = indexes[i] - (i == 0 ? 0 : (indexes[i - 1] + 1));
- READWRITE(COMPACTSIZE(index));
- }
- }
+ SERIALIZE_METHODS(BlockTransactionsRequest, obj)
+ {
+ READWRITE(obj.blockhash, Using<VectorFormatter<DifferenceFormatter>>(obj.indexes));
}
};
@@ -77,24 +58,9 @@ public:
explicit BlockTransactions(const BlockTransactionsRequest& req) :
blockhash(req.blockhash), txn(req.indexes.size()) {}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(blockhash);
- uint64_t txn_size = (uint64_t)txn.size();
- READWRITE(COMPACTSIZE(txn_size));
- if (ser_action.ForRead()) {
- size_t i = 0;
- while (txn.size() < txn_size) {
- txn.resize(std::min((uint64_t)(1000 + txn.size()), txn_size));
- for (; i < txn.size(); i++)
- READWRITE(TransactionCompressor(txn[i]));
- }
- } else {
- for (size_t i = 0; i < txn.size(); i++)
- READWRITE(TransactionCompressor(txn[i]));
- }
+ SERIALIZE_METHODS(BlockTransactions, obj)
+ {
+ READWRITE(obj.blockhash, Using<VectorFormatter<TransactionCompression>>(obj.txn));
}
};
@@ -105,17 +71,7 @@ struct PrefilledTransaction {
uint16_t index;
CTransactionRef tx;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- uint64_t idx = index;
- READWRITE(COMPACTSIZE(idx));
- if (idx > std::numeric_limits<uint16_t>::max())
- throw std::ios_base::failure("index overflowed 16-bits");
- index = idx;
- READWRITE(TransactionCompressor(tx));
- }
+ SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), Using<TransactionCompression>(obj.tx)); }
};
typedef enum ReadStatus_t
@@ -153,43 +109,15 @@ public:
size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(header);
- READWRITE(nonce);
-
- uint64_t shorttxids_size = (uint64_t)shorttxids.size();
- READWRITE(COMPACTSIZE(shorttxids_size));
+ SERIALIZE_METHODS(CBlockHeaderAndShortTxIDs, obj)
+ {
+ READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn);
if (ser_action.ForRead()) {
- size_t i = 0;
- while (shorttxids.size() < shorttxids_size) {
- shorttxids.resize(std::min((uint64_t)(1000 + shorttxids.size()), shorttxids_size));
- for (; i < shorttxids.size(); i++) {
- uint32_t lsb = 0; uint16_t msb = 0;
- READWRITE(lsb);
- READWRITE(msb);
- shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
- static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids serialization assumes 6-byte shorttxids");
- }
- }
- } else {
- for (size_t i = 0; i < shorttxids.size(); i++) {
- uint32_t lsb = shorttxids[i] & 0xffffffff;
- uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
- READWRITE(lsb);
- READWRITE(msb);
+ if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) {
+ throw std::ios_base::failure("indexes overflowed 16 bits");
}
+ obj.FillShortTxIDSelector();
}
-
- READWRITE(prefilledtxn);
-
- if (BlockTxCount() > std::numeric_limits<uint16_t>::max())
- throw std::ios_base::failure("indexes overflowed 16 bits");
-
- if (ser_action.ForRead())
- FillShortTxIDSelector();
}
};
diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp
index 7aff3be6e7..5f5bed5bda 100644
--- a/src/blockfilter.cpp
+++ b/src/blockfilter.cpp
@@ -12,6 +12,7 @@
#include <primitives/transaction.h>
#include <script/script.h>
#include <streams.h>
+#include <util/golombrice.h>
/// SerType used to serialize parameters in GCS filter encoding.
static constexpr int GCS_SER_TYPE = SER_NETWORK;
@@ -23,37 +24,6 @@ static const std::map<BlockFilterType, std::string> g_filter_types = {
{BlockFilterType::BASIC, "basic"},
};
-template <typename OStream>
-static void GolombRiceEncode(BitStreamWriter<OStream>& bitwriter, uint8_t P, uint64_t x)
-{
- // Write quotient as unary-encoded: q 1's followed by one 0.
- uint64_t q = x >> P;
- while (q > 0) {
- int nbits = q <= 64 ? static_cast<int>(q) : 64;
- bitwriter.Write(~0ULL, nbits);
- q -= nbits;
- }
- bitwriter.Write(0, 1);
-
- // Write the remainder in P bits. Since the remainder is just the bottom
- // P bits of x, there is no need to mask first.
- bitwriter.Write(x, P);
-}
-
-template <typename IStream>
-static uint64_t GolombRiceDecode(BitStreamReader<IStream>& bitreader, uint8_t P)
-{
- // Read unary-encoded quotient: q 1's followed by one 0.
- uint64_t q = 0;
- while (bitreader.Read(1) == 1) {
- ++q;
- }
-
- uint64_t r = bitreader.Read(P);
-
- return (q << P) + r;
-}
-
// Map a value x that is uniformly distributed in the range [0, 2^64) to a
// value uniformly distributed in [0, n) by returning the upper 64 bits of
// x * n.
diff --git a/src/bloom.cpp b/src/bloom.cpp
index bd6069b31f..30af507243 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -102,19 +102,6 @@ bool CBloomFilter::contains(const uint256& hash) const
return contains(data);
}
-void CBloomFilter::clear()
-{
- vData.assign(vData.size(),0);
- isFull = false;
- isEmpty = true;
-}
-
-void CBloomFilter::reset(const unsigned int nNewTweak)
-{
- clear();
- nTweak = nNewTweak;
-}
-
bool CBloomFilter::IsWithinSizeConstraints() const
{
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
diff --git a/src/bloom.h b/src/bloom.h
index 68e76a0258..8e3b7be54d 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -84,9 +84,6 @@ public:
bool contains(const COutPoint& outpoint) const;
bool contains(const uint256& hash) const;
- void clear();
- void reset(const unsigned int nNewTweak);
-
//! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS
//! (catch a filter which was just deserialized which was too big)
bool IsWithinSizeConstraints() const;
diff --git a/src/chain.h b/src/chain.h
index 48bcb8bfdd..802e23f775 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -333,12 +333,12 @@ public:
SERIALIZE_METHODS(CDiskBlockIndex, obj)
{
int _nVersion = s.GetVersion();
- if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
+ if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
- READWRITE(VARINT(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
+ READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
READWRITE(VARINT(obj.nStatus));
READWRITE(VARINT(obj.nTx));
- if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
+ if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos));
if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos));
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 31592b0f0a..799474fae2 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -84,10 +84,10 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
// The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000008ea3cf107ae0dec57f03fe8");
+ consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000e1ab5ec9348e9f4b8eb8154");
// By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x00000000000000000005f8920febd3925f8272a6a71237563d78c2edfdd09ddf"); // 597379
+ consensus.defaultAssumeValid = uint256S("0x0000000000000000000f2adce67e49b0b6bdeb9de8b7c3d7e93b21e7fc1e819d"); // 623950
/**
* The message start string is designed to be unlikely to occur in normal data.
@@ -100,7 +100,7 @@ public:
pchMessageStart[3] = 0xd9;
nDefaultPort = 8333;
nPruneAfterHeight = 100000;
- m_assumed_blockchain_size = 280;
+ m_assumed_blockchain_size = 320;
m_assumed_chain_state_size = 4;
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
@@ -135,6 +135,7 @@ public:
fDefaultConsistencyChecks = false;
fRequireStandard = true;
m_is_test_chain = false;
+ m_is_mockable_chain = false;
checkpointData = {
{
@@ -155,10 +156,10 @@ public:
};
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 00000000000000000005f8920febd3925f8272a6a71237563d78c2edfdd09ddf
- /* nTime */ 1569926786,
- /* nTxCount */ 460596047,
- /* dTxRate */ 3.77848885073875,
+ // Data from RPC: getchaintxstats 4096 0000000000000000000f2adce67e49b0b6bdeb9de8b7c3d7e93b21e7fc1e819d
+ /* nTime */ 1585764811,
+ /* nTxCount */ 517186863,
+ /* dTxRate */ 3.305709665792344,
};
}
};
@@ -191,10 +192,10 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
// The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000012b2a3a62424f21c918");
+ consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000001495c1d5a01e2af8a23");
// By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x00000000000000b7ab6ce61eb6d571003fbe5fe892da4c9b740c49a07542462d"); // 1580000
+ consensus.defaultAssumeValid = uint256S("0x000000000000056c49030c174179b52a928c870e6e8a822c75973b7970cfbd01"); // 1692000
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
@@ -202,7 +203,7 @@ public:
pchMessageStart[3] = 0x07;
nDefaultPort = 18333;
nPruneAfterHeight = 1000;
- m_assumed_blockchain_size = 30;
+ m_assumed_blockchain_size = 40;
m_assumed_chain_state_size = 2;
genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN);
@@ -231,7 +232,7 @@ public:
fDefaultConsistencyChecks = false;
fRequireStandard = false;
m_is_test_chain = true;
-
+ m_is_mockable_chain = false;
checkpointData = {
{
@@ -240,10 +241,10 @@ public:
};
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 00000000000000b7ab6ce61eb6d571003fbe5fe892da4c9b740c49a07542462d
- /* nTime */ 1569741320,
- /* nTxCount */ 52318009,
- /* dTxRate */ 0.1517002392872353,
+ // Data from RPC: getchaintxstats 4096 000000000000056c49030c174179b52a928c870e6e8a822c75973b7970cfbd01
+ /* nTime */ 1585561140,
+ /* nTxCount */ 13483,
+ /* dTxRate */ 0.08523187013249722,
};
}
};
@@ -303,6 +304,7 @@ public:
fDefaultConsistencyChecks = true;
fRequireStandard = true;
m_is_test_chain = true;
+ m_is_mockable_chain = true;
checkpointData = {
{
diff --git a/src/chainparams.h b/src/chainparams.h
index 63398e587e..542ef329da 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -68,6 +68,8 @@ public:
bool RequireStandard() const { return fRequireStandard; }
/** If this chain is exclusively used for testing */
bool IsTestChain() const { return m_is_test_chain; }
+ /** If this chain allows time to be mocked */
+ bool IsMockableChain() const { return m_is_mockable_chain; }
uint64_t PruneAfterHeight() const { return nPruneAfterHeight; }
/** Minimum free space (in GB) needed for data directory */
uint64_t AssumedBlockchainSize() const { return m_assumed_blockchain_size; }
@@ -102,6 +104,7 @@ protected:
bool fDefaultConsistencyChecks;
bool fRequireStandard;
bool m_is_test_chain;
+ bool m_is_mockable_chain;
CCheckpointData checkpointData;
ChainTxData chainTxData;
};
diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h
index 3adac373c6..2aca18c188 100644
--- a/src/chainparamsseeds.h
+++ b/src/chainparamsseeds.h
@@ -8,648 +8,682 @@
* IPv4 as well as onion addresses are wrapped inside an IPv6 address accordingly.
*/
static SeedSpec6 pnSeed6_main[] = {
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x18,0x8d,0x49}, 8333},
+ {{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,0x2b,0xe4,0x63}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x91,0x0a,0x7a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xa6,0x23,0x2f}, 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,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,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,0xce,0xe2,0xd8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xce,0xe2,0xe7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0d,0x5c,0xfe,0xe2}, 8335},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0d,0x7d,0xbc,0x80}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x12,0xe4,0x90,0x14}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xaf,0x00,0xc8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe2,0x5a,0xac}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe9,0x6b,0x1c}, 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,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,0xaf,0x00,0xd4}, 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,0x79,0x10,0x23}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x96,0x5e,0x4f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xbc,0xc8,0xaa}, 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,0x1b,0x66,0x66,0x9d}, 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,0x14,0xe2,0x73}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x15,0xb6,0x4f}, 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,0x1f,0x84,0x87,0x86}, 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,0x20,0xd6,0xb7,0x72}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x22,0xe7,0xea,0x96}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xd1,0x72,0x9f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xd5,0x12,0xbe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x61,0xe4,0xe0}, 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,0x7b,0x84,0x21}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x85,0x8c,0xa9}, 8334},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x86,0xa5,0xcd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbf,0xfd,0x7d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x27,0x6c,0x44,0xed}, 7781},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x28,0x4e,0x13,0x95}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2a,0x3c,0xd9,0xb7}, 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,0x2d,0x3a,0x7e,0x8a}, 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,0x2e,0x1c,0x84,0x22}, 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,0xa6,0xa2,0x2d}, 20001},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xb0,0x89}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe3,0x44,0x68}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe3,0x44,0x69}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x4a,0x20,0xbe}, 8885},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x59,0x13,0x86}, 30303},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x61,0x75,0xfa}, 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,0x05,0xa3,0x8b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x22,0x41,0xd9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x42,0xd1,0x36}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x43,0xb3,0x24}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0x0f,0xa6,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0x0f,0xef,0xa4}, 8333},
+ {{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,0xe5,0xee,0xbb}, 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,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,0x33,0x9a,0x3c,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0x9a,0x88,0x3c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0x74,0x9f,0xf7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xa7,0xe8,0x25}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0x16,0x7b,0x78}, 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,0x3a,0x9e,0x00,0x56}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2d,0x9f,0x42}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x4b,0xbf,0xa6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x4b,0xd2,0x51}, 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,0x6b,0xc8,0x1e}, 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,0x3e,0xd5,0xd6,0xcf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x62,0x12,0x15}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x4f,0x91,0xd1}, 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,0x33}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xf8,0xce,0x56}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x28,0xcf,0xa9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x95,0xfc,0x4f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xc1,0xbd,0x2a}, 8333},
+ {{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,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,0xdc,0x16,0x4e}, 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,0xa8,0x7a,0x02}, 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,0x46,0xaa,0xb2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x84,0x96,0x2b}, 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,0x46,0x1a,0x95,0x68}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x33,0x8e,0x2b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x3f,0xaa,0x56}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x39,0x49,0xad}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xed,0xff,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x18,0xeb,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x5f,0x68,0x5e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xe7,0xbb,0x19}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xfd,0xef,0xf6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x4e,0x8c,0xb2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x53,0xea,0x61}, 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,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,0xc5,0xec,0x3a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xd0,0x5e,0xac}, 8333},
+ {{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,0x4a,0x76,0x89,0x77}, 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,0x65,0x60,0x06}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x9d,0x4d,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x5d,0xb7,0xd1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xae,0x81,0xcb}, 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,0x55,0xcc,0x95}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x78,0x77,0x1b}, 8433},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x86,0xac,0x51}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x2a,0x0c,0xc9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x3a,0x8c,0x66}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x6c,0x6c,0xa2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x77,0xb4,0x3e}, 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,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,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,0x82,0x94,0xda}, 8885},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x82,0xa1,0x4c}, 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,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,0x4f,0x4d,0x21,0x80}, 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,0x4f,0xaf,0x9a,0xe4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x4f,0x72,0x22}, 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,0x50,0x59,0xcb,0xac}, 8001},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x64,0x80,0x80}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x7a,0x2b,0x4e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x97,0x7c,0x7f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xa7,0x4f,0xae}, 8333},
+ {{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,0xe5,0x97,0xbb}, 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,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,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,0x04,0x66,0x5b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x06,0x22,0x9a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x10,0xb6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x11,0xca}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x19,0x47,0x44}, 8444},
+ {{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,0x52,0x17,0x6a,0x38}, 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,0x91,0x29,0x18}, 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,0x95,0x61,0x19}, 17567},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x96,0xb4,0x1e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xb1,0xb0,0x18}, 8333},
+ {{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,0xc2,0x99,0xe9}, 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,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,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,0xc8,0xcd,0x1e}, 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,0x20,0x46,0xc5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x3a,0x86,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x55,0x83,0xa8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa3,0xd3,0x4b}, 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,0x53,0xf3,0xbf,0xc7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x2e,0x74,0x47}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x34,0xff,0x93}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x38,0x69,0x11}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x3b,0xf3,0x16}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xc5,0xc6,0xa7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd6,0x4a,0x41}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd9,0xa0,0xa4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xe3,0x0e,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf6,0xc8,0x7a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x0e,0x4f,0x1a}, 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,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,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,0xc0,0xad,0x0e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x50,0xcb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0xcc,0x3f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xe5,0xa6,0x0f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xe9,0x26,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,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,0x56,0x50,0x3e,0xc2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x6b,0xcc,0x32}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x8b,0xf8,0x66}, 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,0x63,0x4f,0x7b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x68,0x7f,0x99}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x75,0x13,0xe2}, 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,0xe0,0xa3,0x42}, 8333},
+ {{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,0x8d}, 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,0x62,0xc6,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x63,0x6d,0x42}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x77,0x80,0x24}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x81,0xfd,0x2e}, 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,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,0x17,0x23,0x09}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x2f,0xd9,0xde}, 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,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,0xb3,0x7e,0x61}, 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,0xda,0xc6,0x2e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xe6,0x60,0x2a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x7d,0x9d,0x99}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x92,0x61,0x64}, 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,0x5a,0xb6,0xa5,0x12}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0xe3,0x82,0x06}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x5c,0x80,0x20}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x7b,0x52,0x0f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x87,0x00,0xbb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x98,0x79,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xb2,0x83,0x6c}, 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,0xc1,0xed,0x58}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xca,0x85,0x4b}, 8885},
+ {{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,0xdb,0x19,0xe8}, 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,0x3e,0xe7,0xfd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x3f,0xc0,0xce}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x3f,0xc5,0xf3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x3f,0xc5,0xf5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x77,0x70,0x3b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xf3,0xf4,0x65}, 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,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,0x26,0x77,0x8d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x32,0xb1,0x42}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x4f,0xcc,0xde}, 10333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x73,0x1c,0x1e}, 11100},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x73,0x59,0x4c}, 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,0x7b,0xb4,0xa4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x7e,0x5e,0xc0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xaa,0x80,0x6a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xb9,0x67,0x46}, 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,0xbe,0x8e,0x7f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xe4,0x03,0xea}, 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,0x1a,0x31,0x47}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x3f,0x41,0x7f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x48,0x8f,0x1c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x68,0xd9,0xfa}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xd1,0x73,0x34}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xed,0x48,0xa6}, 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,0x5e,0x13,0x07,0x37}, 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,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,0x57,0xe2,0x38}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x5b,0x50,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x66,0x3c,0xa8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9a,0x5a,0x63}, 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,0xa5,0xaf,0x4b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xae,0x7d,0x18}, 18333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xb7,0x36,0x65}, 12853},
{{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,0xd5,0x8f,0x0d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd5,0xb8,0x6d}, 778},
+ {{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,0x2f,0x7a,0xab}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x51,0xf4,0xbf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x63,0x0d,0x96}, 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,0x74,0x69,0x31}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xe0,0x83,0x04}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0x5c,0x27,0x74}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0x64,0xa3,0x76}, 8327},
+ {{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,0x65,0xfb,0x44,0x92}, 12337},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x66,0x84,0xe5,0xfd}, 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,0x67,0x0e,0xf4,0xbe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x10,0x80,0x3f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x3b,0x90,0x87}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x3b,0x90,0xee}, 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,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,0x64,0xdc,0x2e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x69,0x38,0x52}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x6a,0xd0,0xcf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x6a,0xd3,0x6b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x6c,0xe4,0x33}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x0b,0x90,0x47}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x80,0xe4,0xfc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x98,0xcc,0xcc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x99,0x1e,0xec}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x9b,0xe9,0x0d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc6,0x7e,0x74}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xf5,0x7d,0xfb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6a,0x0c,0x39,0x48}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6a,0x48,0x24,0x60}, 46289},
- {{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,0xbf,0x74,0x67}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x0f,0xf3,0xcf}, 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,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,0x6c,0xa0,0xca,0xd0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xd5,0xcd,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,0x63,0x3f,0x9f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x68,0x08,0x30}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xb7,0xfb,0x4d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xc6,0xbf,0x16}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xec,0x5a,0x7a}, 58333},
+ {{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,0xf8,0xce,0x0d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xfc,0x85,0x39}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6f,0x5a,0x91,0x39}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6f,0x5a,0x9f,0xb8}, 50001},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x71,0x23,0xb3,0x95}, 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,0x71,0x34,0x87,0x7d}, 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,0x3a,0xab,0x43}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x01,0x60,0x51}, 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,0x77,0x1d,0x36,0x9f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0xcf,0x4e,0x98}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xd3,0x97,0x63}, 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,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,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,0x80,0xc5,0x80,0xde}, 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,0x82,0xff,0xbb,0x56}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x72,0x0a,0xec}, 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,0x85,0x12,0x01,0x72}, 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,0x88,0x24,0x7b,0x14}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x38,0x2a,0x77}, 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,0x89,0xe2,0x22,0x2e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0x44,0x14,0x89}, 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,0x91,0xef,0x09,0x03}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x91,0xf9,0x6a,0x67}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xff,0xe3,0xb6}, 4033},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x93,0xc0,0x12,0xaf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x93,0xfd,0x36,0x1a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0x42,0x3a,0x3a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0x46,0x52,0x55}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0x5a,0x22,0x77}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0x8f,0xe7,0x48}, 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,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,0x99,0x7c,0xbb,0xdc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0xd1,0x01,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0xd3,0x9f,0xc8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9b,0x04,0x34,0x2d}, 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,0x9c,0x13,0x13,0x5a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x07,0xd3,0x6b}, 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,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,0x8a,0x2d,0xdc}, 22235},
+ {{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,0xa0,0x10,0x00,0x1e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0x9a,0xcf,0x93}, 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,0xa6,0x3e,0x52,0x67}, 32771},
+ {{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,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,0xf4,0x50,0xd0}, 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,0xb3,0x88,0x0b}, 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,0xa9,0x37,0xb6,0xb9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xab,0x21,0xb1,0x09}, 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,0xac,0x69,0x70,0xe9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x6e,0x1e,0x51}, 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,0x17,0x67,0x1e}, 8000},
{{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,0x59,0x1c,0x89}, 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,0xad,0xd0,0x80,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xf9,0x0b,0xcf}, 18333},
+ {{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,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,0xb0,0x26,0x07,0x2b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x5c,0x96,0x0c}, 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,0xb0,0x63,0x02,0xcf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7e,0xa7,0x0a}, 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,0xdf,0x88,0xab}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb1,0x34,0xad,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x21,0x88,0xa2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x80,0x27,0x6e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x8f,0x32,0x08}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xc6,0x3c,0x9b}, 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,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,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,0x34,0x25}, 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,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,0x50,0xff,0xfa}, 8333},
- {{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,0xb4,0x81,0x62}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x13,0x1c,0xc3}, 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,0xb8,0x5f,0x3a,0xa4}, 8663},
+ {{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,0x32,0x44,0x40}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x35,0x9e,0x0c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3d,0x4f,0xd5}, 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,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,0x5f,0xdb,0x35}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x82,0xd7,0x49}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x82,0xd7,0xbb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x8d,0x3c,0x7f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x93,0x0b,0x6c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x9a,0x9f,0xa4}, 9992},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xc6,0x38,0x4d}, 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,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,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,0xd8,0x8c,0x21}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xd9,0xf1,0x8e}, 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,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,0xfb,0xa1,0x36}, 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,0xd3}, 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,0x44,0x2d,0x8f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x78,0xf6,0x7d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x05,0x2f}, 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,0xa7,0x65,0x33}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xaf,0x4d,0x10}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xd5,0xa8,0x98}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xe6,0xf5,0xbc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbd,0x79,0xb9,0x94}, 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,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,0xbe,0xb8,0xc6,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xd2,0xea,0x26}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xda,0xbe,0x55}, 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,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,0xa7,0x95,0x8f}, 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,0xa9,0x5e,0x46}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xc6,0x5a,0x62}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xfe,0x59,0x86}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xfe,0x59,0xdc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x29,0x4e,0x7d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x2e,0x53,0x08}, 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,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,0x4d,0x87,0xb5}, 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,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,0x47,0xe1,0x37}, 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,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,0xc3,0x0d,0xdc,0xa5}, 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,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,0xa8,0x24,0x14}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xc9,0x21,0x00}, 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,0xf2,0x5d,0xbd}, 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,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,0x2c,0xe7,0xa0}, 6333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x36,0x71,0x3b}, 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,0x44,0xc7,0x04}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf7,0x01,0x75}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf7,0x0a,0x1a}, 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,0xc9,0xf1,0x02,0x55}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0xb9,0x2d,0x6e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x56,0xcf,0x35}, 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,0xca,0x37,0x57,0x2d}, 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,0x6f,0xf1,0xc3}, 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,0xb9,0x7a,0x96}, 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,0xb6,0x9a,0xb2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x51,0x01,0x69}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x85,0xc9,0x72}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xad,0x19,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xb4,0xae,0xc8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xbe,0x24,0x0d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0x36,0x26,0xe3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0x36,0x27,0x63}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0xcb,0xde,0x34}, 8223},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd3,0x68,0x9a,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x18,0x67,0x14}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x21,0xcc,0xbe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x33,0x9c,0x8b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x6d,0xc6,0x7e}, 8333},
- {{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,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,0xd0,0x6e,0x63,0x69}, 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,0x25,0x5c,0xa3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x59,0x62,0xc7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x59,0x96,0x0d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xae,0x9c,0x48}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xd1,0x7b,0xa5}, 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,0xd8,0x26,0x81,0xa4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x56,0x9a,0xd7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x5d,0x8b,0x3f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xba,0xfa,0x35}, 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,0xd9,0x16,0x84,0xdc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x2b,0x48,0x69}, 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,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,0x45,0x91,0xea}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x9e,0x09,0x66}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0x82,0x8e,0xb2}, 33389},
+ {{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},
- {{0x20,0x01,0x1b,0xa8,0x04,0x01,0x00,0x32,0xb8,0x42,0x38,0x91,0x59,0x15,0xc6,0x8f}, 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,0xdf,0x10,0x1e,0xaf}, 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,0x28,0x61,0x35,0xe0,0x01,0x50,0x54,0x00,0xff,0xfe,0x37,0xe9,0xeb}, 8333},
- {{0x20,0x01,0x41,0xd0,0xfc,0x63,0x9c,0x00,0x1a,0xcc,0xd2,0x2f,0x3f,0x5c,0xef,0x7f}, 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,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,0xa6,0x1a}, 8333},
- {{0x20,0x01,0x48,0x01,0x78,0x21,0x00,0x77,0xbe,0x76,0x4e,0xff,0xfe,0x10,0xc7,0xf6}, 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,0xf8,0x10,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xba}, 8333},
{{0x20,0x01,0x4b,0xa0,0xff,0xfa,0x00,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93}, 8333},
- {{0x20,0x01,0x4c,0x48,0x00,0x02,0xa3,0x28,0xd8,0xa7,0xe0,0xff,0xfe,0x96,0x40,0x3a}, 8333},
- {{0x20,0x01,0x05,0x6b,0xdd,0xa9,0x4b,0x00,0x49,0xf9,0x12,0x1b,0xaa,0x9e,0xde,0x30}, 8333},
{{0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x40,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x91}, 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,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,0x22,0xfc,0x13,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05}, 8333},
- {{0x20,0x01,0x06,0x7c,0x28,0x24,0x80,0x01,0x02,0x25,0x90,0xff,0xfe,0x67,0x98,0x30}, 7777},
- {{0x20,0x01,0x06,0x7c,0x2b,0x5c,0x01,0x01,0x02,0x16,0x3e,0xff,0xfe,0xa3,0x52,0x34}, 8333},
- {{0x20,0x01,0x06,0x7c,0x2d,0xb8,0x00,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83}, 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,0x07,0x18,0x08,0x01,0x03,0x11,0x50,0x54,0x00,0xff,0xfe,0x19,0xc4,0x83}, 8333},
- {{0x20,0x01,0x80,0x03,0xd1,0x36,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x11,0xff,0xd1}, 8333},
- {{0x20,0x01,0x08,0xd8,0x09,0x6a,0x93,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0xae,0x2c}, 8333},
- {{0x20,0x01,0x08,0xf1,0x16,0x02,0x07,0x00,0x1b,0x28,0xa3,0xe3,0xbb,0x08,0xa7,0x08}, 9444},
- {{0x20,0x01,0x08,0xf8,0x13,0x27,0x15,0x87,0x3f,0x10,0x05,0xab,0x80,0x4d,0x40,0x39}, 8333},
+ {{0x20,0x01,0x08,0x18,0xe2,0x45,0xf8,0x00,0x04,0xdf,0x2b,0xdf,0xec,0xf5,0xeb,0x60}, 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,0x0e,0x42,0x01,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30}, 8333},
- {{0x24,0x00,0x26,0x50,0x04,0x80,0xbc,0x00,0xbc,0xaf,0x7c,0x49,0x8c,0x9e,0x7c,0xdf}, 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,0x40,0x52,0x0e,0x20,0x4f,0x00,0x69,0xfe,0xbb,0x33,0x7b,0x1c,0xa1,0xca}, 8333},
- {{0x24,0x00,0x89,0x02,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xa5,0xeb,0xb7}, 8333},
- {{0x24,0x01,0x18,0x00,0x78,0x00,0x01,0x02,0xbe,0x76,0x4e,0xff,0xfe,0x1c,0x0a,0x7d}, 8333},
{{0x24,0x01,0x25,0x00,0x02,0x03,0x01,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15}, 8333},
{{0x24,0x01,0x39,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x24,0x02,0x73,0x40,0x00,0x01,0x00,0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x0d}, 8333},
- {{0x24,0x05,0x98,0x00,0xba,0x01,0x25,0x1a,0xc5,0x3c,0xb8,0x0a,0x32,0x0d,0x5b,0x41}, 8333},
+ {{0x24,0x01,0xa4,0x00,0x32,0x00,0x56,0x00,0x14,0xee,0xf3,0x61,0x4b,0xdc,0x1f,0x7c}, 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,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,0x00,0x13,0x12,0x00,0xd2,0x00,0x16,0xda,0xe9,0xff,0xfe,0xe9,0xb1,0x9a}, 8333},
- {{0x24,0x0d,0x00,0x1a,0x03,0xc0,0xab,0x00,0xe9,0xf1,0x08,0x7c,0x93,0xac,0x76,0x87}, 8333},
- {{0x26,0x02,0xff,0xc5,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x92,0x11}, 8333},
- {{0x26,0x04,0x20,0x00,0xff,0xc0,0x00,0x00,0x58,0x62,0xb6,0xf8,0xfe,0x72,0x76,0x2f}, 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,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,0x04,0x43,0x00,0x00,0x0a,0x00,0x2e,0x02,0x1b,0x21,0xff,0xfe,0x11,0x03,0x92}, 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,0x05,0x98,0x80,0x02,0x01,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x4b,0x7c}, 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,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,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,0x92,0x80,0x00,0x0b,0x07,0x3b,0x02,0x50,0x56,0xff,0xfe,0x21,0xbf,0x32}, 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,0xf3,0xa0,0x10,0x00,0x00,0x09,0xf8,0x2a,0xfd,0xff,0xfe,0xa1,0x33,0x15}, 8333},
- {{0x26,0x07,0xf4,0x70,0x00,0x08,0x10,0x48,0xae,0x1f,0x6b,0xff,0xfe,0x68,0x5e,0x42}, 8333},
- {{0x26,0x07,0xfd,0x70,0x00,0x4a,0xba,0xbe,0xb0,0x0b,0x01,0xe5,0x1b,0xd5,0x0f,0x78}, 8333},
- {{0x26,0x07,0xff,0x50,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13}, 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,0xf4,0x70,0x00,0x08,0x10,0x48,0xae,0x1f,0x6b,0xff,0xfe,0x70,0x72,0x40}, 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},
- {{0x2a,0x00,0x13,0x28,0xe1,0x01,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x63}, 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},
{{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,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x95}, 8333},
- {{0x2a,0x00,0x1b,0x60,0x00,0x02,0x00,0x04,0x40,0xd0,0x0e,0xff,0xfe,0x88,0xeb,0xd4}, 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,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,0x7b,0x80,0x04,0x54,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01}, 8333},
{{0x2a,0x00,0x8a,0x60,0xe0,0x12,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21}, 8333},
- {{0x2a,0x01,0x42,0x40,0x5f,0x52,0x92,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 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,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,0x06,0xf0,0xff,0xff,0x01,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x8d,0xcb}, 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,0x07,0xa7,0x00,0x02,0x13,0x1b,0x02,0x0c,0x29,0xff,0xfe,0x9a,0x39,0x22}, 8333},
- {{0x2a,0x01,0x07,0xc8,0xd0,0x02,0x03,0x18,0x50,0x54,0x00,0xff,0xfe,0xbe,0xcb,0xb1}, 8333},
+ {{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,0x00,0xd0,0xff,0xff,0x73,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x0e,0x0a,0x01,0x82,0x13,0x00,0x59,0x1e,0x05,0x29,0xb3,0x76,0xc6,0x54}, 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,0x02,0x12,0x05,0x34,0xc3,0xd8,0x90,0x0c,0x0e,0x74,0x1e,0xc4,0x5f,0x36,0x05}, 8333},
- {{0x2a,0x02,0x02,0xc8,0x00,0x01,0x04,0x00,0x00,0x34,0x00,0x00,0x00,0x00,0x01,0x84}, 8333},
- {{0x2a,0x02,0x2f,0x0d,0x02,0x02,0xf9,0x00,0x5e,0x9a,0xd8,0xff,0xfe,0x57,0x8b,0xc5}, 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,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,0x90,0x90,0x00,0x00,0x00,0x02,0x18,0x7d,0xff,0xfe,0x10,0xbe,0x33}, 8333},
- {{0x2a,0x02,0x47,0x80,0x00,0x09,0x00,0x00,0x00,0x02,0xf9,0x28,0xf2,0x80,0x9a,0x6f}, 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,0x7a,0xa0,0x16,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x90,0xeb,0xa2}, 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,0xc2,0x07,0x20,0x14,0x99,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 18333},
{{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x02,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xf6,0x80,0x00,0x01,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x53}, 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,0x03,0x22,0x60,0x01,0x1e,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333},
- {{0x2a,0x03,0x22,0x60,0x01,0x1e,0x03,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333},
- {{0x2a,0x03,0x40,0x00,0x00,0x06,0x41,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43}, 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,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,0x35,0x43,0x10,0x00,0x23,0x10,0x84,0x92,0xb8,0xff,0xfe,0x91,0x22,0xe8}, 8333},
- {{0x2a,0x05,0x6d,0x40,0xb9,0x4e,0xd1,0x00,0x02,0x25,0x90,0xff,0xfe,0x0d,0xcf,0xc2}, 8333},
- {{0x2a,0x05,0xfc,0x87,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06}, 8333},
+ {{0x2a,0x04,0x52,0xc0,0x01,0x01,0x09,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0xdc,0xbe}, 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,0x0b,0x2a,0xc0,0x00,0x01,0x00,0x00,0xd6,0xae,0x52,0xff,0xfe,0x7b,0x74,0x1c}, 8333},
- {{0x2a,0x0b,0x2a,0xc0,0x00,0x01,0x00,0x00,0xd6,0xae,0x52,0xff,0xfe,0x7b,0x88,0xeb}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd7,0x56,0x7b,0x57,0xc9,0x04,0x03,0x32,0x2b,0xb7}, 8333},
+ {{0x2a,0x07,0xb4,0x00,0x00,0x01,0x03,0x4c,0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x02}, 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},
+ {{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,0xd1,0xde,0x96,0xf9,0xa3,0xba,0x40,0x53,0x38,0x89}, 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,0x63,0x37,0x06,0xf7,0x51,0x94,0x7b,0x26,0xff}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd9,0xaf,0x04,0x04,0x09,0x8c,0xf1,0x2c,0x3f,0xae}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xda,0xcb,0xbf,0xc8,0x79,0x3b,0xee,0x7f,0x15,0xf5}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdc,0x3a,0x8c,0x0d,0x31,0x8d,0x27,0x04,0x87,0x58}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdc,0x33,0x15,0x3e,0xe3,0xa1,0x79,0xc4,0xc0,0xdd}, 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,0xad,0x59,0xb9,0xef,0x90,0x0a,0x50,0x5c,0xdf}, 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,0xe5,0xaf,0xbe,0x1d,0xbb,0x56,0x03,0x44,0xa9,0x66}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0x85,0x9a,0x14,0x31,0xa4,0x39,0xe9,0x07,0x42}, 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,0x64,0x56,0x71,0xb0,0x86,0x72,0xf8,0xa6,0x2f}, 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,0xf2,0xe8,0x2f,0xba,0xcb,0x08,0x40,0x9e,0xe9,0x71}, 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,0xf6,0x7a,0x2c,0x02,0x56,0xa2,0xcf,0x71,0x54,0xe9}, 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,0x37,0xde,0x1b,0x5d,0x5b,0x6b,0x1c,0x71,0x02}, 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},
@@ -660,106 +694,67 @@ static SeedSpec6 pnSeed6_main[] = {
{{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,0x0f,0xab,0x1b,0x9e,0x31,0x59,0x3e,0x9b,0xa2,0x80}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0x26,0x27,0x21,0xb1,0x03,0x56,0x84,0x5e,0x54}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0xc4,0xa9,0xc4,0xd5,0x27,0x6a,0x49,0xa6,0x4a}, 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,0x74,0xd2,0x5d,0x96,0x70,0xb1,0x8e,0xd1,0xb0}, 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,0x14,0x2c,0x2c,0x56,0xaa,0xed,0xdb,0x0a,0xef,0x16}, 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,0x1d,0xeb,0xda,0x72,0xe0,0x26,0x06,0xf0,0xc6,0x2f}, 8333},
{{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,0x2c,0x07,0x9b,0xaf,0x8a,0x48,0x5c,0x02,0x6f,0xa1}, 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,0x3e,0x75,0xeb,0x01,0x89,0x58,0x47,0xf0,0x46,0x2b}, 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,0x4d,0x3a,0x3a,0x3b,0x71,0xf3,0xfc,0x34,0x65,0xa2}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x56,0xd1,0xb9,0x52,0xeb,0x37,0x2d,0xaf,0xd0,0x12}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x57,0xdc,0xc2,0xd4,0x98,0x6b,0x52,0x6f,0x7f,0x84}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x53,0xb7,0xf9,0xa3,0xf3,0xb3,0xd6,0xa9,0xde,0x14}, 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,0x59,0x67,0x43,0x60,0xe5,0xf5,0x5a,0xea,0x21,0x45}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5b,0x76,0x29,0x35,0xbe,0xff,0xf8,0xdc,0x9b,0x0d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5d,0x4f,0xf5,0x77,0x72,0xf6,0x8b,0x11,0x7a,0x2e}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5d,0x6a,0x62,0x0d,0xef,0x63,0xd0,0x6a,0x0c,0xf9}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x60,0x52,0xa7,0x4c,0xb0,0x13,0x7a,0x66,0xca,0x2c}, 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,0x3c,0xe9,0xd0,0xc5,0x44,0xe3,0xf7,0xb5,0x75}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x68,0x97,0x13,0x84,0x84,0x8c,0xea,0x86,0xfc,0x54}, 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,0x6c,0x19,0x77,0x9a,0x2f,0xa6,0x25,0x45,0xad,0x50}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6c,0xd8,0xbd,0x00,0x94,0x66,0x0c,0xbc,0x25,0x6a}, 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,0x06,0x00,0xf6,0x1f,0x8d,0x04,0xb4,0x14,0x75}, 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,0x79,0xa8,0x52,0x04,0xe4,0xf3,0x27,0xf5,0x36,0x19}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7a,0x84,0x6b,0x97,0x5b,0xb4,0xb6,0xbb,0x42,0xb0}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7b,0xb6,0x9d,0x1c,0xaa,0x61,0x7f,0x23,0xef,0xce}, 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,0x83,0xc8,0x1b,0x10,0x02,0x56,0x33,0x37,0x46,0x2c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x84,0x97,0xbb,0xfb,0x7a,0xd7,0x40,0xbb,0xf0,0x33}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x89,0x00,0x3c,0x05,0x13,0xed,0x49,0x81,0x1c,0x9e}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0x6d,0xea,0xbe,0xdd,0x29,0x5c,0xd1,0x5e,0x87}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x96,0x88,0xfb,0x80,0x5f,0x75,0x71,0xbf,0x46,0x89}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x94,0x54,0x6c,0x57,0xa4,0x1b,0x74,0xf0,0x7d,0x0b}, 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,0x98,0xd6,0xf6,0x41,0xaf,0x2c,0x08,0x78,0x27,0xe2}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9c,0xef,0xf1,0x8e,0xcb,0x9c,0x51,0x70,0x35,0xac}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa1,0x66,0x1b,0x73,0x28,0xed,0x97,0x91,0x58,0xee}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa3,0x80,0x85,0x98,0x44,0x0a,0x69,0x69,0x73,0xe4}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa4,0x2b,0x41,0x40,0xef,0x5d,0xa0,0x14,0xc6,0x41}, 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,0xa8,0xcf,0x13,0x6d,0x5a,0x02,0x98,0x5f,0x28,0x8a}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0xab,0xcf,0x1e,0x73,0xf1,0xb0,0x8b,0x8d,0x81}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xac,0x4b,0x2e,0xa6,0xd3,0x2e,0x53,0xa9,0x4b,0xcd}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xad,0x9e,0x22,0x9a,0x84,0xb5,0xce,0xac,0x71,0x18}, 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,0xb8,0x0d,0x98,0x31,0x26,0xb1,0x87,0x55,0xe8,0x68}, 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,0xbe,0x7b,0xed,0xca,0xc3,0x48,0xff,0x88,0x61,0x81}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc5,0x19,0x7f,0x82,0x49,0xf9,0x48,0xe7,0x65,0x02}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc6,0x59,0x87,0x2e,0xaf,0xef,0x63,0x81,0xb6,0x4c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0xca,0xe8,0x95,0xf8,0x4e,0x2f,0x73,0x16,0x3d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcf,0x6f,0xab,0x12,0x5e,0x61,0xc2,0xc5,0xea,0x7d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcb,0x00,0x31,0xca,0x04,0x5d,0xb4,0xec,0x58,0xa1}, 8444},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcc,0x16,0xe4,0xda,0x62,0xe2,0xe5,0x48,0x99,0x04}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcd,0x6c,0x2f,0x80,0x7c,0x66,0x87,0x51,0x7f,0x97}, 8333}
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcb,0x00,0x31,0xca,0x04,0x5d,0xb4,0xec,0x58,0xa1}, 8444}
};
static SeedSpec6 pnSeed6_test[] = {
diff --git a/src/checkqueue.h b/src/checkqueue.h
index 9dab5a09ac..e3faa1dec0 100644
--- a/src/checkqueue.h
+++ b/src/checkqueue.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-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.
diff --git a/src/coins.cpp b/src/coins.cpp
index b71362c6a0..6b4cb2aec7 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -77,8 +77,21 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
}
if (!possible_overwrite) {
if (!it->second.coin.IsSpent()) {
- throw std::logic_error("Adding new coin that replaces non-pruned entry");
+ throw std::logic_error("Attempted to overwrite an unspent coin (when possible_overwrite is false)");
}
+ // If the coin exists in this cache as a spent coin and is DIRTY, then
+ // its spentness hasn't been flushed to the parent cache. We're
+ // re-adding the coin to this cache now but we can't mark it as FRESH.
+ // If we mark it FRESH and then spend it before the cache is flushed
+ // we would remove it from this cache and would never flush spentness
+ // to the parent cache.
+ //
+ // Re-adding a spent coin can happen in the case of a re-org (the coin
+ // is 'spent' when the block adding it is disconnected and then
+ // re-added when it is also added in a newly connected block).
+ //
+ // If the coin doesn't exist in the current cache, or is spent but not
+ // DIRTY, then it can be marked FRESH.
fresh = !(it->second.flags & CCoinsCacheEntry::DIRTY);
}
it->second.coin = std::move(coin);
@@ -86,12 +99,12 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
cachedCoinsUsage += it->second.coin.DynamicMemoryUsage();
}
-void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight, bool check) {
+void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight, bool check_for_overwrite) {
bool fCoinbase = tx.IsCoinBase();
const uint256& txid = tx.GetHash();
for (size_t i = 0; i < tx.vout.size(); ++i) {
- bool overwrite = check ? cache.HaveCoin(COutPoint(txid, i)) : fCoinbase;
- // Always set the possible_overwrite flag to AddCoin for coinbase txn, in order to correctly
+ bool overwrite = check_for_overwrite ? cache.HaveCoin(COutPoint(txid, i)) : fCoinbase;
+ // Coinbase transactions can always be overwritten, in order to correctly
// deal with the pre-BIP30 occurrences of duplicate coinbase transactions.
cache.AddCoin(COutPoint(txid, i), Coin(tx.vout[i], nHeight, fCoinbase), overwrite);
}
@@ -152,11 +165,11 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
}
CCoinsMap::iterator itUs = cacheCoins.find(it->first);
if (itUs == cacheCoins.end()) {
- // The parent cache does not have an entry, while the child does
- // We can ignore it if it's both FRESH and pruned in the child
+ // The parent cache does not have an entry, while the child cache does.
+ // We can ignore it if it's both spent and FRESH in the child
if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coin.IsSpent())) {
- // Otherwise we will need to create it in the parent
- // and move the data up and mark it as dirty
+ // Create the coin in the parent cache, move the data up
+ // and mark it as dirty.
CCoinsCacheEntry& entry = cacheCoins[it->first];
entry.coin = std::move(it->second.coin);
cachedCoinsUsage += entry.coin.DynamicMemoryUsage();
@@ -169,19 +182,18 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
}
}
} else {
- // Assert that the child cache entry was not marked FRESH if the
- // parent cache entry has unspent outputs. If this ever happens,
- // it means the FRESH flag was misapplied and there is a logic
- // error in the calling code.
+ // Found the entry in the parent cache
if ((it->second.flags & CCoinsCacheEntry::FRESH) && !itUs->second.coin.IsSpent()) {
- throw std::logic_error("FRESH flag misapplied to cache entry for base transaction with spendable outputs");
+ // The coin was marked FRESH in the child cache, but the coin
+ // exists in the parent cache. If this ever happens, it means
+ // the FRESH flag was misapplied and there is a logic error in
+ // the calling code.
+ throw std::logic_error("FRESH flag misapplied to coin that exists in parent cache");
}
- // Found the entry in the parent cache
if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coin.IsSpent()) {
- // The grandparent does not have an entry, and the child is
- // modified and being pruned. This means we can just delete
- // it from the parent.
+ // The grandparent cache does not have an entry, and the coin
+ // has been spent. We can just delete it from the parent cache.
cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
cacheCoins.erase(itUs);
} else {
@@ -190,11 +202,10 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
itUs->second.coin = std::move(it->second.coin);
cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage();
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
- // NOTE: It is possible the child has a FRESH flag here in
- // the event the entry we found in the parent is pruned. But
- // we must not copy that FRESH flag to the parent as that
- // pruned state likely still needs to be communicated to the
- // grandparent.
+ // NOTE: It isn't safe to mark the coin as FRESH in the parent
+ // cache. If it already existed and was spent in the parent
+ // cache then marking it FRESH would prevent that spentness
+ // from being flushed to the grandparent.
}
}
}
diff --git a/src/coins.h b/src/coins.h
index e71c8a47bc..2aed56c2bd 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -59,7 +59,7 @@ public:
template<typename Stream>
void Serialize(Stream &s) const {
assert(!IsSpent());
- uint32_t code = nHeight * 2 + fCoinBase;
+ uint32_t code = nHeight * uint32_t{2} + fCoinBase;
::Serialize(s, VARINT(code));
::Serialize(s, Using<TxOutCompression>(out));
}
@@ -109,19 +109,45 @@ public:
}
};
+/**
+ * A Coin in one level of the coins database caching hierarchy.
+ *
+ * A coin can either be:
+ * - unspent or spent (in which case the Coin object will be nulled out - see Coin.Clear())
+ * - DIRTY or not DIRTY
+ * - FRESH or not FRESH
+ *
+ * Out of these 2^3 = 8 states, only some combinations are valid:
+ * - unspent, FRESH, DIRTY (e.g. a new coin created in the cache)
+ * - unspent, not FRESH, DIRTY (e.g. a coin changed in the cache during a reorg)
+ * - unspent, not FRESH, not DIRTY (e.g. an unspent coin fetched from the parent cache)
+ * - spent, FRESH, not DIRTY (e.g. a spent coin fetched from the parent cache)
+ * - spent, not FRESH, DIRTY (e.g. a coin is spent and spentness needs to be flushed to the parent)
+ */
struct CCoinsCacheEntry
{
Coin coin; // The actual cached data.
unsigned char flags;
enum Flags {
- DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
- FRESH = (1 << 1), // The parent view does not have this entry (or it is pruned).
- /* Note that FRESH is a performance optimization with which we can
- * erase coins that are fully spent if we know we do not need to
- * flush the changes to the parent cache. It is always safe to
- * not mark FRESH if that condition is not guaranteed.
+ /**
+ * DIRTY means the CCoinsCacheEntry is potentially different from the
+ * version in the parent cache. Failure to mark a coin as DIRTY when
+ * it is potentially different from the parent cache will cause a
+ * consensus failure, since the coin's state won't get written to the
+ * parent when the cache is flushed.
+ */
+ DIRTY = (1 << 0),
+ /**
+ * FRESH means the parent cache does not have this coin or that it is a
+ * spent coin in the parent cache. If a FRESH coin in the cache is
+ * later spent, it can be deleted entirely and doesn't ever need to be
+ * flushed to the parent. This is a performance optimization. Marking a
+ * coin as FRESH when it exists unspent in the parent cache will cause a
+ * consensus failure, since it might not be deleted from the parent
+ * when this cache is flushed.
*/
+ FRESH = (1 << 1),
};
CCoinsCacheEntry() : flags(0) {}
@@ -246,7 +272,7 @@ public:
bool HaveCoinInCache(const COutPoint &outpoint) const;
/**
- * Return a reference to Coin in the cache, or a pruned one if not found. This is
+ * Return a reference to Coin in the cache, or coinEmpty if not found. This is
* more efficient than GetCoin.
*
* Generally, do not hold the reference returned for more than a short scope.
@@ -258,10 +284,10 @@ public:
const Coin& AccessCoin(const COutPoint &output) const;
/**
- * Add a coin. Set potential_overwrite to true if a non-pruned version may
- * already exist.
+ * Add a coin. Set possible_overwrite to true if an unspent version may
+ * already exist in the cache.
*/
- void AddCoin(const COutPoint& outpoint, Coin&& coin, bool potential_overwrite);
+ void AddCoin(const COutPoint& outpoint, Coin&& coin, bool possible_overwrite);
/**
* Spend a coin. Pass moveto in order to get the deleted data.
diff --git a/src/compressor.h b/src/compressor.h
index 7bb60d311e..478bfff0b6 100644
--- a/src/compressor.h
+++ b/src/compressor.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -15,7 +15,17 @@ bool CompressScript(const CScript& script, std::vector<unsigned char> &out);
unsigned int GetSpecialScriptSize(unsigned int nSize);
bool DecompressScript(CScript& script, unsigned int nSize, const std::vector<unsigned char> &out);
+/**
+ * Compress amount.
+ *
+ * nAmount is of type uint64_t and thus cannot be negative. If you're passing in
+ * a CAmount (int64_t), make sure to properly handle the case where the amount
+ * is negative before calling CompressAmount(...).
+ *
+ * @pre Function defined only for 0 <= nAmount <= MAX_MONEY.
+ */
uint64_t CompressAmount(uint64_t nAmount);
+
uint64_t DecompressAmount(uint64_t nAmount);
/** Compact serializer for scripts.
diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp
index 843985e54c..af01902c92 100644
--- a/src/consensus/merkle.cpp
+++ b/src/consensus/merkle.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -10,7 +10,7 @@
that the following merkle tree algorithm has a serious flaw related to
duplicate txids, resulting in a vulnerability (CVE-2012-2459).
- The reason is that if the number of hashes in the list at a given time
+ The reason is that if the number of hashes in the list at a given level
is odd, the last one is duplicated before computing the next level (which
is unusual in Merkle trees). This results in certain sequences of
transactions leading to the same merkle root. For example, these two
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index 8a3abb31f4..a79e7b9d12 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -16,7 +16,7 @@
* provider of the transaction should be banned/ignored/disconnected/etc.
*/
enum class TxValidationResult {
- TX_RESULT_UNSET, //!< initial value. Tx has not yet been rejected
+ TX_RESULT_UNSET = 0, //!< initial value. Tx has not yet been rejected
TX_CONSENSUS, //!< invalid by consensus rules
/**
* Invalid by a change to consensus rules more recent than SegWit.
@@ -50,7 +50,7 @@ enum class TxValidationResult {
* useful for some other use-cases.
*/
enum class BlockValidationResult {
- BLOCK_RESULT_UNSET, //!< initial value. Block has not yet been rejected
+ BLOCK_RESULT_UNSET = 0, //!< initial value. Block has not yet been rejected
BLOCK_CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
/**
* Invalid by a change to consensus rules more recent than SegWit.
@@ -71,31 +71,31 @@ enum class BlockValidationResult {
-/** Base class for capturing information about block/transaction validation. This is subclassed
+/** Template for capturing information about block/transaction validation. This is instantiated
* by TxValidationState and BlockValidationState for validation information on transactions
* and blocks respectively. */
+template <typename Result>
class ValidationState {
private:
enum mode_state {
MODE_VALID, //!< everything ok
MODE_INVALID, //!< network rule violation (DoS value may be set)
MODE_ERROR, //!< run-time error
- } m_mode;
+ } m_mode{MODE_VALID};
+ Result m_result{};
std::string m_reject_reason;
std::string m_debug_message;
-protected:
- void Invalid(const std::string &reject_reason="",
+public:
+ bool Invalid(Result result,
+ const std::string &reject_reason="",
const std::string &debug_message="")
{
+ m_result = result;
m_reject_reason = reject_reason;
m_debug_message = debug_message;
if (m_mode != MODE_ERROR) m_mode = MODE_INVALID;
+ return false;
}
-public:
- // ValidationState is abstract. Have a pure virtual destructor.
- virtual ~ValidationState() = 0;
-
- ValidationState() : m_mode(MODE_VALID) {}
bool Error(const std::string& reject_reason)
{
if (m_mode == MODE_VALID)
@@ -106,40 +106,25 @@ public:
bool IsValid() const { return m_mode == MODE_VALID; }
bool IsInvalid() const { return m_mode == MODE_INVALID; }
bool IsError() const { return m_mode == MODE_ERROR; }
+ Result GetResult() const { return m_result; }
std::string GetRejectReason() const { return m_reject_reason; }
std::string GetDebugMessage() const { return m_debug_message; }
-};
+ std::string ToString() const
+ {
+ if (IsValid()) {
+ return "Valid";
+ }
-inline ValidationState::~ValidationState() {};
+ if (!m_debug_message.empty()) {
+ return m_reject_reason + ", " + m_debug_message;
+ }
-class TxValidationState : public ValidationState {
-private:
- TxValidationResult m_result = TxValidationResult::TX_RESULT_UNSET;
-public:
- bool Invalid(TxValidationResult result,
- const std::string &reject_reason="",
- const std::string &debug_message="")
- {
- m_result = result;
- ValidationState::Invalid(reject_reason, debug_message);
- return false;
+ return m_reject_reason;
}
- TxValidationResult GetResult() const { return m_result; }
};
-class BlockValidationState : public ValidationState {
-private:
- BlockValidationResult m_result = BlockValidationResult::BLOCK_RESULT_UNSET;
-public:
- bool Invalid(BlockValidationResult result,
- const std::string &reject_reason="",
- const std::string &debug_message="") {
- m_result = result;
- ValidationState::Invalid(reject_reason, debug_message);
- return false;
- }
- BlockValidationResult GetResult() const { return m_result; }
-};
+class TxValidationState : public ValidationState<TxValidationResult> {};
+class BlockValidationState : public ValidationState<BlockValidationResult> {};
// These implement the weight = (stripped_size * 4) + witness_size formula,
// using only serialization with and without witness data. As witness_size
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 9a65b02585..df78c319ee 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -59,6 +59,14 @@ CScript ParseScript(const std::string& s)
{
// Number
int64_t n = atoi64(*w);
+
+ //limit the range of numbers ParseScript accepts in decimal
+ //since numbers outside -0xFFFFFFFF...0xFFFFFFFF are illegal in scripts
+ if (n > int64_t{0xffffffff} || n < -1 * int64_t{0xffffffff}) {
+ throw std::runtime_error("script parse error: decimal numeric value only allowed in the "
+ "range -0xFFFFFFFF...0xFFFFFFFF");
+ }
+
result << n;
}
else if (w->substr(0,2) == "0x" && w->size() > 2 && IsHex(std::string(w->begin()+2, w->end())))
diff --git a/src/crc32c/.appveyor.yml b/src/crc32c/.appveyor.yml
new file mode 100644
index 0000000000..7345746750
--- /dev/null
+++ b/src/crc32c/.appveyor.yml
@@ -0,0 +1,37 @@
+# Build matrix / environment variables are explained on:
+# https://www.appveyor.com/docs/appveyor-yml/
+# This file can be validated on: https://ci.appveyor.com/tools/validate-yaml
+
+version: "{build}"
+
+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
+
+platform:
+ - x86
+ - x64
+
+configuration:
+ - RelWithDebInfo
+ - Debug
+
+build_script:
+ - git submodule update --init --recursive
+ - mkdir build
+ - cd build
+ - if "%platform%"=="x64" set CMAKE_GENERATOR=%CMAKE_GENERATOR% Win64
+ - cmake --version
+ - cmake .. -G "%CMAKE_GENERATOR%" -DCRC32C_USE_GLOG=0
+ -DCMAKE_CONFIGURATION_TYPES="%CONFIGURATION%"
+ - cmake --build . --config "%CONFIGURATION%"
+ - cd ..
+
+test_script:
+ - build\%CONFIGURATION%\crc32c_tests.exe
+ - build\%CONFIGURATION%\crc32c_capi_tests.exe
+ - build\%CONFIGURATION%\crc32c_bench.exe
diff --git a/src/crc32c/.clang-format b/src/crc32c/.clang-format
new file mode 100644
index 0000000000..be9b80799f
--- /dev/null
+++ b/src/crc32c/.clang-format
@@ -0,0 +1,3 @@
+---
+Language: Cpp
+BasedOnStyle: Google
diff --git a/src/crc32c/.clang_complete b/src/crc32c/.clang_complete
new file mode 100644
index 0000000000..fa6757c6f3
--- /dev/null
+++ b/src/crc32c/.clang_complete
@@ -0,0 +1,8 @@
+-Ibuild/include/
+-Ibuild/third_party/glog/
+-Iinclude/
+-Ithird_party/benchmark/include/
+-Ithird_party/googletest/googletest/include/
+-Ithird_party/googletest/googlemock/include/
+-Ithird_party/glog/src/
+-std=c++11
diff --git a/src/crc32c/.gitignore b/src/crc32c/.gitignore
new file mode 100644
index 0000000000..61769727e3
--- /dev/null
+++ b/src/crc32c/.gitignore
@@ -0,0 +1,8 @@
+# Editors.
+*.sw*
+.DS_Store
+/.vscode
+
+# Build directory.
+build/
+out/
diff --git a/src/crc32c/.gitmodules b/src/crc32c/.gitmodules
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/crc32c/.gitmodules
diff --git a/src/crc32c/.travis.yml b/src/crc32c/.travis.yml
new file mode 100644
index 0000000000..d990a89f07
--- /dev/null
+++ b/src/crc32c/.travis.yml
@@ -0,0 +1,76 @@
+# Build matrix / environment variables are explained on:
+# http://about.travis-ci.org/docs/user/build-configuration/
+# This file can be validated on: http://lint.travis-ci.org/
+
+language: cpp
+dist: bionic
+osx_image: xcode10.3
+
+compiler:
+- gcc
+- clang
+os:
+- linux
+- osx
+
+env:
+- GLOG=1 SHARED_LIB=0 BUILD_TYPE=Debug
+- GLOG=1 SHARED_LIB=0 BUILD_TYPE=RelWithDebInfo
+- GLOG=0 SHARED_LIB=0 BUILD_TYPE=Debug
+- GLOG=0 SHARED_LIB=0 BUILD_TYPE=RelWithDebInfo
+- GLOG=0 SHARED_LIB=1 BUILD_TYPE=Debug
+- GLOG=0 SHARED_LIB=1 BUILD_TYPE=RelWithDebInfo
+
+addons:
+ apt:
+ sources:
+ - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main'
+ key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
+ - sourceline: 'ppa:ubuntu-toolchain-r/test'
+ packages:
+ - clang-9
+ - cmake
+ - gcc-9
+ - g++-9
+ - ninja-build
+ homebrew:
+ packages:
+ - cmake
+ - gcc@9
+ - llvm@9
+ - ninja
+ update: true
+
+install:
+# The following Homebrew packages aren't linked by default, and need to be
+# prepended to the path explicitly.
+- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
+ export PATH="$(brew --prefix llvm)/bin:$PATH";
+ fi
+# /usr/bin/gcc points to an older compiler on both Linux and macOS.
+- if [ "$CXX" = "g++" ]; then export CXX="g++-9" CC="gcc-9"; fi
+# /usr/bin/clang points to an older compiler on both Linux and macOS.
+#
+# Homebrew's llvm package doesn't ship a versioned clang++ binary, so the values
+# below don't work on macOS. Fortunately, the path change above makes the
+# default values (clang and clang++) resolve to the correct compiler on macOS.
+- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
+ if [ "$CXX" = "clang++" ]; then export CXX="clang++-9" CC="clang-9"; fi;
+ fi
+- echo ${CC}
+- echo ${CXX}
+- ${CXX} --version
+- cmake --version
+
+before_script:
+- mkdir -p build && cd build
+- cmake .. -G Ninja -DCRC32C_USE_GLOG=$GLOG -DCMAKE_BUILD_TYPE=$BUILD_TYPE
+ -DBUILD_SHARED_LIBS=$SHARED_LIB -DCMAKE_INSTALL_PREFIX=$HOME/.local
+- cmake --build .
+- cd ..
+
+script:
+- build/crc32c_tests
+- build/crc32c_capi_tests
+- build/crc32c_bench
+- cd build && cmake --build . --target install
diff --git a/src/crc32c/.ycm_extra_conf.py b/src/crc32c/.ycm_extra_conf.py
new file mode 100644
index 0000000000..536aadcec8
--- /dev/null
+++ b/src/crc32c/.ycm_extra_conf.py
@@ -0,0 +1,142 @@
+# Copyright 2017 The CRC32C Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""YouCompleteMe configuration that interprets a .clang_complete file.
+
+This module implementes the YouCompleteMe configuration API documented at:
+https://github.com/Valloric/ycmd#ycm_extra_confpy-specification
+
+The implementation loads and processes a .clang_complete file, documented at:
+https://github.com/Rip-Rip/clang_complete/blob/master/README.md
+"""
+
+import os
+
+# Flags added to the list in .clang_complete.
+BASE_FLAGS = [
+ '-Werror', # Unlike clang_complete, YCM can also be used as a linter.
+ '-DUSE_CLANG_COMPLETER', # YCM needs this.
+ '-xc++', # YCM needs this to avoid compiling headers as C code.
+]
+
+# Clang flags that take in paths.
+# See https://clang.llvm.org/docs/ClangCommandLineReference.html
+PATH_FLAGS = [
+ '-isystem',
+ '-I',
+ '-iquote',
+ '--sysroot='
+]
+
+
+def DirectoryOfThisScript():
+ """Returns the absolute path to the directory containing this script."""
+ return os.path.dirname(os.path.abspath(__file__))
+
+
+def MakeRelativePathsInFlagsAbsolute(flags, build_root):
+ """Expands relative paths in a list of Clang command-line flags.
+
+ Args:
+ flags: The list of flags passed to Clang.
+ build_root: The current directory when running the Clang compiler. Should be
+ an absolute path.
+
+ Returns:
+ A list of flags with relative paths replaced by absolute paths.
+ """
+ new_flags = []
+ make_next_absolute = False
+ for flag in flags:
+ new_flag = flag
+
+ if make_next_absolute:
+ make_next_absolute = False
+ if not flag.startswith('/'):
+ new_flag = os.path.join(build_root, flag)
+
+ for path_flag in PATH_FLAGS:
+ if flag == path_flag:
+ make_next_absolute = True
+ break
+
+ if flag.startswith(path_flag):
+ path = flag[len(path_flag):]
+ new_flag = path_flag + os.path.join(build_root, path)
+ break
+
+ if new_flag:
+ new_flags.append(new_flag)
+ return new_flags
+
+
+def FindNearest(target, path, build_root):
+ """Looks for a file with a specific name closest to a project path.
+
+ This is similar to the logic used by a version-control system (like git) to
+ find its configuration directory (.git) based on the current directory when a
+ command is invoked.
+
+ Args:
+ target: The file name to search for.
+ path: The directory where the search starts. The search will explore the
+ given directory's ascendants using the parent relationship. Should be an
+ absolute path.
+ build_root: A directory that acts as a fence for the search. If the search
+ reaches this directory, it will not advance to its parent. Should be an
+ absolute path.
+
+ Returns:
+ The path to a file with the desired name. None if the search failed.
+ """
+ candidate = os.path.join(path, target)
+ if os.path.isfile(candidate):
+ return candidate
+
+ if path == build_root:
+ return None
+
+ parent = os.path.dirname(path)
+ if parent == path:
+ return None
+
+ return FindNearest(target, parent, build_root)
+
+
+def FlagsForClangComplete(file_path, build_root):
+ """Reads the .clang_complete flags for a source file.
+
+ Args:
+ file_path: The path to the source file. Should be inside the project. Used
+ to locate the relevant .clang_complete file.
+ build_root: The current directory when running the Clang compiler for this
+ file. Should be an absolute path.
+
+ Returns:
+ A list of strings, where each element is a Clang command-line flag.
+ """
+ clang_complete_path = FindNearest('.clang_complete', file_path, build_root)
+ if clang_complete_path is None:
+ return None
+ clang_complete_flags = open(clang_complete_path, 'r').read().splitlines()
+ return clang_complete_flags
+
+
+def FlagsForFile(filename, **kwargs):
+ """Implements the YouCompleteMe API."""
+
+ # kwargs can be used to pass 'client_data' to the YCM configuration. This
+ # configuration script does not need any extra information, so
+ # pylint: disable=unused-argument
+
+ build_root = DirectoryOfThisScript()
+ file_path = os.path.realpath(filename)
+
+ flags = BASE_FLAGS
+ clang_flags = FlagsForClangComplete(file_path, build_root)
+ if clang_flags:
+ flags += clang_flags
+
+ final_flags = MakeRelativePathsInFlagsAbsolute(flags, build_root)
+
+ return {'flags': final_flags}
diff --git a/src/crc32c/AUTHORS b/src/crc32c/AUTHORS
new file mode 100644
index 0000000000..6f1f6871a6
--- /dev/null
+++ b/src/crc32c/AUTHORS
@@ -0,0 +1,9 @@
+# This is the list of CRC32C authors for copyright purposes.
+#
+# This does not necessarily list everyone who has contributed code, since in
+# some cases, their employer may be the copyright holder. To see the full list
+# of contributors, see the revision history in source control.
+Google Inc.
+
+Fangming Fang <Fangming.Fang@arm.com>
+Vadim Skipin <vadim.skipin@gmail.com>
diff --git a/src/crc32c/CMakeLists.txt b/src/crc32c/CMakeLists.txt
new file mode 100644
index 0000000000..111a3e3614
--- /dev/null
+++ b/src/crc32c/CMakeLists.txt
@@ -0,0 +1,423 @@
+# Copyright 2017 The CRC32C Authors. All rights reserved.
+# 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.
+
+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)
+
+# https://github.com/izenecloud/cmake/blob/master/SetCompilerWarningAll.cmake
+if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ # Use the highest warning level for Visual Studio.
+ set(CMAKE_CXX_WARNING_LEVEL 4)
+ if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+ string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ else(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
+ endif(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+
+ # Disable C++ exceptions.
+ string(REGEX REPLACE "/EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
+ add_definitions(-D_HAS_EXCEPTIONS=0)
+
+ # Disable RTTI.
+ string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
+else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ # Use -Wall for clang and gcc.
+ if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
+ endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
+
+ # Use -Wextra for clang and gcc.
+ if(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
+ endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra")
+
+ # Use -Werror for clang and gcc.
+ if(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
+ endif(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
+
+ # Disable C++ exceptions.
+ string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
+
+ # Disable RTTI.
+ string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+
+option(CRC32C_BUILD_TESTS "Build CRC32C's unit tests" ON)
+option(CRC32C_BUILD_BENCHMARKS "Build CRC32C's benchmarks" ON)
+option(CRC32C_USE_GLOG "Build CRC32C's tests with Google Logging" ON)
+option(CRC32C_INSTALL "Install CRC32C's header and library" ON)
+
+include(TestBigEndian)
+test_big_endian(BYTE_ORDER_BIG_ENDIAN)
+
+include(CheckCXXCompilerFlag)
+# Used by glog.
+check_cxx_compiler_flag(-Wno-deprecated CRC32C_HAVE_NO_DEPRECATED)
+# Used by glog.
+check_cxx_compiler_flag(-Wno-sign-compare CRC32C_HAVE_NO_SIGN_COMPARE)
+# Used by glog.
+check_cxx_compiler_flag(-Wno-unused-parameter CRC32C_HAVE_NO_UNUSED_PARAMETER)
+# Used by googletest.
+check_cxx_compiler_flag(-Wno-missing-field-initializers
+ CRC32C_HAVE_NO_MISSING_FIELD_INITIALIZERS)
+
+# Check for __builtin_prefetch support in the compiler.
+include(CheckCXXSourceCompiles)
+check_cxx_source_compiles("
+int main() {
+ char data = 0;
+ const char* address = &data;
+ __builtin_prefetch(address, 0, 0);
+ return 0;
+}
+" HAVE_BUILTIN_PREFETCH)
+
+# Check for _mm_prefetch support in the compiler.
+include(CheckCXXSourceCompiles)
+check_cxx_source_compiles("
+#if defined(_MSC_VER)
+#include <intrin.h>
+#else // !defined(_MSC_VER)
+#include <xmmintrin.h>
+#endif // defined(_MSC_VER)
+
+int main() {
+ char data = 0;
+ const char* address = &data;
+ _mm_prefetch(address, _MM_HINT_NTA);
+ return 0;
+}
+" HAVE_MM_PREFETCH)
+
+# Check for SSE4.2 support in the compiler.
+set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS})
+if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:AVX")
+else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -msse4.2")
+endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+check_cxx_source_compiles("
+#if defined(_MSC_VER)
+#include <intrin.h>
+#else // !defined(_MSC_VER)
+#include <cpuid.h>
+#include <nmmintrin.h>
+#endif // defined(_MSC_VER)
+
+int main() {
+ _mm_crc32_u8(0, 0); _mm_crc32_u32(0, 0);
+#if defined(_M_X64) || defined(__x86_64__)
+ _mm_crc32_u64(0, 0);
+#endif // defined(_M_X64) || defined(__x86_64__)
+ return 0;
+}
+" HAVE_SSE42)
+set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS})
+
+# Check for ARMv8 w/ CRC and CRYPTO extensions support in the compiler.
+set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS})
+if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ # TODO(pwnall): Insert correct flag when VS gets ARM CRC32C support.
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:NOTYET")
+else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -march=armv8-a+crc+crypto")
+endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+check_cxx_source_compiles("
+#include <arm_acle.h>
+#include <arm_neon.h>
+
+int main() {
+ __crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0);
+ vmull_p64(0, 0);
+ return 0;
+}
+" HAVE_ARM64_CRC32C)
+set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS})
+
+# Check for strong getauxval() support in the system headers.
+check_cxx_source_compiles("
+#include <arm_acle.h>
+#include <arm_neon.h>
+#include <sys/auxv.h>
+
+int main() {
+ getauxval(AT_HWCAP);
+ return 0;
+}
+" HAVE_STRONG_GETAUXVAL)
+
+# Check for weak getauxval() support in the compiler.
+check_cxx_source_compiles("
+unsigned long getauxval(unsigned long type) __attribute__((weak));
+#define AT_HWCAP 16
+
+int main() {
+ getauxval(AT_HWCAP);
+ return 0;
+}
+" HAVE_WEAK_GETAUXVAL)
+
+if(CRC32C_USE_GLOG)
+ # glog requires this setting to avoid using dynamic_cast.
+ set(DISABLE_RTTI ON CACHE BOOL "" FORCE)
+
+ # glog's test targets trigger deprecation warnings, and compiling them burns
+ # CPU cycles on the CI.
+ set(BUILD_TESTING_SAVED "${BUILD_TESTING}")
+ set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
+ add_subdirectory("third_party/glog" EXCLUDE_FROM_ALL)
+ set(BUILD_TESTING "${BUILD_TESTING_SAVED}" CACHE BOOL "" FORCE)
+
+ # glog triggers deprecation warnings on OSX.
+ # https://github.com/google/glog/issues/185
+ if(CRC32C_HAVE_NO_DEPRECATED)
+ set_property(TARGET glog APPEND PROPERTY COMPILE_OPTIONS -Wno-deprecated)
+ endif(CRC32C_HAVE_NO_DEPRECATED)
+
+ # glog triggers sign comparison warnings on gcc.
+ if(CRC32C_HAVE_NO_SIGN_COMPARE)
+ set_property(TARGET glog APPEND PROPERTY COMPILE_OPTIONS -Wno-sign-compare)
+ endif(CRC32C_HAVE_NO_SIGN_COMPARE)
+
+ # glog triggers unused parameter warnings on clang.
+ if(CRC32C_HAVE_NO_UNUSED_PARAMETER)
+ set_property(TARGET glog
+ APPEND PROPERTY COMPILE_OPTIONS -Wno-unused-parameter)
+ endif(CRC32C_HAVE_NO_UNUSED_PARAMETER)
+
+ set(CRC32C_TESTS_BUILT_WITH_GLOG 1)
+endif(CRC32C_USE_GLOG)
+
+configure_file(
+ "src/crc32c_config.h.in"
+ "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
+)
+
+include_directories("${PROJECT_BINARY_DIR}/include")
+
+# ARM64 CRC32C code is built separately, so we don't accidentally compile
+# unsupported instructions into code that gets run without ARM32 support.
+add_library(crc32c_arm64 OBJECT "")
+target_sources(crc32c_arm64
+ PRIVATE
+ "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
+ "src/crc32c_arm64.cc"
+ "src/crc32c_arm64.h"
+)
+if(HAVE_ARM64_CRC32C)
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ # TODO(pwnall): Insert correct flag when VS gets ARM64 CRC32C support.
+ target_compile_options(crc32c_arm64 PRIVATE "/arch:NOTYET")
+ else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ target_compile_options(crc32c_arm64 PRIVATE "-march=armv8-a+crc+crypto")
+ endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+endif(HAVE_ARM64_CRC32C)
+
+# CMake only enables PIC by default in SHARED and MODULE targets.
+if(BUILD_SHARED_LIBS)
+ set_property(TARGET crc32c_arm64 PROPERTY POSITION_INDEPENDENT_CODE TRUE)
+endif(BUILD_SHARED_LIBS)
+
+# SSE4.2 code is built separately, so we don't accidentally compile unsupported
+# instructions into code that gets run without SSE4.2 support.
+add_library(crc32c_sse42 OBJECT "")
+target_sources(crc32c_sse42
+ PRIVATE
+ "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
+ "src/crc32c_sse42.cc"
+ "src/crc32c_sse42.h"
+)
+if(HAVE_SSE42)
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ target_compile_options(crc32c_sse42 PRIVATE "/arch:AVX")
+ else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ target_compile_options(crc32c_sse42 PRIVATE "-msse4.2")
+ endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+endif(HAVE_SSE42)
+
+# CMake only enables PIC by default in SHARED and MODULE targets.
+if(BUILD_SHARED_LIBS)
+ set_property(TARGET crc32c_sse42 PROPERTY POSITION_INDEPENDENT_CODE TRUE)
+endif(BUILD_SHARED_LIBS)
+
+# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
+include(GNUInstallDirs)
+
+add_library(crc32c ""
+ # TODO(pwnall): Move the TARGET_OBJECTS generator expressions to the PRIVATE
+ # section of target_sources when cmake_minimum_required becomes 3.9 or above.
+ $<TARGET_OBJECTS:crc32c_arm64>
+ $<TARGET_OBJECTS:crc32c_sse42>
+)
+target_sources(crc32c
+ PRIVATE
+ "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
+ "src/crc32c_arm64.h"
+ "src/crc32c_arm64_linux_check.h"
+ "src/crc32c_internal.h"
+ "src/crc32c_portable.cc"
+ "src/crc32c_prefetch.h"
+ "src/crc32c_read_le.h"
+ "src/crc32c_round_up.h"
+ "src/crc32c_sse42.h"
+ "src/crc32c_sse42_check.h"
+ "src/crc32c.cc"
+
+ # Only CMake 3.3+ supports PUBLIC sources in targets exported by "install".
+ $<$<VERSION_GREATER:CMAKE_VERSION,3.2>:PUBLIC>
+ "include/crc32c/crc32c.h"
+)
+
+target_include_directories(crc32c
+ PUBLIC
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+target_compile_definitions(crc32c
+PRIVATE
+ CRC32C_HAVE_CONFIG_H=1
+)
+
+set_target_properties(crc32c
+ PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
+
+# Warnings as errors in Visual Studio for this project's targets.
+if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set_property(TARGET crc32c APPEND PROPERTY COMPILE_OPTIONS "/WX")
+ set_property(TARGET crc32c_arm64 APPEND PROPERTY COMPILE_OPTIONS "/WX")
+ set_property(TARGET crc32c_sse42 APPEND PROPERTY COMPILE_OPTIONS "/WX")
+endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+
+if(CRC32C_BUILD_TESTS)
+ enable_testing()
+
+ # Prevent overriding the parent project's compiler/linker settings on Windows.
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+ set(install_gtest OFF)
+ set(install_gmock OFF)
+
+ # This project is tested using GoogleTest.
+ add_subdirectory("third_party/googletest")
+
+ # GoogleTest triggers a missing field initializers warning.
+ if(CRC32C_HAVE_NO_MISSING_FIELD_INITIALIZERS)
+ set_property(TARGET gtest
+ APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
+ set_property(TARGET gmock
+ APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
+ endif(CRC32C_HAVE_NO_MISSING_FIELD_INITIALIZERS)
+
+ add_executable(crc32c_tests "")
+ target_sources(crc32c_tests
+ PRIVATE
+ "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
+ "src/crc32c_arm64_unittest.cc"
+ "src/crc32c_extend_unittests.h"
+ "src/crc32c_portable_unittest.cc"
+ "src/crc32c_prefetch_unittest.cc"
+ "src/crc32c_read_le_unittest.cc"
+ "src/crc32c_round_up_unittest.cc"
+ "src/crc32c_sse42_unittest.cc"
+ "src/crc32c_unittest.cc"
+ "src/crc32c_test_main.cc"
+ )
+ target_link_libraries(crc32c_tests crc32c gtest)
+
+ # Warnings as errors in Visual Studio for this project's targets.
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set_property(TARGET crc32c_tests APPEND PROPERTY COMPILE_OPTIONS "/WX")
+ endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+
+ if(CRC32C_USE_GLOG)
+ target_link_libraries(crc32c_tests glog)
+ endif(CRC32C_USE_GLOG)
+
+ add_test(NAME crc32c_tests COMMAND crc32c_tests)
+
+ add_executable(crc32c_capi_tests "")
+ target_sources(crc32c_capi_tests
+ PRIVATE
+ "src/crc32c_capi_unittest.c"
+ )
+ target_link_libraries(crc32c_capi_tests crc32c)
+
+ # Warnings as errors in Visual Studio for this project's targets.
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set_property(TARGET crc32c_capi_tests APPEND PROPERTY COMPILE_OPTIONS "/WX")
+ endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+
+ add_test(NAME crc32c_capi_tests COMMAND crc32c_capi_tests)
+endif(CRC32C_BUILD_TESTS)
+
+if(CRC32C_BUILD_BENCHMARKS)
+ add_executable(crc32c_bench "")
+ target_sources(crc32c_bench
+ PRIVATE
+ "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
+ "src/crc32c_benchmark.cc"
+ )
+ target_link_libraries(crc32c_bench crc32c)
+
+ # This project uses Google benchmark for benchmarking.
+ set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
+ set(BENCHMARK_ENABLE_EXCEPTIONS OFF CACHE BOOL "" FORCE)
+ add_subdirectory("third_party/benchmark")
+ target_link_libraries(crc32c_bench benchmark)
+
+ if(CRC32C_USE_GLOG)
+ target_link_libraries(crc32c_bench glog)
+ endif(CRC32C_USE_GLOG)
+
+ # Warnings as errors in Visual Studio for this project's targets.
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set_property(TARGET crc32c_bench APPEND PROPERTY COMPILE_OPTIONS "/WX")
+ endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+endif(CRC32C_BUILD_BENCHMARKS)
+
+if(CRC32C_INSTALL)
+ install(TARGETS crc32c
+ EXPORT Crc32cTargets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ )
+ install(
+ FILES
+ "include/crc32c/crc32c.h"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/crc32c"
+ )
+
+ include(CMakePackageConfigHelpers)
+ write_basic_package_version_file(
+ "${PROJECT_BINARY_DIR}/Crc32cConfigVersion.cmake"
+ COMPATIBILITY SameMajorVersion
+ )
+ install(
+ EXPORT Crc32cTargets
+ NAMESPACE Crc32c::
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Crc32c"
+ )
+ install(
+ FILES
+ "Crc32cConfig.cmake"
+ "${PROJECT_BINARY_DIR}/Crc32cConfigVersion.cmake"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Crc32c"
+ )
+endif(CRC32C_INSTALL)
diff --git a/src/crc32c/CONTRIBUTING.md b/src/crc32c/CONTRIBUTING.md
new file mode 100644
index 0000000000..ae319c70ac
--- /dev/null
+++ b/src/crc32c/CONTRIBUTING.md
@@ -0,0 +1,23 @@
+# How to Contribute
+
+We'd love to accept your patches and contributions to this project. There are
+just a few small guidelines you need to follow.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution,
+this simply gives us permission to use and redistribute your contributions as
+part of the project. Head over to <https://cla.developers.google.com/> to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+information on using pull requests.
diff --git a/src/crc32c/Crc32cConfig.cmake b/src/crc32c/Crc32cConfig.cmake
new file mode 100644
index 0000000000..4d6057ec26
--- /dev/null
+++ b/src/crc32c/Crc32cConfig.cmake
@@ -0,0 +1,5 @@
+# Copyright 2017 The CRC32C Authors. All rights reserved.
+# 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.
+
+include("${CMAKE_CURRENT_LIST_DIR}/Crc32cTargets.cmake")
diff --git a/src/crc32c/LICENSE b/src/crc32c/LICENSE
new file mode 100644
index 0000000000..8c8735cf12
--- /dev/null
+++ b/src/crc32c/LICENSE
@@ -0,0 +1,28 @@
+Copyright 2017, The CRC32C Authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/crc32c/README.md b/src/crc32c/README.md
new file mode 100644
index 0000000000..0bd69f7f09
--- /dev/null
+++ b/src/crc32c/README.md
@@ -0,0 +1,125 @@
+# CRC32C
+
+[![Build Status](https://travis-ci.org/google/crc32c.svg?branch=master)](https://travis-ci.org/google/crc32c)
+[![Build Status](https://ci.appveyor.com/api/projects/status/moiq7331pett4xuj/branch/master?svg=true)](https://ci.appveyor.com/project/pwnall/crc32c)
+
+New file format authors should consider
+[HighwayHash](https://github.com/google/highwayhash). The initial version of
+this code was extracted from [LevelDB](https://github.com/google/leveldb), which
+is a stable key-value store that is widely used at Google.
+
+This project collects a few CRC32C implementations under an umbrella that
+dispatches to a suitable implementation based on the host computer's hardware
+capabilities.
+
+CRC32C is specified as the CRC that uses the iSCSI polynomial in
+[RFC 3720](https://tools.ietf.org/html/rfc3720#section-12.1). The polynomial was
+introduced by G. Castagnoli, S. Braeuer and M. Herrmann. CRC32C is used in
+software such as Btrfs, ext4, Ceph and leveldb.
+
+
+## Usage
+
+```cpp
+#include "crc32c/crc32c.h"
+
+int main() {
+ const std::uint8_t buffer[] = {0, 0, 0, 0};
+ std::uint32_t result;
+
+ // Process a raw buffer.
+ result = crc32c::Crc32c(buffer, 4);
+
+ // Process a std::string.
+ std::string string;
+ string.resize(4);
+ result = crc32c::Crc32c(string);
+
+ // If you have C++17 support, process a std::string_view.
+ std::string_view string_view(string);
+ result = crc32c::Crc32c(string_view);
+
+ return 0;
+}
+```
+
+
+## Prerequisites
+
+This project uses [CMake](https://cmake.org/) for building and testing. CMake is
+available in all popular Linux distributions, as well as in
+[Homebrew](https://brew.sh/).
+
+This project uses submodules for dependency management.
+
+```bash
+git submodule update --init --recursive
+```
+
+If you're using [Atom](https://atom.io/), the following packages can help.
+
+```bash
+apm install autocomplete-clang build build-cmake clang-format language-cmake \
+ linter linter-clang
+```
+
+If you don't mind more setup in return for more speed, replace
+`autocomplete-clang` and `linter-clang` with `you-complete-me`. This requires
+[setting up ycmd](https://github.com/Valloric/ycmd#building).
+
+```bash
+apm install autocomplete-plus build build-cmake clang-format language-cmake \
+ linter you-complete-me
+```
+
+## Building
+
+The following commands build and install the project.
+
+```bash
+mkdir build
+cd build
+cmake -DCRC32C_BUILD_TESTS=0 -DCRC32C_BUILD_BENCHMARKS=0 .. && make all install
+```
+
+
+## Development
+
+The following command (when executed from `build/`) (re)builds the project and
+runs the tests.
+
+```bash
+cmake .. && cmake --build . && ctest --output-on-failure
+```
+
+
+### Android testing
+
+The following command builds the project against the Android NDK, which is
+useful for benchmarking against ARM processors.
+
+```bash
+cmake .. -DCMAKE_SYSTEM_NAME=Android -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
+ -DCMAKE_ANDROID_NDK=$HOME/Library/Android/sdk/ndk-bundle \
+ -DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
+ -DCMAKE_ANDROID_STL_TYPE=c++_static -DCRC32C_USE_GLOG=0 \
+ -DCMAKE_BUILD_TYPE=Release && cmake --build .
+```
+
+The following commands install and run the benchmarks.
+
+```bash
+adb push crc32c_bench /data/local/tmp
+adb shell chmod +x /data/local/tmp/crc32c_bench
+adb shell 'cd /data/local/tmp && ./crc32c_bench'
+adb shell rm /data/local/tmp/crc32c_bench
+```
+
+The following commands install and run the tests.
+
+```bash
+adb push crc32c_tests /data/local/tmp
+adb shell chmod +x /data/local/tmp/crc32c_tests
+adb shell 'cd /data/local/tmp && ./crc32c_tests'
+adb shell rm /data/local/tmp/crc32c_tests
+```
diff --git a/src/crc32c/include/crc32c/crc32c.h b/src/crc32c/include/crc32c/crc32c.h
new file mode 100644
index 0000000000..e8a78170a9
--- /dev/null
+++ b/src/crc32c/include/crc32c/crc32c.h
@@ -0,0 +1,89 @@
+/* Copyright 2017 The CRC32C Authors. All rights reserved.
+ 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. */
+
+#ifndef CRC32C_CRC32C_H_
+#define CRC32C_CRC32C_H_
+
+/* The API exported by the CRC32C project. */
+
+#if defined(__cplusplus)
+
+#include <cstddef>
+#include <cstdint>
+#include <string>
+
+#else /* !defined(__cplusplus) */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#endif /* !defined(__cplusplus) */
+
+
+/* The C API. */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+/* Extends "crc" with the CRC32C of "count" bytes in the buffer pointed by
+ "data" */
+uint32_t crc32c_extend(uint32_t crc, const uint8_t* data, size_t count);
+
+/* Computes the CRC32C of "count" bytes in the buffer pointed by "data". */
+uint32_t crc32c_value(const uint8_t* data, size_t count);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif /* defined(__cplusplus) */
+
+
+/* The C++ API. */
+
+#if defined(__cplusplus)
+
+namespace crc32c {
+
+// Extends "crc" with the CRC32C of "count" bytes in the buffer pointed by
+// "data".
+uint32_t Extend(uint32_t crc, const uint8_t* data, size_t count);
+
+// Computes the CRC32C of "count" bytes in the buffer pointed by "data".
+inline uint32_t Crc32c(const uint8_t* data, size_t count) {
+ return Extend(0, data, count);
+}
+
+// Computes the CRC32C of "count" bytes in the buffer pointed by "data".
+inline uint32_t Crc32c(const char* data, size_t count) {
+ return Extend(0, reinterpret_cast<const uint8_t*>(data), count);
+}
+
+// Computes the CRC32C of the string's content.
+inline uint32_t Crc32c(const std::string& string) {
+ return Crc32c(reinterpret_cast<const uint8_t*>(string.data()),
+ string.size());
+}
+
+} // namespace crc32c
+
+#if __cplusplus > 201402L
+#if __has_include(<string_view>)
+#include <string_view>
+
+namespace crc32c {
+
+// Computes the CRC32C of the bytes in the string_view.
+inline uint32_t Crc32c(const std::string_view& string_view) {
+ return Crc32c(reinterpret_cast<const uint8_t*>(string_view.data()),
+ string_view.size());
+}
+
+} // namespace crc32c
+
+#endif // __has_include(<string_view>)
+#endif // __cplusplus > 201402L
+
+#endif /* defined(__cplusplus) */
+
+#endif // CRC32C_CRC32C_H_
diff --git a/src/crc32c/src/crc32c.cc b/src/crc32c/src/crc32c.cc
new file mode 100644
index 0000000000..4d3018af47
--- /dev/null
+++ b/src/crc32c/src/crc32c.cc
@@ -0,0 +1,39 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "crc32c/crc32c.h"
+
+#include <cstddef>
+#include <cstdint>
+
+#include "./crc32c_arm64.h"
+#include "./crc32c_arm64_linux_check.h"
+#include "./crc32c_internal.h"
+#include "./crc32c_sse42.h"
+#include "./crc32c_sse42_check.h"
+
+namespace crc32c {
+
+uint32_t Extend(uint32_t crc, const uint8_t* data, size_t count) {
+#if HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+ 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);
+#endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+ return ExtendPortable(crc, data, count);
+}
+
+extern "C" uint32_t crc32c_extend(uint32_t crc, const uint8_t* data,
+ size_t count) {
+ return crc32c::Extend(crc, data, count);
+}
+
+extern "C" uint32_t crc32c_value(const uint8_t* data, size_t count) {
+ return crc32c::Crc32c(data, count);
+}
+
+} // namespace crc32c
diff --git a/src/crc32c/src/crc32c_arm64.cc b/src/crc32c/src/crc32c_arm64.cc
new file mode 100644
index 0000000000..b872245f95
--- /dev/null
+++ b/src/crc32c/src/crc32c_arm64.cc
@@ -0,0 +1,126 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "./crc32c_arm64.h"
+
+// In a separate source file to allow this accelerated CRC32C function to be
+// compiled with the appropriate compiler flags to enable ARM NEON CRC32C
+// instructions.
+
+// This implementation is based on https://github.com/google/leveldb/pull/490.
+
+#include <cstddef>
+#include <cstdint>
+
+#include "./crc32c_internal.h"
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+#if HAVE_ARM64_CRC32C
+
+#include <arm_acle.h>
+#include <arm_neon.h>
+
+#define KBYTES 1032
+#define SEGMENTBYTES 256
+
+// compute 8bytes for each segment parallelly
+#define CRC32C32BYTES(P, IND) \
+ do { \
+ crc1 = __crc32cd( \
+ crc1, *((const uint64_t *)(P) + (SEGMENTBYTES / 8) * 1 + (IND))); \
+ crc2 = __crc32cd( \
+ crc2, *((const uint64_t *)(P) + (SEGMENTBYTES / 8) * 2 + (IND))); \
+ crc3 = __crc32cd( \
+ crc3, *((const uint64_t *)(P) + (SEGMENTBYTES / 8) * 3 + (IND))); \
+ crc0 = __crc32cd( \
+ crc0, *((const uint64_t *)(P) + (SEGMENTBYTES / 8) * 0 + (IND))); \
+ } while (0);
+
+// compute 8*8 bytes for each segment parallelly
+#define CRC32C256BYTES(P, IND) \
+ do { \
+ CRC32C32BYTES((P), (IND)*8 + 0) \
+ CRC32C32BYTES((P), (IND)*8 + 1) \
+ CRC32C32BYTES((P), (IND)*8 + 2) \
+ CRC32C32BYTES((P), (IND)*8 + 3) \
+ CRC32C32BYTES((P), (IND)*8 + 4) \
+ CRC32C32BYTES((P), (IND)*8 + 5) \
+ CRC32C32BYTES((P), (IND)*8 + 6) \
+ CRC32C32BYTES((P), (IND)*8 + 7) \
+ } while (0);
+
+// compute 4*8*8 bytes for each segment parallelly
+#define CRC32C1024BYTES(P) \
+ do { \
+ CRC32C256BYTES((P), 0) \
+ CRC32C256BYTES((P), 1) \
+ CRC32C256BYTES((P), 2) \
+ CRC32C256BYTES((P), 3) \
+ (P) += 4 * SEGMENTBYTES; \
+ } while (0)
+
+namespace crc32c {
+
+uint32_t ExtendArm64(uint32_t crc, const uint8_t *buf, size_t size) {
+ int64_t length = size;
+ uint32_t crc0, crc1, crc2, crc3;
+ uint64_t t0, t1, t2;
+
+ // k0=CRC(x^(3*SEGMENTBYTES*8)), k1=CRC(x^(2*SEGMENTBYTES*8)),
+ // k2=CRC(x^(SEGMENTBYTES*8))
+ 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;
+ crc1 = 0;
+ crc2 = 0;
+ crc3 = 0;
+
+ // Process 1024 bytes in parallel.
+ CRC32C1024BYTES(p);
+
+ // 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(0, t2);
+ crc ^= __crc32cd(0, t1);
+ crc ^= __crc32cd(0, t0);
+
+ length -= KBYTES;
+ }
+
+ while (length >= 8) {
+ crc = __crc32cd(crc, *(uint64_t *)p);
+ p += 8;
+ length -= 8;
+ }
+
+ if (length & 4) {
+ crc = __crc32cw(crc, *(uint32_t *)p);
+ p += 4;
+ }
+
+ if (length & 2) {
+ crc = __crc32ch(crc, *(uint16_t *)p);
+ p += 2;
+ }
+
+ if (length & 1) {
+ crc = __crc32cb(crc, *p);
+ }
+
+ return crc ^ kCRC32Xor;
+}
+
+} // namespace crc32c
+
+#endif // HAVE_ARM64_CRC32C
diff --git a/src/crc32c/src/crc32c_arm64.h b/src/crc32c/src/crc32c_arm64.h
new file mode 100644
index 0000000000..100cd56ec8
--- /dev/null
+++ b/src/crc32c/src/crc32c_arm64.h
@@ -0,0 +1,27 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#ifndef CRC32C_CRC32C_ARM_LINUX_H_
+#define CRC32C_CRC32C_ARM_LINUX_H_
+
+#include <cstddef>
+#include <cstdint>
+
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+#if HAVE_ARM64_CRC32C
+
+namespace crc32c {
+
+uint32_t ExtendArm64(uint32_t crc, const uint8_t* data, size_t count);
+
+} // namespace crc32c
+
+#endif // HAVE_ARM64_CRC32C
+
+#endif // CRC32C_CRC32C_ARM_LINUX_H_
diff --git a/src/crc32c/src/crc32c_arm64_linux_check.h b/src/crc32c/src/crc32c_arm64_linux_check.h
new file mode 100644
index 0000000000..1a20a757bb
--- /dev/null
+++ b/src/crc32c/src/crc32c_arm64_linux_check.h
@@ -0,0 +1,50 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#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.
+
+#include <cstddef>
+#include <cstdint>
+
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+#if HAVE_ARM64_CRC32C
+
+#if HAVE_STRONG_GETAUXVAL
+#include <sys/auxv.h>
+#elif HAVE_WEAK_GETAUXVAL
+// getauxval() is not available on Android until API level 20. Link it as a weak
+// symbol.
+extern "C" unsigned long getauxval(unsigned long type) __attribute__((weak));
+
+#define AT_HWCAP 16
+#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
+
+namespace crc32c {
+
+inline bool CanUseArm64Linux() {
+#if 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);
+#else
+ return false;
+#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
+}
+
+} // namespace crc32c
+
+#endif // HAVE_ARM64_CRC32C
+
+#endif // CRC32C_CRC32C_ARM_LINUX_CHECK_H_
diff --git a/src/crc32c/src/crc32c_arm64_unittest.cc b/src/crc32c/src/crc32c_arm64_unittest.cc
new file mode 100644
index 0000000000..6f917d9c0c
--- /dev/null
+++ b/src/crc32c/src/crc32c_arm64_unittest.cc
@@ -0,0 +1,24 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "gtest/gtest.h"
+
+#include "./crc32c_arm64.h"
+#include "./crc32c_extend_unittests.h"
+
+namespace crc32c {
+
+#if HAVE_ARM64_CRC32C
+
+struct Arm64TestTraits {
+ static uint32_t Extend(uint32_t crc, const uint8_t* data, size_t count) {
+ return ExtendArm64(crc, data, count);
+ }
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(Arm64, ExtendTest, Arm64TestTraits);
+
+#endif // HAVE_ARM64_CRC32C
+
+} // namespace crc32c
diff --git a/src/crc32c/src/crc32c_benchmark.cc b/src/crc32c/src/crc32c_benchmark.cc
new file mode 100644
index 0000000000..c464304b3f
--- /dev/null
+++ b/src/crc32c/src/crc32c_benchmark.cc
@@ -0,0 +1,106 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include <cstddef>
+#include <cstdint>
+
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+#include "benchmark/benchmark.h"
+
+#if CRC32C_TESTS_BUILT_WITH_GLOG
+#include "glog/logging.h"
+#endif // CRC32C_TESTS_BUILT_WITH_GLOG
+
+#include "./crc32c_arm64.h"
+#include "./crc32c_arm64_linux_check.h"
+#include "./crc32c_internal.h"
+#include "./crc32c_sse42.h"
+#include "./crc32c_sse42_check.h"
+#include "crc32c/crc32c.h"
+
+class CRC32CBenchmark : public benchmark::Fixture {
+ public:
+ void SetUp(const benchmark::State& state) override {
+ block_size_ = static_cast<size_t>(state.range(0));
+ block_data_ = std::string(block_size_, 'x');
+ block_buffer_ = reinterpret_cast<const uint8_t*>(block_data_.data());
+ }
+
+ protected:
+ std::string block_data_;
+ const uint8_t* block_buffer_;
+ size_t block_size_;
+};
+
+BENCHMARK_DEFINE_F(CRC32CBenchmark, Public)(benchmark::State& state) {
+ uint32_t crc = 0;
+ for (auto _ : state)
+ crc = crc32c::Extend(crc, block_buffer_, block_size_);
+ state.SetBytesProcessed(state.iterations() * block_size_);
+}
+BENCHMARK_REGISTER_F(CRC32CBenchmark, Public)
+ ->RangeMultiplier(16)
+ ->Range(256, 16777216); // Block size.
+
+BENCHMARK_DEFINE_F(CRC32CBenchmark, Portable)(benchmark::State& state) {
+ uint32_t crc = 0;
+ for (auto _ : state)
+ crc = crc32c::ExtendPortable(crc, block_buffer_, block_size_);
+ state.SetBytesProcessed(state.iterations() * block_size_);
+}
+BENCHMARK_REGISTER_F(CRC32CBenchmark, Portable)
+ ->RangeMultiplier(16)
+ ->Range(256, 16777216); // Block size.
+
+#if HAVE_ARM64_CRC32C
+
+BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmLinux)(benchmark::State& state) {
+ if (!crc32c::CanUseArm64Linux()) {
+ state.SkipWithError("ARM CRC32C instructions not available or not enabled");
+ return;
+ }
+
+ uint32_t crc = 0;
+ for (auto _ : state)
+ crc = crc32c::ExtendArm64(crc, block_buffer_, block_size_);
+ state.SetBytesProcessed(state.iterations() * block_size_);
+}
+BENCHMARK_REGISTER_F(CRC32CBenchmark, ArmLinux)
+ ->RangeMultiplier(16)
+ ->Range(256, 16777216); // Block size.
+
+#endif // HAVE_ARM64_CRC32C
+
+#if HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+BENCHMARK_DEFINE_F(CRC32CBenchmark, Sse42)(benchmark::State& state) {
+ if (!crc32c::CanUseSse42()) {
+ state.SkipWithError("SSE4.2 instructions not available or not enabled");
+ return;
+ }
+
+ uint32_t crc = 0;
+ for (auto _ : state)
+ crc = crc32c::ExtendSse42(crc, block_buffer_, block_size_);
+ state.SetBytesProcessed(state.iterations() * block_size_);
+}
+BENCHMARK_REGISTER_F(CRC32CBenchmark, Sse42)
+ ->RangeMultiplier(16)
+ ->Range(256, 16777216); // Block size.
+
+#endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+int main(int argc, char** argv) {
+#if CRC32C_TESTS_BUILT_WITH_GLOG
+ google::InitGoogleLogging(argv[0]);
+ google::InstallFailureSignalHandler();
+#endif // CRC32C_TESTS_BUILT_WITH_GLOG
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ return 0;
+}
diff --git a/src/crc32c/src/crc32c_capi_unittest.c b/src/crc32c/src/crc32c_capi_unittest.c
new file mode 100644
index 0000000000..c8993a0959
--- /dev/null
+++ b/src/crc32c/src/crc32c_capi_unittest.c
@@ -0,0 +1,66 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "crc32c/crc32c.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main() {
+ /* From rfc3720 section B.4. */
+ uint8_t buf[32];
+
+ memset(buf, 0, sizeof(buf));
+ if ((uint32_t)0x8a9136aa != crc32c_value(buf, sizeof(buf))) {
+ printf("crc32c_value(zeros) test failed\n");
+ return 1;
+ }
+
+ memset(buf, 0xff, sizeof(buf));
+ if ((uint32_t)0x62a8ab43 != crc32c_value(buf, sizeof(buf))) {
+ printf("crc32c_value(0xff) test failed\n");
+ return 1;
+ }
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = (uint8_t)i;
+ if ((uint32_t)0x46dd794e != crc32c_value(buf, sizeof(buf))) {
+ printf("crc32c_value(0..31) test failed\n");
+ return 1;
+ }
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = (uint8_t)(31 - i);
+ if ((uint32_t)0x113fdb5c != crc32c_value(buf, sizeof(buf))) {
+ printf("crc32c_value(31..0) test failed\n");
+ return 1;
+ }
+
+ uint8_t data[48] = {
+ 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ if ((uint32_t)0xd9963a56 != crc32c_value(data, sizeof(data))) {
+ printf("crc32c_value(31..0) test failed\n");
+ return 1;
+ }
+
+ const uint8_t* hello_space_world = (const uint8_t*)"hello world";
+ const uint8_t* hello_space = (const uint8_t*)"hello ";
+ const uint8_t* world = (const uint8_t*)"world";
+
+ if (crc32c_value(hello_space_world, 11) !=
+ crc32c_extend(crc32c_value(hello_space, 6), world, 5)) {
+ printf("crc32c_extend test failed\n");
+ return 1;
+ }
+
+ printf("All tests passed\n");
+ return 0;
+}
diff --git a/src/crc32c/src/crc32c_config.h.in b/src/crc32c/src/crc32c_config.h.in
new file mode 100644
index 0000000000..4034fa5644
--- /dev/null
+++ b/src/crc32c/src/crc32c_config.h.in
@@ -0,0 +1,36 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#ifndef CRC32C_CRC32C_CONFIG_H_
+#define CRC32C_CRC32C_CONFIG_H_
+
+// Define to 1 if building for a big-endian platform.
+#cmakedefine01 BYTE_ORDER_BIG_ENDIAN
+
+// Define to 1 if the compiler has the __builtin_prefetch intrinsic.
+#cmakedefine01 HAVE_BUILTIN_PREFETCH
+
+// Define to 1 if targeting X86 and the compiler has the _mm_prefetch intrinsic.
+#cmakedefine01 HAVE_MM_PREFETCH
+
+// Define to 1 if targeting X86 and the compiler has the _mm_crc32_u{8,32,64}
+// intrinsics.
+#cmakedefine01 HAVE_SSE42
+
+// Define to 1 if targeting ARM and the compiler has the __crc32c{b,h,w,d} and
+// the vmull_p64 intrinsics.
+#cmakedefine01 HAVE_ARM64_CRC32C
+
+// Define to 1 if the system libraries have the getauxval function in the
+// <sys/auxv.h> header. Should be true on Linux and Android API level 20+.
+#cmakedefine01 HAVE_STRONG_GETAUXVAL
+
+// Define to 1 if the compiler supports defining getauxval as a weak symbol.
+// Should be true for any compiler that supports __attribute__((weak)).
+#cmakedefine01 HAVE_WEAK_GETAUXVAL
+
+// Define to 1 if CRC32C tests have been built with Google Logging.
+#cmakedefine01 CRC32C_TESTS_BUILT_WITH_GLOG
+
+#endif // CRC32C_CRC32C_CONFIG_H_
diff --git a/src/crc32c/src/crc32c_extend_unittests.h b/src/crc32c/src/crc32c_extend_unittests.h
new file mode 100644
index 0000000000..0732973737
--- /dev/null
+++ b/src/crc32c/src/crc32c_extend_unittests.h
@@ -0,0 +1,112 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#ifndef CRC32C_CRC32C_EXTEND_UNITTESTS_H_
+#define CRC32C_CRC32C_EXTEND_UNITTESTS_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+
+#include "gtest/gtest.h"
+
+// Common test cases for all implementations of CRC32C_Extend().
+
+namespace crc32c {
+
+template<typename TestTraits>
+class ExtendTest : public testing::Test {};
+
+TYPED_TEST_SUITE_P(ExtendTest);
+
+TYPED_TEST_P(ExtendTest, StandardResults) {
+ // From rfc3720 section B.4.
+ uint8_t buf[32];
+
+ std::memset(buf, 0, sizeof(buf));
+ EXPECT_EQ(static_cast<uint32_t>(0x8a9136aa),
+ TypeParam::Extend(0, buf, sizeof(buf)));
+
+ std::memset(buf, 0xff, sizeof(buf));
+ EXPECT_EQ(static_cast<uint32_t>(0x62a8ab43),
+ TypeParam::Extend(0, buf, sizeof(buf)));
+
+ for (int i = 0; i < 32; ++i)
+ buf[i] = static_cast<uint8_t>(i);
+ EXPECT_EQ(static_cast<uint32_t>(0x46dd794e),
+ TypeParam::Extend(0, buf, sizeof(buf)));
+
+ for (int i = 0; i < 32; ++i)
+ buf[i] = static_cast<uint8_t>(31 - i);
+ EXPECT_EQ(static_cast<uint32_t>(0x113fdb5c),
+ TypeParam::Extend(0, buf, sizeof(buf)));
+
+ uint8_t data[48] = {
+ 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ EXPECT_EQ(static_cast<uint32_t>(0xd9963a56),
+ TypeParam::Extend(0, data, sizeof(data)));
+}
+
+TYPED_TEST_P(ExtendTest, HelloWorld) {
+ const uint8_t* hello_space_world =
+ reinterpret_cast<const uint8_t*>("hello world");
+ const uint8_t* hello_space = reinterpret_cast<const uint8_t*>("hello ");
+ const uint8_t* world = reinterpret_cast<const uint8_t*>("world");
+
+ EXPECT_EQ(TypeParam::Extend(0, hello_space_world, 11),
+ TypeParam::Extend(TypeParam::Extend(0, hello_space, 6), world, 5));
+}
+
+TYPED_TEST_P(ExtendTest, BufferSlicing) {
+ uint8_t buffer[48] = {
+ 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ for (size_t i = 0; i < 48; ++i) {
+ for (size_t j = i + 1; j <= 48; ++j) {
+ uint32_t crc = 0;
+
+ if (i > 0) crc = TypeParam::Extend(crc, buffer, i);
+ crc = TypeParam::Extend(crc, buffer + i, j - i);
+ if (j < 48) crc = TypeParam::Extend(crc, buffer + j, 48 - j);
+
+ EXPECT_EQ(static_cast<uint32_t>(0xd9963a56), crc);
+ }
+ }
+}
+
+TYPED_TEST_P(ExtendTest, LargeBufferSlicing) {
+ uint8_t buffer[2048];
+ for (size_t i = 0; i < 2048; i++)
+ buffer[i] = static_cast<uint8_t>(3 * i * i + 7 * i + 11);
+
+ for (size_t i = 0; i < 2048; ++i) {
+ for (size_t j = i + 1; j <= 2048; ++j) {
+ uint32_t crc = 0;
+
+ if (i > 0) crc = TypeParam::Extend(crc, buffer, i);
+ crc = TypeParam::Extend(crc, buffer + i, j - i);
+ if (j < 2048) crc = TypeParam::Extend(crc, buffer + j, 2048 - j);
+
+ EXPECT_EQ(static_cast<uint32_t>(0x36dcc753), crc);
+ }
+ }
+}
+
+REGISTER_TYPED_TEST_SUITE_P(ExtendTest,
+ StandardResults,
+ HelloWorld,
+ BufferSlicing,
+ LargeBufferSlicing);
+
+} // namespace crc32c
+
+#endif // CRC32C_CRC32C_EXTEND_UNITTESTS_H_
diff --git a/src/crc32c/src/crc32c_internal.h b/src/crc32c/src/crc32c_internal.h
new file mode 100644
index 0000000000..2bd23dea43
--- /dev/null
+++ b/src/crc32c/src/crc32c_internal.h
@@ -0,0 +1,23 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#ifndef CRC32C_CRC32C_INTERNAL_H_
+#define CRC32C_CRC32C_INTERNAL_H_
+
+// Internal functions that may change between releases.
+
+#include <cstddef>
+#include <cstdint>
+
+namespace crc32c {
+
+// Un-accelerated implementation that works on all CPUs.
+uint32_t ExtendPortable(uint32_t crc, const uint8_t* data, size_t count);
+
+// CRCs are pre- and post- conditioned by xoring with all ones.
+static constexpr const uint32_t kCRC32Xor = static_cast<uint32_t>(0xffffffffU);
+
+} // namespace crc32c
+
+#endif // CRC32C_CRC32C_INTERNAL_H_
diff --git a/src/crc32c/src/crc32c_portable.cc b/src/crc32c/src/crc32c_portable.cc
new file mode 100644
index 0000000000..31ec6eac53
--- /dev/null
+++ b/src/crc32c/src/crc32c_portable.cc
@@ -0,0 +1,351 @@
+// Copyright 2008 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "./crc32c_internal.h"
+
+#include <cstddef>
+#include <cstdint>
+
+#include "./crc32c_prefetch.h"
+#include "./crc32c_read_le.h"
+#include "./crc32c_round_up.h"
+
+namespace {
+
+const uint32_t kByteExtensionTable[256] = {
+ 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c,
+ 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
+ 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c,
+ 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
+ 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc,
+ 0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
+ 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512,
+ 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
+ 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad,
+ 0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
+ 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf,
+ 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
+ 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f,
+ 0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
+ 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f,
+ 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
+ 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e,
+ 0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
+ 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e,
+ 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
+ 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de,
+ 0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
+ 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4,
+ 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
+ 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b,
+ 0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
+ 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5,
+ 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
+ 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975,
+ 0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
+ 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905,
+ 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
+ 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8,
+ 0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
+ 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8,
+ 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
+ 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78,
+ 0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
+ 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6,
+ 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
+ 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69,
+ 0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
+ 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351};
+
+const uint32_t kStrideExtensionTable0[256] = {
+ 0x00000000, 0x30d23865, 0x61a470ca, 0x517648af, 0xc348e194, 0xf39ad9f1,
+ 0xa2ec915e, 0x923ea93b, 0x837db5d9, 0xb3af8dbc, 0xe2d9c513, 0xd20bfd76,
+ 0x4035544d, 0x70e76c28, 0x21912487, 0x11431ce2, 0x03171d43, 0x33c52526,
+ 0x62b36d89, 0x526155ec, 0xc05ffcd7, 0xf08dc4b2, 0xa1fb8c1d, 0x9129b478,
+ 0x806aa89a, 0xb0b890ff, 0xe1ced850, 0xd11ce035, 0x4322490e, 0x73f0716b,
+ 0x228639c4, 0x125401a1, 0x062e3a86, 0x36fc02e3, 0x678a4a4c, 0x57587229,
+ 0xc566db12, 0xf5b4e377, 0xa4c2abd8, 0x941093bd, 0x85538f5f, 0xb581b73a,
+ 0xe4f7ff95, 0xd425c7f0, 0x461b6ecb, 0x76c956ae, 0x27bf1e01, 0x176d2664,
+ 0x053927c5, 0x35eb1fa0, 0x649d570f, 0x544f6f6a, 0xc671c651, 0xf6a3fe34,
+ 0xa7d5b69b, 0x97078efe, 0x8644921c, 0xb696aa79, 0xe7e0e2d6, 0xd732dab3,
+ 0x450c7388, 0x75de4bed, 0x24a80342, 0x147a3b27, 0x0c5c750c, 0x3c8e4d69,
+ 0x6df805c6, 0x5d2a3da3, 0xcf149498, 0xffc6acfd, 0xaeb0e452, 0x9e62dc37,
+ 0x8f21c0d5, 0xbff3f8b0, 0xee85b01f, 0xde57887a, 0x4c692141, 0x7cbb1924,
+ 0x2dcd518b, 0x1d1f69ee, 0x0f4b684f, 0x3f99502a, 0x6eef1885, 0x5e3d20e0,
+ 0xcc0389db, 0xfcd1b1be, 0xada7f911, 0x9d75c174, 0x8c36dd96, 0xbce4e5f3,
+ 0xed92ad5c, 0xdd409539, 0x4f7e3c02, 0x7fac0467, 0x2eda4cc8, 0x1e0874ad,
+ 0x0a724f8a, 0x3aa077ef, 0x6bd63f40, 0x5b040725, 0xc93aae1e, 0xf9e8967b,
+ 0xa89eded4, 0x984ce6b1, 0x890ffa53, 0xb9ddc236, 0xe8ab8a99, 0xd879b2fc,
+ 0x4a471bc7, 0x7a9523a2, 0x2be36b0d, 0x1b315368, 0x096552c9, 0x39b76aac,
+ 0x68c12203, 0x58131a66, 0xca2db35d, 0xfaff8b38, 0xab89c397, 0x9b5bfbf2,
+ 0x8a18e710, 0xbacadf75, 0xebbc97da, 0xdb6eafbf, 0x49500684, 0x79823ee1,
+ 0x28f4764e, 0x18264e2b, 0x18b8ea18, 0x286ad27d, 0x791c9ad2, 0x49cea2b7,
+ 0xdbf00b8c, 0xeb2233e9, 0xba547b46, 0x8a864323, 0x9bc55fc1, 0xab1767a4,
+ 0xfa612f0b, 0xcab3176e, 0x588dbe55, 0x685f8630, 0x3929ce9f, 0x09fbf6fa,
+ 0x1baff75b, 0x2b7dcf3e, 0x7a0b8791, 0x4ad9bff4, 0xd8e716cf, 0xe8352eaa,
+ 0xb9436605, 0x89915e60, 0x98d24282, 0xa8007ae7, 0xf9763248, 0xc9a40a2d,
+ 0x5b9aa316, 0x6b489b73, 0x3a3ed3dc, 0x0aecebb9, 0x1e96d09e, 0x2e44e8fb,
+ 0x7f32a054, 0x4fe09831, 0xddde310a, 0xed0c096f, 0xbc7a41c0, 0x8ca879a5,
+ 0x9deb6547, 0xad395d22, 0xfc4f158d, 0xcc9d2de8, 0x5ea384d3, 0x6e71bcb6,
+ 0x3f07f419, 0x0fd5cc7c, 0x1d81cddd, 0x2d53f5b8, 0x7c25bd17, 0x4cf78572,
+ 0xdec92c49, 0xee1b142c, 0xbf6d5c83, 0x8fbf64e6, 0x9efc7804, 0xae2e4061,
+ 0xff5808ce, 0xcf8a30ab, 0x5db49990, 0x6d66a1f5, 0x3c10e95a, 0x0cc2d13f,
+ 0x14e49f14, 0x2436a771, 0x7540efde, 0x4592d7bb, 0xd7ac7e80, 0xe77e46e5,
+ 0xb6080e4a, 0x86da362f, 0x97992acd, 0xa74b12a8, 0xf63d5a07, 0xc6ef6262,
+ 0x54d1cb59, 0x6403f33c, 0x3575bb93, 0x05a783f6, 0x17f38257, 0x2721ba32,
+ 0x7657f29d, 0x4685caf8, 0xd4bb63c3, 0xe4695ba6, 0xb51f1309, 0x85cd2b6c,
+ 0x948e378e, 0xa45c0feb, 0xf52a4744, 0xc5f87f21, 0x57c6d61a, 0x6714ee7f,
+ 0x3662a6d0, 0x06b09eb5, 0x12caa592, 0x22189df7, 0x736ed558, 0x43bced3d,
+ 0xd1824406, 0xe1507c63, 0xb02634cc, 0x80f40ca9, 0x91b7104b, 0xa165282e,
+ 0xf0136081, 0xc0c158e4, 0x52fff1df, 0x622dc9ba, 0x335b8115, 0x0389b970,
+ 0x11ddb8d1, 0x210f80b4, 0x7079c81b, 0x40abf07e, 0xd2955945, 0xe2476120,
+ 0xb331298f, 0x83e311ea, 0x92a00d08, 0xa272356d, 0xf3047dc2, 0xc3d645a7,
+ 0x51e8ec9c, 0x613ad4f9, 0x304c9c56, 0x009ea433};
+
+const uint32_t kStrideExtensionTable1[256] = {
+ 0x00000000, 0x54075546, 0xa80eaa8c, 0xfc09ffca, 0x55f123e9, 0x01f676af,
+ 0xfdff8965, 0xa9f8dc23, 0xabe247d2, 0xffe51294, 0x03eced5e, 0x57ebb818,
+ 0xfe13643b, 0xaa14317d, 0x561dceb7, 0x021a9bf1, 0x5228f955, 0x062fac13,
+ 0xfa2653d9, 0xae21069f, 0x07d9dabc, 0x53de8ffa, 0xafd77030, 0xfbd02576,
+ 0xf9cabe87, 0xadcdebc1, 0x51c4140b, 0x05c3414d, 0xac3b9d6e, 0xf83cc828,
+ 0x043537e2, 0x503262a4, 0xa451f2aa, 0xf056a7ec, 0x0c5f5826, 0x58580d60,
+ 0xf1a0d143, 0xa5a78405, 0x59ae7bcf, 0x0da92e89, 0x0fb3b578, 0x5bb4e03e,
+ 0xa7bd1ff4, 0xf3ba4ab2, 0x5a429691, 0x0e45c3d7, 0xf24c3c1d, 0xa64b695b,
+ 0xf6790bff, 0xa27e5eb9, 0x5e77a173, 0x0a70f435, 0xa3882816, 0xf78f7d50,
+ 0x0b86829a, 0x5f81d7dc, 0x5d9b4c2d, 0x099c196b, 0xf595e6a1, 0xa192b3e7,
+ 0x086a6fc4, 0x5c6d3a82, 0xa064c548, 0xf463900e, 0x4d4f93a5, 0x1948c6e3,
+ 0xe5413929, 0xb1466c6f, 0x18beb04c, 0x4cb9e50a, 0xb0b01ac0, 0xe4b74f86,
+ 0xe6add477, 0xb2aa8131, 0x4ea37efb, 0x1aa42bbd, 0xb35cf79e, 0xe75ba2d8,
+ 0x1b525d12, 0x4f550854, 0x1f676af0, 0x4b603fb6, 0xb769c07c, 0xe36e953a,
+ 0x4a964919, 0x1e911c5f, 0xe298e395, 0xb69fb6d3, 0xb4852d22, 0xe0827864,
+ 0x1c8b87ae, 0x488cd2e8, 0xe1740ecb, 0xb5735b8d, 0x497aa447, 0x1d7df101,
+ 0xe91e610f, 0xbd193449, 0x4110cb83, 0x15179ec5, 0xbcef42e6, 0xe8e817a0,
+ 0x14e1e86a, 0x40e6bd2c, 0x42fc26dd, 0x16fb739b, 0xeaf28c51, 0xbef5d917,
+ 0x170d0534, 0x430a5072, 0xbf03afb8, 0xeb04fafe, 0xbb36985a, 0xef31cd1c,
+ 0x133832d6, 0x473f6790, 0xeec7bbb3, 0xbac0eef5, 0x46c9113f, 0x12ce4479,
+ 0x10d4df88, 0x44d38ace, 0xb8da7504, 0xecdd2042, 0x4525fc61, 0x1122a927,
+ 0xed2b56ed, 0xb92c03ab, 0x9a9f274a, 0xce98720c, 0x32918dc6, 0x6696d880,
+ 0xcf6e04a3, 0x9b6951e5, 0x6760ae2f, 0x3367fb69, 0x317d6098, 0x657a35de,
+ 0x9973ca14, 0xcd749f52, 0x648c4371, 0x308b1637, 0xcc82e9fd, 0x9885bcbb,
+ 0xc8b7de1f, 0x9cb08b59, 0x60b97493, 0x34be21d5, 0x9d46fdf6, 0xc941a8b0,
+ 0x3548577a, 0x614f023c, 0x635599cd, 0x3752cc8b, 0xcb5b3341, 0x9f5c6607,
+ 0x36a4ba24, 0x62a3ef62, 0x9eaa10a8, 0xcaad45ee, 0x3eced5e0, 0x6ac980a6,
+ 0x96c07f6c, 0xc2c72a2a, 0x6b3ff609, 0x3f38a34f, 0xc3315c85, 0x973609c3,
+ 0x952c9232, 0xc12bc774, 0x3d2238be, 0x69256df8, 0xc0ddb1db, 0x94dae49d,
+ 0x68d31b57, 0x3cd44e11, 0x6ce62cb5, 0x38e179f3, 0xc4e88639, 0x90efd37f,
+ 0x39170f5c, 0x6d105a1a, 0x9119a5d0, 0xc51ef096, 0xc7046b67, 0x93033e21,
+ 0x6f0ac1eb, 0x3b0d94ad, 0x92f5488e, 0xc6f21dc8, 0x3afbe202, 0x6efcb744,
+ 0xd7d0b4ef, 0x83d7e1a9, 0x7fde1e63, 0x2bd94b25, 0x82219706, 0xd626c240,
+ 0x2a2f3d8a, 0x7e2868cc, 0x7c32f33d, 0x2835a67b, 0xd43c59b1, 0x803b0cf7,
+ 0x29c3d0d4, 0x7dc48592, 0x81cd7a58, 0xd5ca2f1e, 0x85f84dba, 0xd1ff18fc,
+ 0x2df6e736, 0x79f1b270, 0xd0096e53, 0x840e3b15, 0x7807c4df, 0x2c009199,
+ 0x2e1a0a68, 0x7a1d5f2e, 0x8614a0e4, 0xd213f5a2, 0x7beb2981, 0x2fec7cc7,
+ 0xd3e5830d, 0x87e2d64b, 0x73814645, 0x27861303, 0xdb8fecc9, 0x8f88b98f,
+ 0x267065ac, 0x727730ea, 0x8e7ecf20, 0xda799a66, 0xd8630197, 0x8c6454d1,
+ 0x706dab1b, 0x246afe5d, 0x8d92227e, 0xd9957738, 0x259c88f2, 0x719bddb4,
+ 0x21a9bf10, 0x75aeea56, 0x89a7159c, 0xdda040da, 0x74589cf9, 0x205fc9bf,
+ 0xdc563675, 0x88516333, 0x8a4bf8c2, 0xde4cad84, 0x2245524e, 0x76420708,
+ 0xdfbadb2b, 0x8bbd8e6d, 0x77b471a7, 0x23b324e1};
+
+const uint32_t kStrideExtensionTable2[256] = {
+ 0x00000000, 0x678efd01, 0xcf1dfa02, 0xa8930703, 0x9bd782f5, 0xfc597ff4,
+ 0x54ca78f7, 0x334485f6, 0x3243731b, 0x55cd8e1a, 0xfd5e8919, 0x9ad07418,
+ 0xa994f1ee, 0xce1a0cef, 0x66890bec, 0x0107f6ed, 0x6486e636, 0x03081b37,
+ 0xab9b1c34, 0xcc15e135, 0xff5164c3, 0x98df99c2, 0x304c9ec1, 0x57c263c0,
+ 0x56c5952d, 0x314b682c, 0x99d86f2f, 0xfe56922e, 0xcd1217d8, 0xaa9cead9,
+ 0x020fedda, 0x658110db, 0xc90dcc6c, 0xae83316d, 0x0610366e, 0x619ecb6f,
+ 0x52da4e99, 0x3554b398, 0x9dc7b49b, 0xfa49499a, 0xfb4ebf77, 0x9cc04276,
+ 0x34534575, 0x53ddb874, 0x60993d82, 0x0717c083, 0xaf84c780, 0xc80a3a81,
+ 0xad8b2a5a, 0xca05d75b, 0x6296d058, 0x05182d59, 0x365ca8af, 0x51d255ae,
+ 0xf94152ad, 0x9ecfafac, 0x9fc85941, 0xf846a440, 0x50d5a343, 0x375b5e42,
+ 0x041fdbb4, 0x639126b5, 0xcb0221b6, 0xac8cdcb7, 0x97f7ee29, 0xf0791328,
+ 0x58ea142b, 0x3f64e92a, 0x0c206cdc, 0x6bae91dd, 0xc33d96de, 0xa4b36bdf,
+ 0xa5b49d32, 0xc23a6033, 0x6aa96730, 0x0d279a31, 0x3e631fc7, 0x59ede2c6,
+ 0xf17ee5c5, 0x96f018c4, 0xf371081f, 0x94fff51e, 0x3c6cf21d, 0x5be20f1c,
+ 0x68a68aea, 0x0f2877eb, 0xa7bb70e8, 0xc0358de9, 0xc1327b04, 0xa6bc8605,
+ 0x0e2f8106, 0x69a17c07, 0x5ae5f9f1, 0x3d6b04f0, 0x95f803f3, 0xf276fef2,
+ 0x5efa2245, 0x3974df44, 0x91e7d847, 0xf6692546, 0xc52da0b0, 0xa2a35db1,
+ 0x0a305ab2, 0x6dbea7b3, 0x6cb9515e, 0x0b37ac5f, 0xa3a4ab5c, 0xc42a565d,
+ 0xf76ed3ab, 0x90e02eaa, 0x387329a9, 0x5ffdd4a8, 0x3a7cc473, 0x5df23972,
+ 0xf5613e71, 0x92efc370, 0xa1ab4686, 0xc625bb87, 0x6eb6bc84, 0x09384185,
+ 0x083fb768, 0x6fb14a69, 0xc7224d6a, 0xa0acb06b, 0x93e8359d, 0xf466c89c,
+ 0x5cf5cf9f, 0x3b7b329e, 0x2a03aaa3, 0x4d8d57a2, 0xe51e50a1, 0x8290ada0,
+ 0xb1d42856, 0xd65ad557, 0x7ec9d254, 0x19472f55, 0x1840d9b8, 0x7fce24b9,
+ 0xd75d23ba, 0xb0d3debb, 0x83975b4d, 0xe419a64c, 0x4c8aa14f, 0x2b045c4e,
+ 0x4e854c95, 0x290bb194, 0x8198b697, 0xe6164b96, 0xd552ce60, 0xb2dc3361,
+ 0x1a4f3462, 0x7dc1c963, 0x7cc63f8e, 0x1b48c28f, 0xb3dbc58c, 0xd455388d,
+ 0xe711bd7b, 0x809f407a, 0x280c4779, 0x4f82ba78, 0xe30e66cf, 0x84809bce,
+ 0x2c139ccd, 0x4b9d61cc, 0x78d9e43a, 0x1f57193b, 0xb7c41e38, 0xd04ae339,
+ 0xd14d15d4, 0xb6c3e8d5, 0x1e50efd6, 0x79de12d7, 0x4a9a9721, 0x2d146a20,
+ 0x85876d23, 0xe2099022, 0x878880f9, 0xe0067df8, 0x48957afb, 0x2f1b87fa,
+ 0x1c5f020c, 0x7bd1ff0d, 0xd342f80e, 0xb4cc050f, 0xb5cbf3e2, 0xd2450ee3,
+ 0x7ad609e0, 0x1d58f4e1, 0x2e1c7117, 0x49928c16, 0xe1018b15, 0x868f7614,
+ 0xbdf4448a, 0xda7ab98b, 0x72e9be88, 0x15674389, 0x2623c67f, 0x41ad3b7e,
+ 0xe93e3c7d, 0x8eb0c17c, 0x8fb73791, 0xe839ca90, 0x40aacd93, 0x27243092,
+ 0x1460b564, 0x73ee4865, 0xdb7d4f66, 0xbcf3b267, 0xd972a2bc, 0xbefc5fbd,
+ 0x166f58be, 0x71e1a5bf, 0x42a52049, 0x252bdd48, 0x8db8da4b, 0xea36274a,
+ 0xeb31d1a7, 0x8cbf2ca6, 0x242c2ba5, 0x43a2d6a4, 0x70e65352, 0x1768ae53,
+ 0xbffba950, 0xd8755451, 0x74f988e6, 0x137775e7, 0xbbe472e4, 0xdc6a8fe5,
+ 0xef2e0a13, 0x88a0f712, 0x2033f011, 0x47bd0d10, 0x46bafbfd, 0x213406fc,
+ 0x89a701ff, 0xee29fcfe, 0xdd6d7908, 0xbae38409, 0x1270830a, 0x75fe7e0b,
+ 0x107f6ed0, 0x77f193d1, 0xdf6294d2, 0xb8ec69d3, 0x8ba8ec25, 0xec261124,
+ 0x44b51627, 0x233beb26, 0x223c1dcb, 0x45b2e0ca, 0xed21e7c9, 0x8aaf1ac8,
+ 0xb9eb9f3e, 0xde65623f, 0x76f6653c, 0x1178983d};
+
+const uint32_t kStrideExtensionTable3[256] = {
+ 0x00000000, 0xf20c0dfe, 0xe1f46d0d, 0x13f860f3, 0xc604aceb, 0x3408a115,
+ 0x27f0c1e6, 0xd5fccc18, 0x89e52f27, 0x7be922d9, 0x6811422a, 0x9a1d4fd4,
+ 0x4fe183cc, 0xbded8e32, 0xae15eec1, 0x5c19e33f, 0x162628bf, 0xe42a2541,
+ 0xf7d245b2, 0x05de484c, 0xd0228454, 0x222e89aa, 0x31d6e959, 0xc3dae4a7,
+ 0x9fc30798, 0x6dcf0a66, 0x7e376a95, 0x8c3b676b, 0x59c7ab73, 0xabcba68d,
+ 0xb833c67e, 0x4a3fcb80, 0x2c4c517e, 0xde405c80, 0xcdb83c73, 0x3fb4318d,
+ 0xea48fd95, 0x1844f06b, 0x0bbc9098, 0xf9b09d66, 0xa5a97e59, 0x57a573a7,
+ 0x445d1354, 0xb6511eaa, 0x63add2b2, 0x91a1df4c, 0x8259bfbf, 0x7055b241,
+ 0x3a6a79c1, 0xc866743f, 0xdb9e14cc, 0x29921932, 0xfc6ed52a, 0x0e62d8d4,
+ 0x1d9ab827, 0xef96b5d9, 0xb38f56e6, 0x41835b18, 0x527b3beb, 0xa0773615,
+ 0x758bfa0d, 0x8787f7f3, 0x947f9700, 0x66739afe, 0x5898a2fc, 0xaa94af02,
+ 0xb96ccff1, 0x4b60c20f, 0x9e9c0e17, 0x6c9003e9, 0x7f68631a, 0x8d646ee4,
+ 0xd17d8ddb, 0x23718025, 0x3089e0d6, 0xc285ed28, 0x17792130, 0xe5752cce,
+ 0xf68d4c3d, 0x048141c3, 0x4ebe8a43, 0xbcb287bd, 0xaf4ae74e, 0x5d46eab0,
+ 0x88ba26a8, 0x7ab62b56, 0x694e4ba5, 0x9b42465b, 0xc75ba564, 0x3557a89a,
+ 0x26afc869, 0xd4a3c597, 0x015f098f, 0xf3530471, 0xe0ab6482, 0x12a7697c,
+ 0x74d4f382, 0x86d8fe7c, 0x95209e8f, 0x672c9371, 0xb2d05f69, 0x40dc5297,
+ 0x53243264, 0xa1283f9a, 0xfd31dca5, 0x0f3dd15b, 0x1cc5b1a8, 0xeec9bc56,
+ 0x3b35704e, 0xc9397db0, 0xdac11d43, 0x28cd10bd, 0x62f2db3d, 0x90fed6c3,
+ 0x8306b630, 0x710abbce, 0xa4f677d6, 0x56fa7a28, 0x45021adb, 0xb70e1725,
+ 0xeb17f41a, 0x191bf9e4, 0x0ae39917, 0xf8ef94e9, 0x2d1358f1, 0xdf1f550f,
+ 0xcce735fc, 0x3eeb3802, 0xb13145f8, 0x433d4806, 0x50c528f5, 0xa2c9250b,
+ 0x7735e913, 0x8539e4ed, 0x96c1841e, 0x64cd89e0, 0x38d46adf, 0xcad86721,
+ 0xd92007d2, 0x2b2c0a2c, 0xfed0c634, 0x0cdccbca, 0x1f24ab39, 0xed28a6c7,
+ 0xa7176d47, 0x551b60b9, 0x46e3004a, 0xb4ef0db4, 0x6113c1ac, 0x931fcc52,
+ 0x80e7aca1, 0x72eba15f, 0x2ef24260, 0xdcfe4f9e, 0xcf062f6d, 0x3d0a2293,
+ 0xe8f6ee8b, 0x1afae375, 0x09028386, 0xfb0e8e78, 0x9d7d1486, 0x6f711978,
+ 0x7c89798b, 0x8e857475, 0x5b79b86d, 0xa975b593, 0xba8dd560, 0x4881d89e,
+ 0x14983ba1, 0xe694365f, 0xf56c56ac, 0x07605b52, 0xd29c974a, 0x20909ab4,
+ 0x3368fa47, 0xc164f7b9, 0x8b5b3c39, 0x795731c7, 0x6aaf5134, 0x98a35cca,
+ 0x4d5f90d2, 0xbf539d2c, 0xacabfddf, 0x5ea7f021, 0x02be131e, 0xf0b21ee0,
+ 0xe34a7e13, 0x114673ed, 0xc4babff5, 0x36b6b20b, 0x254ed2f8, 0xd742df06,
+ 0xe9a9e704, 0x1ba5eafa, 0x085d8a09, 0xfa5187f7, 0x2fad4bef, 0xdda14611,
+ 0xce5926e2, 0x3c552b1c, 0x604cc823, 0x9240c5dd, 0x81b8a52e, 0x73b4a8d0,
+ 0xa64864c8, 0x54446936, 0x47bc09c5, 0xb5b0043b, 0xff8fcfbb, 0x0d83c245,
+ 0x1e7ba2b6, 0xec77af48, 0x398b6350, 0xcb876eae, 0xd87f0e5d, 0x2a7303a3,
+ 0x766ae09c, 0x8466ed62, 0x979e8d91, 0x6592806f, 0xb06e4c77, 0x42624189,
+ 0x519a217a, 0xa3962c84, 0xc5e5b67a, 0x37e9bb84, 0x2411db77, 0xd61dd689,
+ 0x03e11a91, 0xf1ed176f, 0xe215779c, 0x10197a62, 0x4c00995d, 0xbe0c94a3,
+ 0xadf4f450, 0x5ff8f9ae, 0x8a0435b6, 0x78083848, 0x6bf058bb, 0x99fc5545,
+ 0xd3c39ec5, 0x21cf933b, 0x3237f3c8, 0xc03bfe36, 0x15c7322e, 0xe7cb3fd0,
+ 0xf4335f23, 0x063f52dd, 0x5a26b1e2, 0xa82abc1c, 0xbbd2dcef, 0x49ded111,
+ 0x9c221d09, 0x6e2e10f7, 0x7dd67004, 0x8fda7dfa};
+
+constexpr const ptrdiff_t kPrefetchHorizon = 256;
+
+} // namespace
+
+namespace crc32c {
+
+uint32_t ExtendPortable(uint32_t crc, const uint8_t* data, size_t size) {
+ const uint8_t* p = data;
+ const uint8_t* e = p + size;
+ uint32_t l = crc ^ kCRC32Xor;
+
+// Process one byte at a time.
+#define STEP1 \
+ do { \
+ int c = (l & 0xff) ^ *p++; \
+ l = kByteExtensionTable[c] ^ (l >> 8); \
+ } while (0)
+
+// Process one of the 4 strides of 4-byte data.
+#define STEP4(s) \
+ do { \
+ crc##s = ReadUint32LE(p + s * 4) ^ kStrideExtensionTable3[crc##s & 0xff] ^ \
+ kStrideExtensionTable2[(crc##s >> 8) & 0xff] ^ \
+ kStrideExtensionTable1[(crc##s >> 16) & 0xff] ^ \
+ kStrideExtensionTable0[crc##s >> 24]; \
+ } while (0)
+
+// Process a 16-byte swath of 4 strides, each of which has 4 bytes of data.
+#define STEP16 \
+ do { \
+ STEP4(0); \
+ STEP4(1); \
+ STEP4(2); \
+ STEP4(3); \
+ p += 16; \
+ } while (0)
+
+// Process 4 bytes that were already loaded into a word.
+#define STEP4W(w) \
+ do { \
+ w ^= l; \
+ for (size_t i = 0; i < 4; ++i) { \
+ w = (w >> 8) ^ kByteExtensionTable[w & 0xff]; \
+ } \
+ l = w; \
+ } while (0)
+
+ // Point x at first 4-byte aligned byte in the buffer. This might be past the
+ // end of the buffer.
+ const uint8_t* x = RoundUp<4>(p);
+ if (x <= e) {
+ // Process bytes p is 4-byte aligned.
+ while (p != x) {
+ STEP1;
+ }
+ }
+
+ if ((e - p) >= 16) {
+ // Load a 16-byte swath into the stride partial results.
+ uint32_t crc0 = ReadUint32LE(p + 0 * 4) ^ l;
+ uint32_t crc1 = ReadUint32LE(p + 1 * 4);
+ uint32_t crc2 = ReadUint32LE(p + 2 * 4);
+ uint32_t crc3 = ReadUint32LE(p + 3 * 4);
+ p += 16;
+
+ while ((e - p) > kPrefetchHorizon) {
+ RequestPrefetch(p + kPrefetchHorizon);
+
+ // Process 64 bytes at a time.
+ STEP16;
+ STEP16;
+ STEP16;
+ STEP16;
+ }
+
+ // Process one 16-byte swath at a time.
+ while ((e - p) >= 16) {
+ STEP16;
+ }
+
+ // Advance one word at a time as far as possible.
+ while ((e - p) >= 4) {
+ STEP4(0);
+ uint32_t tmp = crc0;
+ crc0 = crc1;
+ crc1 = crc2;
+ crc2 = crc3;
+ crc3 = tmp;
+ p += 4;
+ }
+
+ // Combine the 4 partial stride results.
+ l = 0;
+ STEP4W(crc0);
+ STEP4W(crc1);
+ STEP4W(crc2);
+ STEP4W(crc3);
+ }
+
+ // Process the last few bytes.
+ while (p != e) {
+ STEP1;
+ }
+#undef STEP4W
+#undef STEP16
+#undef STEP4
+#undef STEP1
+ return l ^ kCRC32Xor;
+}
+
+} // namespace crc32c
diff --git a/src/crc32c/src/crc32c_portable_unittest.cc b/src/crc32c/src/crc32c_portable_unittest.cc
new file mode 100644
index 0000000000..5098e2c373
--- /dev/null
+++ b/src/crc32c/src/crc32c_portable_unittest.cc
@@ -0,0 +1,20 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "gtest/gtest.h"
+
+#include "./crc32c_extend_unittests.h"
+#include "./crc32c_internal.h"
+
+namespace crc32c {
+
+struct PortableTestTraits {
+ static uint32_t Extend(uint32_t crc, const uint8_t* data, size_t count) {
+ return ExtendPortable(crc, data, count);
+ }
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(Portable, ExtendTest, PortableTestTraits);
+
+} // namespace crc32c
diff --git a/src/crc32c/src/crc32c_prefetch.h b/src/crc32c/src/crc32c_prefetch.h
new file mode 100644
index 0000000000..aec7d54e84
--- /dev/null
+++ b/src/crc32c/src/crc32c_prefetch.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#ifndef CRC32C_CRC32C_PREFETCH_H_
+#define CRC32C_CRC32C_PREFETCH_H_
+
+#include <cstddef>
+#include <cstdint>
+
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+#if HAVE_MM_PREFETCH
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+#else // !defined(_MSC_VER)
+#include <xmmintrin.h>
+#endif // defined(_MSC_VER)
+
+#endif // HAVE_MM_PREFETCH
+
+namespace crc32c {
+
+// Ask the hardware to prefetch the data at the given address into the L1 cache.
+inline void RequestPrefetch(const uint8_t* address) {
+#if HAVE_BUILTIN_PREFETCH
+ // Clang and GCC implement the __builtin_prefetch non-standard extension,
+ // which maps to the best instruction on the target architecture.
+ __builtin_prefetch(reinterpret_cast<const char*>(address), 0 /* Read only. */,
+ 0 /* No temporal locality. */);
+#elif HAVE_MM_PREFETCH
+ // Visual Studio doesn't implement __builtin_prefetch, but exposes the
+ // PREFETCHNTA instruction via the _mm_prefetch intrinsic.
+ _mm_prefetch(reinterpret_cast<const char*>(address), _MM_HINT_NTA);
+#else
+ // No prefetch support. Silence compiler warnings.
+ (void)address;
+#endif // HAVE_BUILTIN_PREFETCH
+}
+
+} // namespace crc32c
+
+#endif // CRC32C_CRC32C_ROUND_UP_H_
diff --git a/src/crc32c/src/crc32c_prefetch_unittest.cc b/src/crc32c/src/crc32c_prefetch_unittest.cc
new file mode 100644
index 0000000000..b34ed2d5fe
--- /dev/null
+++ b/src/crc32c/src/crc32c_prefetch_unittest.cc
@@ -0,0 +1,9 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "./crc32c_prefetch.h"
+
+// There is no easy way to test cache prefetching. We can only test that the
+// crc32c_prefetch.h header compiles on its own, so it doesn't have any unstated
+// dependencies.
diff --git a/src/crc32c/src/crc32c_read_le.h b/src/crc32c/src/crc32c_read_le.h
new file mode 100644
index 0000000000..3bd45fe3aa
--- /dev/null
+++ b/src/crc32c/src/crc32c_read_le.h
@@ -0,0 +1,53 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#ifndef CRC32C_CRC32C_READ_LE_H_
+#define CRC32C_CRC32C_READ_LE_H_
+
+#include <cstdint>
+#include <cstring>
+
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+namespace crc32c {
+
+// Reads a little-endian 32-bit integer from a 32-bit-aligned buffer.
+inline uint32_t ReadUint32LE(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));
+#else // !BYTE_ORDER_BIG_ENDIAN
+ uint32_t result;
+ // This should be optimized to a single instruction.
+ std::memcpy(&result, buffer, sizeof(result));
+ return result;
+#endif // BYTE_ORDER_BIG_ENDIAN
+}
+
+// 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));
+#else // !BYTE_ORDER_BIG_ENDIAN
+ uint64_t result;
+ // This should be optimized to a single instruction.
+ std::memcpy(&result, buffer, sizeof(result));
+ return result;
+#endif // BYTE_ORDER_BIG_ENDIAN
+}
+
+} // namespace crc32c
+
+#endif // CRC32C_CRC32C_READ_LE_H_
diff --git a/src/crc32c/src/crc32c_read_le_unittest.cc b/src/crc32c/src/crc32c_read_le_unittest.cc
new file mode 100644
index 0000000000..2a30302adf
--- /dev/null
+++ b/src/crc32c/src/crc32c_read_le_unittest.cc
@@ -0,0 +1,32 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "./crc32c_read_le.h"
+
+#include <cstddef>
+#include <cstdint>
+
+#include "gtest/gtest.h"
+
+#include "./crc32c_round_up.h"
+
+namespace crc32c {
+
+TEST(Crc32CReadLETest, ReadUint32LE) {
+ // little-endian 0x12345678
+ alignas(4) uint8_t bytes[] = {0x78, 0x56, 0x34, 0x12};
+
+ ASSERT_EQ(RoundUp<4>(bytes), bytes) << "Stack array is not aligned";
+ EXPECT_EQ(static_cast<uint32_t>(0x12345678), ReadUint32LE(bytes));
+}
+
+TEST(Crc32CReadLETest, ReadUint64LE) {
+ // little-endian 0x123456789ABCDEF0
+ alignas(8) uint8_t bytes[] = {0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12};
+
+ ASSERT_EQ(RoundUp<8>(bytes), bytes) << "Stack array is not aligned";
+ EXPECT_EQ(static_cast<uint64_t>(0x123456789ABCDEF0), ReadUint64LE(bytes));
+}
+
+} // namespace crc32c
diff --git a/src/crc32c/src/crc32c_round_up.h b/src/crc32c/src/crc32c_round_up.h
new file mode 100644
index 0000000000..d3b922beb9
--- /dev/null
+++ b/src/crc32c/src/crc32c_round_up.h
@@ -0,0 +1,34 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#ifndef CRC32C_CRC32C_ROUND_UP_H_
+#define CRC32C_CRC32C_ROUND_UP_H_
+
+#include <cstddef>
+#include <cstdint>
+
+namespace crc32c {
+
+// Returns the smallest number >= the given number that is evenly divided by N.
+//
+// N must be a power of two.
+template <int N>
+constexpr inline uintptr_t RoundUp(uintptr_t pointer) {
+ static_assert((N & (N - 1)) == 0, "N must be a power of two");
+ return (pointer + (N - 1)) & ~(N - 1);
+}
+
+// Returns the smallest address >= the given address that is aligned to N bytes.
+//
+// N must be a power of two.
+template <int N>
+constexpr inline const uint8_t* RoundUp(const uint8_t* pointer) {
+ static_assert((N & (N - 1)) == 0, "N must be a power of two");
+ return reinterpret_cast<uint8_t*>(
+ RoundUp<N>(reinterpret_cast<uintptr_t>(pointer)));
+}
+
+} // namespace crc32c
+
+#endif // CRC32C_CRC32C_ROUND_UP_H_
diff --git a/src/crc32c/src/crc32c_round_up_unittest.cc b/src/crc32c/src/crc32c_round_up_unittest.cc
new file mode 100644
index 0000000000..5ff657bb5c
--- /dev/null
+++ b/src/crc32c/src/crc32c_round_up_unittest.cc
@@ -0,0 +1,84 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "./crc32c_round_up.h"
+
+#include <cstddef>
+#include <cstdint>
+
+#include "gtest/gtest.h"
+
+namespace crc32c {
+
+TEST(CRC32CRoundUpTest, RoundUpUintptr) {
+ uintptr_t zero = 0;
+
+ ASSERT_EQ(zero, RoundUp<1>(zero));
+ ASSERT_EQ(1U, RoundUp<1>(1U));
+ ASSERT_EQ(2U, RoundUp<1>(2U));
+ ASSERT_EQ(3U, RoundUp<1>(3U));
+ ASSERT_EQ(~static_cast<uintptr_t>(0), RoundUp<1>(~static_cast<uintptr_t>(0)));
+ ASSERT_EQ(~static_cast<uintptr_t>(1), RoundUp<1>(~static_cast<uintptr_t>(1)));
+ ASSERT_EQ(~static_cast<uintptr_t>(2), RoundUp<1>(~static_cast<uintptr_t>(2)));
+ ASSERT_EQ(~static_cast<uintptr_t>(3), RoundUp<1>(~static_cast<uintptr_t>(3)));
+
+ ASSERT_EQ(zero, RoundUp<2>(zero));
+ ASSERT_EQ(2U, RoundUp<2>(1U));
+ ASSERT_EQ(2U, RoundUp<2>(2U));
+ ASSERT_EQ(4U, RoundUp<2>(3U));
+ ASSERT_EQ(4U, RoundUp<2>(4U));
+ ASSERT_EQ(6U, RoundUp<2>(5U));
+ ASSERT_EQ(6U, RoundUp<2>(6U));
+ ASSERT_EQ(8U, RoundUp<2>(7U));
+ ASSERT_EQ(8U, RoundUp<2>(8U));
+ ASSERT_EQ(~static_cast<uintptr_t>(1), RoundUp<2>(~static_cast<uintptr_t>(1)));
+ ASSERT_EQ(~static_cast<uintptr_t>(1), RoundUp<2>(~static_cast<uintptr_t>(2)));
+ ASSERT_EQ(~static_cast<uintptr_t>(3), RoundUp<2>(~static_cast<uintptr_t>(3)));
+ ASSERT_EQ(~static_cast<uintptr_t>(3), RoundUp<2>(~static_cast<uintptr_t>(4)));
+
+ ASSERT_EQ(zero, RoundUp<4>(zero));
+ ASSERT_EQ(4U, RoundUp<4>(1U));
+ ASSERT_EQ(4U, RoundUp<4>(2U));
+ ASSERT_EQ(4U, RoundUp<4>(3U));
+ ASSERT_EQ(4U, RoundUp<4>(4U));
+ ASSERT_EQ(8U, RoundUp<4>(5U));
+ ASSERT_EQ(8U, RoundUp<4>(6U));
+ ASSERT_EQ(8U, RoundUp<4>(7U));
+ ASSERT_EQ(8U, RoundUp<4>(8U));
+ ASSERT_EQ(~static_cast<uintptr_t>(3), RoundUp<4>(~static_cast<uintptr_t>(3)));
+ ASSERT_EQ(~static_cast<uintptr_t>(3), RoundUp<4>(~static_cast<uintptr_t>(4)));
+ ASSERT_EQ(~static_cast<uintptr_t>(3), RoundUp<4>(~static_cast<uintptr_t>(5)));
+ ASSERT_EQ(~static_cast<uintptr_t>(3), RoundUp<4>(~static_cast<uintptr_t>(6)));
+ ASSERT_EQ(~static_cast<uintptr_t>(7), RoundUp<4>(~static_cast<uintptr_t>(7)));
+ ASSERT_EQ(~static_cast<uintptr_t>(7), RoundUp<4>(~static_cast<uintptr_t>(8)));
+ ASSERT_EQ(~static_cast<uintptr_t>(7), RoundUp<4>(~static_cast<uintptr_t>(9)));
+}
+
+TEST(CRC32CRoundUpTest, RoundUpPointer) {
+ uintptr_t zero = 0, three = 3, four = 4, seven = 7, eight = 8;
+
+ const uint8_t* zero_ptr = reinterpret_cast<const uint8_t*>(zero);
+ const uint8_t* three_ptr = reinterpret_cast<const uint8_t*>(three);
+ const uint8_t* four_ptr = reinterpret_cast<const uint8_t*>(four);
+ const uint8_t* seven_ptr = reinterpret_cast<const uint8_t*>(seven);
+ const uint8_t* eight_ptr = reinterpret_cast<uint8_t*>(eight);
+
+ ASSERT_EQ(zero_ptr, RoundUp<1>(zero_ptr));
+ ASSERT_EQ(zero_ptr, RoundUp<4>(zero_ptr));
+ ASSERT_EQ(zero_ptr, RoundUp<8>(zero_ptr));
+
+ ASSERT_EQ(three_ptr, RoundUp<1>(three_ptr));
+ ASSERT_EQ(four_ptr, RoundUp<4>(three_ptr));
+ ASSERT_EQ(eight_ptr, RoundUp<8>(three_ptr));
+
+ ASSERT_EQ(four_ptr, RoundUp<1>(four_ptr));
+ ASSERT_EQ(four_ptr, RoundUp<4>(four_ptr));
+ ASSERT_EQ(eight_ptr, RoundUp<8>(four_ptr));
+
+ ASSERT_EQ(seven_ptr, RoundUp<1>(seven_ptr));
+ ASSERT_EQ(eight_ptr, RoundUp<4>(seven_ptr));
+ ASSERT_EQ(eight_ptr, RoundUp<8>(four_ptr));
+}
+
+} // namespace crc32c
diff --git a/src/crc32c/src/crc32c_sse42.cc b/src/crc32c/src/crc32c_sse42.cc
new file mode 100644
index 0000000000..139520428e
--- /dev/null
+++ b/src/crc32c/src/crc32c_sse42.cc
@@ -0,0 +1,258 @@
+// Copyright 2008 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "./crc32c_sse42.h"
+
+// In a separate source file to allow this accelerated CRC32C function to be
+// compiled with the appropriate compiler flags to enable SSE4.2 instructions.
+
+// This implementation is loosely based on Intel Pub 323405 from April 2011,
+// "Fast CRC Computation for iSCSI Polynomial Using CRC32 Instruction".
+
+#include <cstddef>
+#include <cstdint>
+
+#include "./crc32c_internal.h"
+#include "./crc32c_prefetch.h"
+#include "./crc32c_read_le.h"
+#include "./crc32c_round_up.h"
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+#if HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+#else // !defined(_MSC_VER)
+#include <nmmintrin.h>
+#endif // defined(_MSC_VER)
+
+namespace crc32c {
+
+namespace {
+
+constexpr const ptrdiff_t kGroups = 3;
+constexpr const ptrdiff_t kBlock0Size = 16 * 1024 / kGroups / 64 * 64;
+constexpr const ptrdiff_t kBlock1Size = 4 * 1024 / kGroups / 8 * 8;
+constexpr const ptrdiff_t kBlock2Size = 1024 / kGroups / 8 * 8;
+
+const uint32_t kBlock0SkipTable[8][16] = {
+ {0x00000000, 0xff770459, 0xfb027e43, 0x04757a1a, 0xf3e88a77, 0x0c9f8e2e,
+ 0x08eaf434, 0xf79df06d, 0xe23d621f, 0x1d4a6646, 0x193f1c5c, 0xe6481805,
+ 0x11d5e868, 0xeea2ec31, 0xead7962b, 0x15a09272},
+ {0x00000000, 0xc196b2cf, 0x86c1136f, 0x4757a1a0, 0x086e502f, 0xc9f8e2e0,
+ 0x8eaf4340, 0x4f39f18f, 0x10dca05e, 0xd14a1291, 0x961db331, 0x578b01fe,
+ 0x18b2f071, 0xd92442be, 0x9e73e31e, 0x5fe551d1},
+ {0x00000000, 0x21b940bc, 0x43728178, 0x62cbc1c4, 0x86e502f0, 0xa75c424c,
+ 0xc5978388, 0xe42ec334, 0x08267311, 0x299f33ad, 0x4b54f269, 0x6aedb2d5,
+ 0x8ec371e1, 0xaf7a315d, 0xcdb1f099, 0xec08b025},
+ {0x00000000, 0x104ce622, 0x2099cc44, 0x30d52a66, 0x41339888, 0x517f7eaa,
+ 0x61aa54cc, 0x71e6b2ee, 0x82673110, 0x922bd732, 0xa2fefd54, 0xb2b21b76,
+ 0xc354a998, 0xd3184fba, 0xe3cd65dc, 0xf38183fe},
+ {0x00000000, 0x012214d1, 0x024429a2, 0x03663d73, 0x04885344, 0x05aa4795,
+ 0x06cc7ae6, 0x07ee6e37, 0x0910a688, 0x0832b259, 0x0b548f2a, 0x0a769bfb,
+ 0x0d98f5cc, 0x0cbae11d, 0x0fdcdc6e, 0x0efec8bf},
+ {0x00000000, 0x12214d10, 0x24429a20, 0x3663d730, 0x48853440, 0x5aa47950,
+ 0x6cc7ae60, 0x7ee6e370, 0x910a6880, 0x832b2590, 0xb548f2a0, 0xa769bfb0,
+ 0xd98f5cc0, 0xcbae11d0, 0xfdcdc6e0, 0xefec8bf0},
+ {0x00000000, 0x27f8a7f1, 0x4ff14fe2, 0x6809e813, 0x9fe29fc4, 0xb81a3835,
+ 0xd013d026, 0xf7eb77d7, 0x3a294979, 0x1dd1ee88, 0x75d8069b, 0x5220a16a,
+ 0xa5cbd6bd, 0x8233714c, 0xea3a995f, 0xcdc23eae},
+ {0x00000000, 0x745292f2, 0xe8a525e4, 0x9cf7b716, 0xd4a63d39, 0xa0f4afcb,
+ 0x3c0318dd, 0x48518a2f, 0xaca00c83, 0xd8f29e71, 0x44052967, 0x3057bb95,
+ 0x780631ba, 0x0c54a348, 0x90a3145e, 0xe4f186ac},
+};
+const uint32_t kBlock1SkipTable[8][16] = {
+ {0x00000000, 0x79113270, 0xf22264e0, 0x8b335690, 0xe1a8bf31, 0x98b98d41,
+ 0x138adbd1, 0x6a9be9a1, 0xc6bd0893, 0xbfac3ae3, 0x349f6c73, 0x4d8e5e03,
+ 0x2715b7a2, 0x5e0485d2, 0xd537d342, 0xac26e132},
+ {0x00000000, 0x889667d7, 0x14c0b95f, 0x9c56de88, 0x298172be, 0xa1171569,
+ 0x3d41cbe1, 0xb5d7ac36, 0x5302e57c, 0xdb9482ab, 0x47c25c23, 0xcf543bf4,
+ 0x7a8397c2, 0xf215f015, 0x6e432e9d, 0xe6d5494a},
+ {0x00000000, 0xa605caf8, 0x49e7e301, 0xefe229f9, 0x93cfc602, 0x35ca0cfa,
+ 0xda282503, 0x7c2deffb, 0x2273faf5, 0x8476300d, 0x6b9419f4, 0xcd91d30c,
+ 0xb1bc3cf7, 0x17b9f60f, 0xf85bdff6, 0x5e5e150e},
+ {0x00000000, 0x44e7f5ea, 0x89cfebd4, 0xcd281e3e, 0x1673a159, 0x529454b3,
+ 0x9fbc4a8d, 0xdb5bbf67, 0x2ce742b2, 0x6800b758, 0xa528a966, 0xe1cf5c8c,
+ 0x3a94e3eb, 0x7e731601, 0xb35b083f, 0xf7bcfdd5},
+ {0x00000000, 0x59ce8564, 0xb39d0ac8, 0xea538fac, 0x62d66361, 0x3b18e605,
+ 0xd14b69a9, 0x8885eccd, 0xc5acc6c2, 0x9c6243a6, 0x7631cc0a, 0x2fff496e,
+ 0xa77aa5a3, 0xfeb420c7, 0x14e7af6b, 0x4d292a0f},
+ {0x00000000, 0x8eb5fb75, 0x1887801b, 0x96327b6e, 0x310f0036, 0xbfbafb43,
+ 0x2988802d, 0xa73d7b58, 0x621e006c, 0xecabfb19, 0x7a998077, 0xf42c7b02,
+ 0x5311005a, 0xdda4fb2f, 0x4b968041, 0xc5237b34},
+ {0x00000000, 0xc43c00d8, 0x8d947741, 0x49a87799, 0x1ec49873, 0xdaf898ab,
+ 0x9350ef32, 0x576cefea, 0x3d8930e6, 0xf9b5303e, 0xb01d47a7, 0x7421477f,
+ 0x234da895, 0xe771a84d, 0xaed9dfd4, 0x6ae5df0c},
+ {0x00000000, 0x7b1261cc, 0xf624c398, 0x8d36a254, 0xe9a5f1c1, 0x92b7900d,
+ 0x1f813259, 0x64935395, 0xd6a79573, 0xadb5f4bf, 0x208356eb, 0x5b913727,
+ 0x3f0264b2, 0x4410057e, 0xc926a72a, 0xb234c6e6},
+};
+const uint32_t kBlock2SkipTable[8][16] = {
+ {0x00000000, 0x8f158014, 0x1bc776d9, 0x94d2f6cd, 0x378eedb2, 0xb89b6da6,
+ 0x2c499b6b, 0xa35c1b7f, 0x6f1ddb64, 0xe0085b70, 0x74daadbd, 0xfbcf2da9,
+ 0x589336d6, 0xd786b6c2, 0x4354400f, 0xcc41c01b},
+ {0x00000000, 0xde3bb6c8, 0xb99b1b61, 0x67a0ada9, 0x76da4033, 0xa8e1f6fb,
+ 0xcf415b52, 0x117aed9a, 0xedb48066, 0x338f36ae, 0x542f9b07, 0x8a142dcf,
+ 0x9b6ec055, 0x4555769d, 0x22f5db34, 0xfcce6dfc},
+ {0x00000000, 0xde85763d, 0xb8e69a8b, 0x6663ecb6, 0x742143e7, 0xaaa435da,
+ 0xccc7d96c, 0x1242af51, 0xe84287ce, 0x36c7f1f3, 0x50a41d45, 0x8e216b78,
+ 0x9c63c429, 0x42e6b214, 0x24855ea2, 0xfa00289f},
+ {0x00000000, 0xd569796d, 0xaf3e842b, 0x7a57fd46, 0x5b917ea7, 0x8ef807ca,
+ 0xf4affa8c, 0x21c683e1, 0xb722fd4e, 0x624b8423, 0x181c7965, 0xcd750008,
+ 0xecb383e9, 0x39dafa84, 0x438d07c2, 0x96e47eaf},
+ {0x00000000, 0x6ba98c6d, 0xd75318da, 0xbcfa94b7, 0xab4a4745, 0xc0e3cb28,
+ 0x7c195f9f, 0x17b0d3f2, 0x5378f87b, 0x38d17416, 0x842be0a1, 0xef826ccc,
+ 0xf832bf3e, 0x939b3353, 0x2f61a7e4, 0x44c82b89},
+ {0x00000000, 0xa6f1f0f6, 0x480f971d, 0xeefe67eb, 0x901f2e3a, 0x36eedecc,
+ 0xd810b927, 0x7ee149d1, 0x25d22a85, 0x8323da73, 0x6dddbd98, 0xcb2c4d6e,
+ 0xb5cd04bf, 0x133cf449, 0xfdc293a2, 0x5b336354},
+ {0x00000000, 0x4ba4550a, 0x9748aa14, 0xdcecff1e, 0x2b7d22d9, 0x60d977d3,
+ 0xbc3588cd, 0xf791ddc7, 0x56fa45b2, 0x1d5e10b8, 0xc1b2efa6, 0x8a16baac,
+ 0x7d87676b, 0x36233261, 0xeacfcd7f, 0xa16b9875},
+ {0x00000000, 0xadf48b64, 0x5e056039, 0xf3f1eb5d, 0xbc0ac072, 0x11fe4b16,
+ 0xe20fa04b, 0x4ffb2b2f, 0x7df9f615, 0xd00d7d71, 0x23fc962c, 0x8e081d48,
+ 0xc1f33667, 0x6c07bd03, 0x9ff6565e, 0x3202dd3a},
+};
+
+constexpr const ptrdiff_t kPrefetchHorizon = 256;
+
+} // namespace
+
+uint32_t ExtendSse42(uint32_t crc, const uint8_t* data, size_t size) {
+ const uint8_t* p = data;
+ const uint8_t* e = data + size;
+ uint32_t l = crc ^ kCRC32Xor;
+
+#define STEP1 \
+ do { \
+ l = _mm_crc32_u8(l, *p++); \
+ } while (0)
+
+#define STEP4(crc) \
+ do { \
+ crc = _mm_crc32_u32(crc, ReadUint32LE(p)); \
+ p += 4; \
+ } while (0)
+
+#define STEP8(crc, data) \
+ do { \
+ crc = _mm_crc32_u64(crc, ReadUint64LE(data)); \
+ data += 8; \
+ } while (0)
+
+#define STEP8BY3(crc0, crc1, crc2, p0, p1, p2) \
+ do { \
+ STEP8(crc0, p0); \
+ STEP8(crc1, p1); \
+ STEP8(crc2, p2); \
+ } while (0)
+
+#define STEP8X3(crc0, crc1, crc2, bs) \
+ do { \
+ crc0 = _mm_crc32_u64(crc0, ReadUint64LE(p)); \
+ crc1 = _mm_crc32_u64(crc1, ReadUint64LE(p + bs)); \
+ crc2 = _mm_crc32_u64(crc2, ReadUint64LE(p + 2 * bs)); \
+ p += 8; \
+ } while (0)
+
+#define SKIP_BLOCK(crc, tab) \
+ do { \
+ crc = tab[0][crc & 0xf] ^ tab[1][(crc >> 4) & 0xf] ^ \
+ tab[2][(crc >> 8) & 0xf] ^ tab[3][(crc >> 12) & 0xf] ^ \
+ tab[4][(crc >> 16) & 0xf] ^ tab[5][(crc >> 20) & 0xf] ^ \
+ tab[6][(crc >> 24) & 0xf] ^ tab[7][(crc >> 28) & 0xf]; \
+ } while (0)
+
+ // Point x at first 8-byte aligned byte in the buffer. This might be past the
+ // end of the buffer.
+ const uint8_t* x = RoundUp<8>(p);
+ if (x <= e) {
+ // Process bytes p is 8-byte aligned.
+ while (p != x) {
+ STEP1;
+ }
+ }
+
+ // Proccess the data in predetermined block sizes with tables for quickly
+ // combining the checksum. Experimentally it's better to use larger block
+ // sizes where possible so use a hierarchy of decreasing block sizes.
+ uint64_t l64 = l;
+ while ((e - p) >= kGroups * kBlock0Size) {
+ uint64_t l641 = 0;
+ uint64_t l642 = 0;
+ for (int i = 0; i < kBlock0Size; i += 8 * 8) {
+ // Prefetch ahead to hide latency.
+ RequestPrefetch(p + kPrefetchHorizon);
+ RequestPrefetch(p + kBlock0Size + kPrefetchHorizon);
+ RequestPrefetch(p + 2 * kBlock0Size + kPrefetchHorizon);
+
+ // Process 64 bytes at a time.
+ STEP8X3(l64, l641, l642, kBlock0Size);
+ STEP8X3(l64, l641, l642, kBlock0Size);
+ STEP8X3(l64, l641, l642, kBlock0Size);
+ STEP8X3(l64, l641, l642, kBlock0Size);
+ STEP8X3(l64, l641, l642, kBlock0Size);
+ STEP8X3(l64, l641, l642, kBlock0Size);
+ STEP8X3(l64, l641, l642, kBlock0Size);
+ STEP8X3(l64, l641, l642, kBlock0Size);
+ }
+
+ // Combine results.
+ SKIP_BLOCK(l64, kBlock0SkipTable);
+ l64 ^= l641;
+ SKIP_BLOCK(l64, kBlock0SkipTable);
+ l64 ^= l642;
+ p += (kGroups - 1) * kBlock0Size;
+ }
+ while ((e - p) >= kGroups * kBlock1Size) {
+ uint64_t l641 = 0;
+ uint64_t l642 = 0;
+ for (int i = 0; i < kBlock1Size; i += 8) {
+ STEP8X3(l64, l641, l642, kBlock1Size);
+ }
+ SKIP_BLOCK(l64, kBlock1SkipTable);
+ l64 ^= l641;
+ SKIP_BLOCK(l64, kBlock1SkipTable);
+ l64 ^= l642;
+ p += (kGroups - 1) * kBlock1Size;
+ }
+ while ((e - p) >= kGroups * kBlock2Size) {
+ uint64_t l641 = 0;
+ uint64_t l642 = 0;
+ for (int i = 0; i < kBlock2Size; i += 8) {
+ STEP8X3(l64, l641, l642, kBlock2Size);
+ }
+ SKIP_BLOCK(l64, kBlock2SkipTable);
+ l64 ^= l641;
+ SKIP_BLOCK(l64, kBlock2SkipTable);
+ l64 ^= l642;
+ p += (kGroups - 1) * kBlock2Size;
+ }
+
+ // Process bytes 16 at a time
+ while ((e - p) >= 16) {
+ STEP8(l64, p);
+ STEP8(l64, p);
+ }
+
+ l = static_cast<uint32_t>(l64);
+ // Process the last few bytes.
+ while (p != e) {
+ STEP1;
+ }
+#undef SKIP_BLOCK
+#undef STEP8X3
+#undef STEP8BY3
+#undef STEP8
+#undef STEP4
+#undef STEP1
+
+ return l ^ kCRC32Xor;
+}
+
+} // namespace crc32c
+
+#endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
diff --git a/src/crc32c/src/crc32c_sse42.h b/src/crc32c/src/crc32c_sse42.h
new file mode 100644
index 0000000000..95da926632
--- /dev/null
+++ b/src/crc32c/src/crc32c_sse42.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#ifndef CRC32C_CRC32C_SSE42_H_
+#define CRC32C_CRC32C_SSE42_H_
+
+// X86-specific code.
+
+#include <cstddef>
+#include <cstdint>
+
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+// The hardware-accelerated implementation is only enabled for 64-bit builds,
+// because a straightforward 32-bit implementation actually runs slower than the
+// portable version. Most X86 machines are 64-bit nowadays, so it doesn't make
+// much sense to spend time building an optimized hardware-accelerated
+// implementation.
+#if HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+namespace crc32c {
+
+// SSE4.2-accelerated implementation in crc32c_sse42.cc
+uint32_t ExtendSse42(uint32_t crc, const uint8_t* data, size_t count);
+
+} // namespace crc32c
+
+#endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+#endif // CRC32C_CRC32C_SSE42_H_
diff --git a/src/crc32c/src/crc32c_sse42_check.h b/src/crc32c/src/crc32c_sse42_check.h
new file mode 100644
index 0000000000..e7528912a6
--- /dev/null
+++ b/src/crc32c/src/crc32c_sse42_check.h
@@ -0,0 +1,50 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#ifndef CRC32C_CRC32C_SSE42_CHECK_H_
+#define CRC32C_CRC32C_SSE42_CHECK_H_
+
+// X86-specific code checking the availability of SSE4.2 instructions.
+
+#include <cstddef>
+#include <cstdint>
+
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+#if HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+// If the compiler supports SSE4.2, it definitely supports X86.
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+
+namespace crc32c {
+
+inline bool CanUseSse42() {
+ int cpu_info[4];
+ __cpuid(cpu_info, 1);
+ return (cpu_info[2] & (1 << 20)) != 0;
+}
+
+} // namespace crc32c
+
+#else // !defined(_MSC_VER)
+#include <cpuid.h>
+
+namespace crc32c {
+
+inline bool CanUseSse42() {
+ unsigned int eax, ebx, ecx, edx;
+ return __get_cpuid(1, &eax, &ebx, &ecx, &edx) && ((ecx & (1 << 20)) != 0);
+}
+
+} // namespace crc32c
+
+#endif // defined(_MSC_VER)
+
+#endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+#endif // CRC32C_CRC32C_SSE42_CHECK_H_
diff --git a/src/crc32c/src/crc32c_sse42_unittest.cc b/src/crc32c/src/crc32c_sse42_unittest.cc
new file mode 100644
index 0000000000..c73ad8ddd1
--- /dev/null
+++ b/src/crc32c/src/crc32c_sse42_unittest.cc
@@ -0,0 +1,24 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "gtest/gtest.h"
+
+#include "./crc32c_extend_unittests.h"
+#include "./crc32c_sse42.h"
+
+namespace crc32c {
+
+#if HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+struct Sse42TestTraits {
+ static uint32_t Extend(uint32_t crc, const uint8_t* data, size_t count) {
+ return ExtendSse42(crc, data, count);
+ }
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(Sse42, ExtendTest, Sse42TestTraits);
+
+#endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
+
+} // namespace crc32c
diff --git a/src/crc32c/src/crc32c_test_main.cc b/src/crc32c/src/crc32c_test_main.cc
new file mode 100644
index 0000000000..275ee380c6
--- /dev/null
+++ b/src/crc32c/src/crc32c_test_main.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifdef CRC32C_HAVE_CONFIG_H
+#include "crc32c/crc32c_config.h"
+#endif
+
+#include "gtest/gtest.h"
+
+#if CRC32C_TESTS_BUILT_WITH_GLOG
+#include "glog/logging.h"
+#endif // CRC32C_TESTS_BUILT_WITH_GLOG
+
+int main(int argc, char** argv) {
+#if CRC32C_TESTS_BUILT_WITH_GLOG
+ google::InitGoogleLogging(argv[0]);
+ google::InstallFailureSignalHandler();
+#endif // CRC32C_TESTS_BUILT_WITH_GLOG
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/src/crc32c/src/crc32c_unittest.cc b/src/crc32c/src/crc32c_unittest.cc
new file mode 100644
index 0000000000..d6c6af680c
--- /dev/null
+++ b/src/crc32c/src/crc32c_unittest.cc
@@ -0,0 +1,129 @@
+// Copyright 2017 The CRC32C Authors. All rights reserved.
+// 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.
+
+#include "crc32c/crc32c.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+
+#include "gtest/gtest.h"
+
+#include "./crc32c_extend_unittests.h"
+
+TEST(Crc32CTest, Crc32c) {
+ // From rfc3720 section B.4.
+ uint8_t buf[32];
+
+ std::memset(buf, 0, sizeof(buf));
+ EXPECT_EQ(static_cast<uint32_t>(0x8a9136aa),
+ crc32c::Crc32c(buf, sizeof(buf)));
+
+ std::memset(buf, 0xff, sizeof(buf));
+ EXPECT_EQ(static_cast<uint32_t>(0x62a8ab43),
+ crc32c::Crc32c(buf, sizeof(buf)));
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = static_cast<uint8_t>(i);
+ EXPECT_EQ(static_cast<uint32_t>(0x46dd794e),
+ crc32c::Crc32c(buf, sizeof(buf)));
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = static_cast<uint8_t>(31 - i);
+ EXPECT_EQ(static_cast<uint32_t>(0x113fdb5c),
+ crc32c::Crc32c(buf, sizeof(buf)));
+
+ uint8_t data[48] = {
+ 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ EXPECT_EQ(static_cast<uint32_t>(0xd9963a56),
+ crc32c::Crc32c(data, sizeof(data)));
+}
+
+namespace crc32c {
+
+struct ApiTestTraits {
+ static uint32_t Extend(uint32_t crc, const uint8_t* data, size_t count) {
+ return ::crc32c::Extend(crc, data, count);
+ }
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(Api, ExtendTest, ApiTestTraits);
+
+} // namespace crc32c
+
+TEST(CRC32CTest, Crc32cCharPointer) {
+ char buf[32];
+
+ std::memset(buf, 0, sizeof(buf));
+ EXPECT_EQ(static_cast<uint32_t>(0x8a9136aa),
+ crc32c::Crc32c(buf, sizeof(buf)));
+
+ std::memset(buf, 0xff, sizeof(buf));
+ EXPECT_EQ(static_cast<uint32_t>(0x62a8ab43),
+ crc32c::Crc32c(buf, sizeof(buf)));
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = static_cast<char>(i);
+ EXPECT_EQ(static_cast<uint32_t>(0x46dd794e),
+ crc32c::Crc32c(buf, sizeof(buf)));
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = static_cast<char>(31 - i);
+ EXPECT_EQ(static_cast<uint32_t>(0x113fdb5c),
+ crc32c::Crc32c(buf, sizeof(buf)));
+}
+
+TEST(CRC32CTest, Crc32cStdString) {
+ std::string buf;
+ buf.resize(32);
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = static_cast<char>(0x00);
+ EXPECT_EQ(static_cast<uint32_t>(0x8a9136aa), crc32c::Crc32c(buf));
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = '\xff';
+ EXPECT_EQ(static_cast<uint32_t>(0x62a8ab43), crc32c::Crc32c(buf));
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = static_cast<char>(i);
+ EXPECT_EQ(static_cast<uint32_t>(0x46dd794e), crc32c::Crc32c(buf));
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = static_cast<char>(31 - i);
+ EXPECT_EQ(static_cast<uint32_t>(0x113fdb5c), crc32c::Crc32c(buf));
+}
+
+#if __cplusplus > 201402L
+#if __has_include(<string_view>)
+
+TEST(CRC32CTest, Crc32cStdStringView) {
+ uint8_t buf[32];
+ std::string_view view(reinterpret_cast<const char*>(buf), sizeof(buf));
+
+ std::memset(buf, 0, sizeof(buf));
+ EXPECT_EQ(static_cast<uint32_t>(0x8a9136aa), crc32c::Crc32c(view));
+
+ std::memset(buf, 0xff, sizeof(buf));
+ EXPECT_EQ(static_cast<uint32_t>(0x62a8ab43), crc32c::Crc32c(view));
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = static_cast<uint8_t>(i);
+ EXPECT_EQ(static_cast<uint32_t>(0x46dd794e), crc32c::Crc32c(view));
+
+ for (size_t i = 0; i < 32; ++i)
+ buf[i] = static_cast<uint8_t>(31 - i);
+ EXPECT_EQ(static_cast<uint32_t>(0x113fdb5c), crc32c::Crc32c(view));
+}
+
+#endif // __has_include(<string_view>)
+#endif // __cplusplus > 201402L
+
+#define TESTED_EXTEND Extend
+#include "./crc32c_extend_unittests.h"
+#undef TESTED_EXTEND
diff --git a/src/crypto/sha256_shani.cpp b/src/crypto/sha256_shani.cpp
index 92f67710fb..3473f6e39f 100644
--- a/src/crypto/sha256_shani.cpp
+++ b/src/crypto/sha256_shani.cpp
@@ -11,13 +11,11 @@
#include <stdint.h>
#include <immintrin.h>
-
-
namespace {
-const __m128i MASK = _mm_set_epi64x(0x0c0d0e0f08090a0bULL, 0x0405060700010203ULL);
-const __m128i INIT0 = _mm_set_epi64x(0x6a09e667bb67ae85ull, 0x510e527f9b05688cull);
-const __m128i INIT1 = _mm_set_epi64x(0x3c6ef372a54ff53aull, 0x1f83d9ab5be0cd19ull);
+alignas(__m128i) const uint8_t MASK[16] = {0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c};
+alignas(__m128i) const uint8_t INIT0[16] = {0x8c, 0x68, 0x05, 0x9b, 0x7f, 0x52, 0x0e, 0x51, 0x85, 0xae, 0x67, 0xbb, 0x67, 0xe6, 0x09, 0x6a};
+alignas(__m128i) const uint8_t INIT1[16] = {0x19, 0xcd, 0xe0, 0x5b, 0xab, 0xd9, 0x83, 0x1f, 0x3a, 0xf5, 0x4f, 0xa5, 0x72, 0xf3, 0x6e, 0x3c};
void inline __attribute__((always_inline)) QuadRound(__m128i& state0, __m128i& state1, uint64_t k1, uint64_t k0)
{
@@ -67,12 +65,12 @@ void inline __attribute__((always_inline)) Unshuffle(__m128i& s0, __m128i& s1)
__m128i inline __attribute__((always_inline)) Load(const unsigned char* in)
{
- return _mm_shuffle_epi8(_mm_loadu_si128((const __m128i*)in), MASK);
+ return _mm_shuffle_epi8(_mm_loadu_si128((const __m128i*)in), _mm_load_si128((const __m128i*)MASK));
}
void inline __attribute__((always_inline)) Save(unsigned char* out, __m128i s)
{
- _mm_storeu_si128((__m128i*)out, _mm_shuffle_epi8(s, MASK));
+ _mm_storeu_si128((__m128i*)out, _mm_shuffle_epi8(s, _mm_load_si128((const __m128i*)MASK)));
}
}
@@ -149,8 +147,8 @@ void Transform_2way(unsigned char* out, const unsigned char* in)
__m128i bm0, bm1, bm2, bm3, bs0, bs1, bso0, bso1;
/* Transform 1 */
- bs0 = as0 = INIT0;
- bs1 = as1 = INIT1;
+ bs0 = as0 = _mm_load_si128((const __m128i*)INIT0);
+ bs1 = as1 = _mm_load_si128((const __m128i*)INIT1);
am0 = Load(in);
bm0 = Load(in + 64);
QuadRound(as0, as1, am0, 0xe9b5dba5b5c0fbcfull, 0x71374491428a2f98ull);
@@ -219,10 +217,10 @@ void Transform_2way(unsigned char* out, const unsigned char* in)
ShiftMessageC(bm1, bm2, bm3);
QuadRound(as0, as1, am3, 0xc67178f2bef9A3f7ull, 0xa4506ceb90befffaull);
QuadRound(bs0, bs1, bm3, 0xc67178f2bef9A3f7ull, 0xa4506ceb90befffaull);
- as0 = _mm_add_epi32(as0, INIT0);
- bs0 = _mm_add_epi32(bs0, INIT0);
- as1 = _mm_add_epi32(as1, INIT1);
- bs1 = _mm_add_epi32(bs1, INIT1);
+ as0 = _mm_add_epi32(as0, _mm_load_si128((const __m128i*)INIT0));
+ bs0 = _mm_add_epi32(bs0, _mm_load_si128((const __m128i*)INIT0));
+ as1 = _mm_add_epi32(as1, _mm_load_si128((const __m128i*)INIT1));
+ bs1 = _mm_add_epi32(bs1, _mm_load_si128((const __m128i*)INIT1));
/* Transform 2 */
aso0 = as0;
@@ -275,8 +273,8 @@ void Transform_2way(unsigned char* out, const unsigned char* in)
bm1 = bs1;
/* Transform 3 */
- bs0 = as0 = INIT0;
- bs1 = as1 = INIT1;
+ bs0 = as0 = _mm_load_si128((const __m128i*)INIT0);
+ bs1 = as1 = _mm_load_si128((const __m128i*)INIT1);
QuadRound(as0, as1, am0, 0xe9b5dba5B5c0fbcfull, 0x71374491428a2f98ull);
QuadRound(bs0, bs1, bm0, 0xe9b5dba5B5c0fbcfull, 0x71374491428a2f98ull);
QuadRound(as0, as1, am1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull);
@@ -339,10 +337,10 @@ void Transform_2way(unsigned char* out, const unsigned char* in)
ShiftMessageC(bm1, bm2, bm3);
QuadRound(as0, as1, am3, 0xc67178f2bef9a3f7ull, 0xa4506ceb90befffaull);
QuadRound(bs0, bs1, bm3, 0xc67178f2bef9a3f7ull, 0xa4506ceb90befffaull);
- as0 = _mm_add_epi32(as0, INIT0);
- bs0 = _mm_add_epi32(bs0, INIT0);
- as1 = _mm_add_epi32(as1, INIT1);
- bs1 = _mm_add_epi32(bs1, INIT1);
+ as0 = _mm_add_epi32(as0, _mm_load_si128((const __m128i*)INIT0));
+ bs0 = _mm_add_epi32(bs0, _mm_load_si128((const __m128i*)INIT0));
+ as1 = _mm_add_epi32(as1, _mm_load_si128((const __m128i*)INIT1));
+ bs1 = _mm_add_epi32(bs1, _mm_load_si128((const __m128i*)INIT1));
/* Extract hash into out */
Unshuffle(as0, as1);
diff --git a/src/cuckoocache.h b/src/cuckoocache.h
index 4ad5818cdc..2daf676c4a 100644
--- a/src/cuckoocache.h
+++ b/src/cuckoocache.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_CUCKOOCACHE_H
#define BITCOIN_CUCKOOCACHE_H
+#include <algorithm> // std::find
#include <array>
#include <atomic>
#include <cmath>
diff --git a/src/flatfile.h b/src/flatfile.h
index 374ceff411..60b3503cc3 100644
--- a/src/flatfile.h
+++ b/src/flatfile.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -20,7 +20,7 @@ struct FlatFilePos
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED));
+ READWRITE(VARINT_MODE(nFile, VarIntMode::NONNEGATIVE_SIGNED));
READWRITE(VARINT(nPos));
}
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index ff75789223..60c4d06f12 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -174,7 +174,7 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &)
/* Deter brute-forcing
If this results in a DoS the user really
shouldn't have their RPC port exposed. */
- MilliSleep(250);
+ UninterruptibleSleep(std::chrono::milliseconds{250});
req->WriteHeader("WWW-Authenticate", WWW_AUTH_HEADER_DATA);
req->WriteReply(HTTP_UNAUTHORIZED);
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 0e13b85806..176284d103 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -189,7 +189,7 @@ static bool InitHTTPAllowList()
}
/** HTTP request method as string - use for logging only */
-static std::string RequestMethodString(HTTPRequest::RequestMethod m)
+std::string RequestMethodString(HTTPRequest::RequestMethod m)
{
switch (m) {
case HTTPRequest::GET:
@@ -236,7 +236,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) {
LogPrint(BCLog::HTTP, "HTTP request from %s rejected: Unknown HTTP request method\n",
hreq->GetPeer().ToString());
- hreq->WriteReply(HTTP_BADMETHOD);
+ hreq->WriteReply(HTTP_BAD_METHOD);
return;
}
@@ -268,10 +268,10 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
item.release(); /* if true, queue took ownership */
else {
LogPrintf("WARNING: request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting\n");
- item->req->WriteReply(HTTP_INTERNAL, "Work queue depth exceeded");
+ item->req->WriteReply(HTTP_INTERNAL_SERVER_ERROR, "Work queue depth exceeded");
}
} else {
- hreq->WriteReply(HTTP_NOTFOUND);
+ hreq->WriteReply(HTTP_NOT_FOUND);
}
}
@@ -510,16 +510,16 @@ void HTTPEvent::trigger(struct timeval* tv)
else
evtimer_add(ev, tv); // trigger after timeval passed
}
-HTTPRequest::HTTPRequest(struct evhttp_request* _req) : req(_req),
- replySent(false)
+HTTPRequest::HTTPRequest(struct evhttp_request* _req, bool _replySent) : req(_req), replySent(_replySent)
{
}
+
HTTPRequest::~HTTPRequest()
{
if (!replySent) {
// Keep track of whether reply was sent to avoid request leaks
LogPrintf("%s: Unhandled request\n", __func__);
- WriteReply(HTTP_INTERNAL, "Unhandled request");
+ WriteReply(HTTP_INTERNAL_SERVER_ERROR, "Unhandled request");
}
// evhttpd cleans up the request, as long as a reply was sent.
}
diff --git a/src/httpserver.h b/src/httpserver.h
index 46820e6aee..97cd63778a 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -60,7 +60,7 @@ private:
bool replySent;
public:
- explicit HTTPRequest(struct evhttp_request* req);
+ explicit HTTPRequest(struct evhttp_request* req, bool replySent = false);
~HTTPRequest();
enum RequestMethod {
diff --git a/src/index/base.cpp b/src/index/base.cpp
index dcb8e99fc1..7bff463f5b 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -188,8 +188,7 @@ bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_ti
return true;
}
-void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
- const std::vector<CTransactionRef>& txn_conflicted)
+void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex)
{
if (!m_synced) {
return;
@@ -270,7 +269,7 @@ void BaseIndex::ChainStateFlushed(const CBlockLocator& locator)
Commit();
}
-bool BaseIndex::BlockUntilSyncedToCurrentChain()
+bool BaseIndex::BlockUntilSyncedToCurrentChain() const
{
AssertLockNotHeld(cs_main);
diff --git a/src/index/base.h b/src/index/base.h
index d0088d9c9a..3fab810bb2 100644
--- a/src/index/base.h
+++ b/src/index/base.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -64,8 +64,7 @@ private:
bool Commit();
protected:
- void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
- const std::vector<CTransactionRef>& txn_conflicted) override;
+ void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;
void ChainStateFlushed(const CBlockLocator& locator) override;
@@ -97,7 +96,7 @@ public:
/// sync once and only needs to process blocks in the ValidationInterface
/// queue. If the index is catching up from far behind, this method does
/// not block and immediately returns false.
- bool BlockUntilSyncedToCurrentChain();
+ bool BlockUntilSyncedToCurrentChain() const;
void Interrupt();
diff --git a/src/indirectmap.h b/src/indirectmap.h
index 76da4a6bd5..a9f4b0b9f2 100644
--- a/src/indirectmap.h
+++ b/src/indirectmap.h
@@ -1,10 +1,12 @@
-// Copyright (c) 2016 The Bitcoin Core developers
+// Copyright (c) 2016-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_INDIRECTMAP_H
#define BITCOIN_INDIRECTMAP_H
+#include <map>
+
template <class T>
struct DereferencingComparator { bool operator()(const T a, const T b) const { return *a < *b; } };
diff --git a/src/init.cpp b/src/init.cpp
index e1a02edb96..a213dacbe0 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -47,12 +47,11 @@
#include <txdb.h>
#include <txmempool.h>
#include <ui_interface.h>
+#include <util/asmap.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <util/threadnames.h>
#include <util/translation.h>
-#include <util/validation.h>
-#include <util/asmap.h>
#include <validation.h>
#include <hash.h>
@@ -74,6 +73,7 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
+#include <boost/signals2/signal.hpp>
#include <boost/thread.hpp>
#if ENABLE_ZMQ
@@ -87,10 +87,6 @@ static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
-// Dump addresses to banlist.dat every 15 minutes (900s)
-static constexpr int DUMP_BANS_INTERVAL = 60 * 15;
-
-
#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
// accessing block files don't count towards the fd_set size limit
@@ -157,7 +153,6 @@ NODISCARD static bool CreatePidFile()
static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
static boost::thread_group threadGroup;
-static CScheduler scheduler;
void Interrupt(NodeContext& node)
{
@@ -202,12 +197,26 @@ void Shutdown(NodeContext& node)
// Because these depend on each-other, we make sure that neither can be
// using the other before destroying them.
if (node.peer_logic) UnregisterValidationInterface(node.peer_logic.get());
- if (node.connman) node.connman->Stop();
+ // Follow the lock order requirements:
+ // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount
+ // which locks cs_vNodes.
+ // * ProcessMessage locks cs_main and g_cs_orphans before indirectly calling ForEachNode which
+ // locks cs_vNodes.
+ // * CConnman::Stop calls DeleteNode, which calls FinalizeNode, which locks cs_main and calls
+ // EraseOrphansFor, which locks g_cs_orphans.
+ //
+ // Thus the implicit locking order requirement is: (1) cs_main, (2) g_cs_orphans, (3) cs_vNodes.
+ if (node.connman) {
+ node.connman->StopThreads();
+ LOCK2(::cs_main, ::g_cs_orphans);
+ node.connman->StopNodes();
+ }
StopTorControl();
// After everything has been shut down, but before things get flushed, stop the
// CScheduler/checkqueue threadGroup
+ if (node.scheduler) node.scheduler->stop();
threadGroup.interrupt_all();
threadGroup.join_all();
@@ -234,13 +243,12 @@ void Shutdown(NodeContext& node)
}
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
- //
- // g_chainstate is referenced here directly (instead of ::ChainstateActive()) because it
- // may not have been initialized yet.
{
LOCK(cs_main);
- if (g_chainstate && g_chainstate->CanFlushToDisk()) {
- g_chainstate->ForceFlushStateToDisk();
+ for (CChainState* chainstate : g_chainman.GetAll()) {
+ if (chainstate->CanFlushToDisk()) {
+ chainstate->ForceFlushStateToDisk();
+ }
}
}
@@ -264,9 +272,11 @@ void Shutdown(NodeContext& node)
{
LOCK(cs_main);
- if (g_chainstate && g_chainstate->CanFlushToDisk()) {
- g_chainstate->ForceFlushStateToDisk();
- g_chainstate->ResetCoinsViews();
+ for (CChainState* chainstate : g_chainman.GetAll()) {
+ if (chainstate->CanFlushToDisk()) {
+ chainstate->ForceFlushStateToDisk();
+ chainstate->ResetCoinsViews();
+ }
}
pblocktree.reset();
}
@@ -282,6 +292,15 @@ void Shutdown(NodeContext& node)
}
#endif
+ node.chain_clients.clear();
+ UnregisterAllValidationInterfaces();
+ GetMainSignals().UnregisterBackgroundSignalScheduler();
+ globalVerifyHandle.reset();
+ ECC_Stop();
+ node.args = nullptr;
+ if (node.mempool) node.mempool = nullptr;
+ node.scheduler.reset();
+
try {
if (!fs::remove(GetPidFile())) {
LogPrintf("%s: Unable to remove PID file: File does not exist\n", __func__);
@@ -289,12 +308,7 @@ void Shutdown(NodeContext& node)
} catch (const fs::filesystem_error& e) {
LogPrintf("%s: Unable to remove PID file: %s\n", __func__, fsbridge::get_filesystem_error_message(e));
}
- node.chain_clients.clear();
- UnregisterAllValidationInterfaces();
- GetMainSignals().UnregisterBackgroundSignalScheduler();
- globalVerifyHandle.reset();
- ECC_Stop();
- if (node.mempool) node.mempool = nullptr;
+
LogPrintf("%s: done\n", __func__);
}
@@ -347,8 +361,11 @@ static void OnRPCStopped()
LogPrint(BCLog::RPC, "RPC stopped.\n");
}
-void SetupServerArgs()
+void SetupServerArgs(NodeContext& node)
{
+ assert(!node.args);
+ node.args = &gArgs;
+
SetupHelpOptions(gArgs);
gArgs.AddArg("-help-debug", "Print help message with debugging options and exit", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); // server-only for now
@@ -375,7 +392,7 @@ void SetupServerArgs()
gArgs.AddArg("-blocknotify=<cmd>", "Execute command when the best block changes (%s in cmd is replaced by block hash)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#endif
gArgs.AddArg("-blockreconstructionextratxn=<n>", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- gArgs.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Transactions from the wallet, RPC and relay whitelisted inbound peers are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Automatic broadcast and rebroadcast of any transactions from inbound peers is disabled, unless '-whitelistforcerelay' is '1', in which case whitelisted peers' transactions will be relayed. RPC transactions are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
@@ -409,6 +426,7 @@ void SetupServerArgs()
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-addnode=<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.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-asmap=<file>", strprintf("Specify asn mapping used for bucketing of the peers (default: %s). Relative paths will be prefixed by the net-specific datadir location.", DEFAULT_ASMAP_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
gArgs.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
gArgs.AddArg("-bantime=<n>", strprintf("Number of seconds to keep misbehaving peers from reconnecting (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
gArgs.AddArg("-bind=<addr>", "Bind to given address and always listen on it. Use [host]:port notation for IPv6", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
@@ -437,7 +455,6 @@ void SetupServerArgs()
gArgs.AddArg("-peertimeout=<n>", strprintf("Specify p2p connection timeout in seconds. This option determines the amount of time a peer may be inactive before the connection to it is dropped. (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
gArgs.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control port to use if onion listening enabled (default: %s)", DEFAULT_TOR_CONTROL), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
gArgs.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::CONNECTION);
- gArgs.AddArg("-asmap=<file>", "Specify asn mapping used for bucketing of the peers. Path should be relative to the -datadir path.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#ifdef USE_UPNP
#if USE_UPNP
gArgs.AddArg("-upnp", "Use UPnP to map the listening port (default: 1 when listening and no -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@@ -450,7 +467,7 @@ void SetupServerArgs()
gArgs.AddArg("-whitebind=<[permissions@]addr>", "Bind to given address and whitelist peers connecting to it. "
"Use [host]:port notation for IPv6. Allowed permissions are bloomfilter (allow requesting BIP37 filtered blocks and transactions), "
"noban (do not ban for misbehavior), "
- "forcerelay (relay even non-standard transactions), "
+ "forcerelay (relay transactions that are already in the mempool; implies relay), "
"relay (relay even in -blocksonly mode), "
"and mempool (allow requesting BIP35 mempool contents). "
"Specify multiple permissions separated by commas (default: noban,mempool,relay). Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@@ -503,11 +520,16 @@ void SetupServerArgs()
gArgs.AddArg("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-addrmantest", "Allows to test address relay on localhost", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). "
- "If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + ListLogCategories() + ".", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ "If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + LogInstance().LogCategoriesString() + ".",
+ ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-debugexclude=<category>", strprintf("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+#ifdef HAVE_THREAD_LOCAL
gArgs.AddArg("-logthreadnames", strprintf("Prepend debug output with name of the originating thread (only available on platforms supporting thread_local) (default: %u)", DEFAULT_LOGTHREADNAMES), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+#else
+ hidden_args.emplace_back("-logthreadnames");
+#endif
gArgs.AddArg("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-mocktime=<n>", "Replace actual time with " + UNIX_EPOCH_TIME + " (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
@@ -527,7 +549,7 @@ void SetupServerArgs()
gArgs.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-whitelistforcerelay", strprintf("Add 'forcerelay' permission to whitelisted inbound peers with default permissions. This will relay transactions even if the transactions were already in the mempool or violate local relay policy. (default: %d)", DEFAULT_WHITELISTFORCERELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
+ gArgs.AddArg("-whitelistforcerelay", strprintf("Add 'forcerelay' permission to whitelisted inbound peers with default permissions. This will relay transactions even if the transactions were already in the mempool. (default: %d)", DEFAULT_WHITELISTFORCERELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-whitelistrelay", strprintf("Add 'relay' permission to whitelisted inbound peers with default permissions. This will accept relayed transactions even when not relaying transactions (default: %d)", DEFAULT_WHITELISTRELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
@@ -564,13 +586,12 @@ void SetupServerArgs()
std::string LicenseInfo()
{
const std::string URL_SOURCE_CODE = "<https://github.com/bitcoin/bitcoin>";
- const std::string URL_WEBSITE = "<https://bitcoincore.org>";
return CopyrightHolders(strprintf(_("Copyright (C) %i-%i").translated, 2009, COPYRIGHT_YEAR) + " ") + "\n" +
"\n" +
strprintf(_("Please contribute if you find %s useful. "
"Visit %s for further information about the software.").translated,
- PACKAGE_NAME, URL_WEBSITE) +
+ PACKAGE_NAME, "<" PACKAGE_URL ">") +
"\n" +
strprintf(_("The source code is available from %s.").translated,
URL_SOURCE_CODE) +
@@ -708,11 +729,17 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
}
// scan for better chains in the block chain database, that are not yet connected in the active best chain
- BlockValidationState state;
- if (!ActivateBestChain(state, chainparams)) {
- LogPrintf("Failed to connect best block (%s)\n", FormatStateMessage(state));
- StartShutdown();
- return;
+
+ // We can't hold cs_main during ActivateBestChain even though we're accessing
+ // the g_chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve
+ // the relevant pointers before the ABC call.
+ for (CChainState* chainstate : WITH_LOCK(::cs_main, return g_chainman.GetAll())) {
+ BlockValidationState state;
+ if (!chainstate->ActivateBestChain(state, chainparams, nullptr)) {
+ LogPrintf("Failed to connect best block (%s)\n", state.ToString());
+ StartShutdown();
+ return;
+ }
}
if (gArgs.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) {
@@ -840,7 +867,9 @@ void InitLogging()
LogInstance().m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false));
LogInstance().m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
LogInstance().m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
+#ifdef HAVE_THREAD_LOCAL
LogInstance().m_log_threadnames = gArgs.GetBoolArg("-logthreadnames", DEFAULT_LOGTHREADNAMES);
+#endif
fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);
@@ -1268,16 +1297,19 @@ bool AppInitMain(NodeContext& node)
}
}
+ assert(!node.scheduler);
+ node.scheduler = MakeUnique<CScheduler>();
+
// Start the lightweight task scheduler thread
- CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
+ CScheduler::Function serviceLoop = [&node]{ node.scheduler->serviceQueue(); };
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
// Gather some entropy once per minute.
- scheduler.scheduleEvery([]{
+ node.scheduler->scheduleEvery([]{
RandAddPeriodic();
- }, 60000);
+ }, std::chrono::minutes{1});
- GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
+ GetMainSignals().RegisterBackgroundSignalScheduler(*node.scheduler);
// Create client interfaces for wallets that are supposed to be loaded
// according to -wallet and -disablewallet options. This only constructs
@@ -1326,8 +1358,12 @@ bool AppInitMain(NodeContext& node)
node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, gArgs.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
assert(!node.connman);
node.connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max())));
+ // 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.mempool);
+ node.mempool = &::mempool;
- node.peer_logic.reset(new PeerLogicValidation(node.connman.get(), node.banman.get(), scheduler));
+ node.peer_logic.reset(new PeerLogicValidation(node.connman.get(), node.banman.get(), *node.scheduler, *node.mempool));
RegisterValidationInterface(node.peer_logic.get());
// sanitize comments per BIP-0014, format user agent and check total size
@@ -1416,6 +1452,31 @@ bool AppInitMain(NodeContext& node)
return InitError(ResolveErrMsg("externalip", strAddr));
}
+ // Read asmap file if configured
+ if (gArgs.IsArgSet("-asmap")) {
+ fs::path asmap_path = fs::path(gArgs.GetArg("-asmap", ""));
+ if (asmap_path.empty()) {
+ asmap_path = DEFAULT_ASMAP_FILENAME;
+ }
+ if (!asmap_path.is_absolute()) {
+ asmap_path = GetDataDir() / asmap_path;
+ }
+ if (!fs::exists(asmap_path)) {
+ InitError(strprintf(_("Could not find asmap file %s").translated, asmap_path));
+ return false;
+ }
+ std::vector<bool> asmap = CAddrMan::DecodeAsmap(asmap_path);
+ if (asmap.size() == 0) {
+ InitError(strprintf(_("Could not parse asmap file %s").translated, asmap_path));
+ return false;
+ }
+ const uint256 asmap_version = SerializeHash(asmap);
+ node.connman->SetAsmap(std::move(asmap));
+ LogPrintf("Using asmap version %s for IP bucketing\n", asmap_version.ToString());
+ } else {
+ LogPrintf("Using /16 prefix for IP bucketing\n");
+ }
+
#if ENABLE_ZMQ
g_zmq_notification_interface = CZMQNotificationInterface::Create();
@@ -1470,17 +1531,18 @@ bool AppInitMain(NodeContext& node)
bool fLoaded = false;
while (!fLoaded && !ShutdownRequested()) {
bool fReset = fReindex;
+ auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
+ return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull();
+ };
std::string strLoadError;
uiInterface.InitMessage(_("Loading block index...").translated);
do {
const int64_t load_block_index_start_time = GetTimeMillis();
- bool is_coinsview_empty;
try {
LOCK(cs_main);
- // This statement makes ::ChainstateActive() usable.
- g_chainstate = MakeUnique<CChainState>();
+ g_chainman.InitializeChainstate();
UnloadBlockIndex();
// new CBlockTreeDB tries to delete the existing file, which
@@ -1533,43 +1595,53 @@ bool AppInitMain(NodeContext& node)
// At this point we're either in reindex or we've loaded a useful
// block tree into BlockIndex()!
- ::ChainstateActive().InitCoinsDB(
- /* cache_size_bytes */ nCoinDBCache,
- /* in_memory */ false,
- /* should_wipe */ fReset || fReindexChainState);
-
- ::ChainstateActive().CoinsErrorCatcher().AddReadErrCallback([]() {
- uiInterface.ThreadSafeMessageBox(
- _("Error reading from database, shutting down.").translated,
- "", CClientUIInterface::MSG_ERROR);
- });
-
- // If necessary, upgrade from older database format.
- // This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
- if (!::ChainstateActive().CoinsDB().Upgrade()) {
- strLoadError = _("Error upgrading chainstate database").translated;
- break;
- }
-
- // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
- if (!::ChainstateActive().ReplayBlocks(chainparams)) {
- strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.").translated;
- break;
- }
-
- // The on-disk coinsdb is now in a good state, create the cache
- ::ChainstateActive().InitCoinsCache();
- assert(::ChainstateActive().CanFlushToDisk());
+ bool failed_chainstate_init = false;
+
+ for (CChainState* chainstate : g_chainman.GetAll()) {
+ LogPrintf("Initializing chainstate %s\n", chainstate->ToString());
+ chainstate->InitCoinsDB(
+ /* cache_size_bytes */ nCoinDBCache,
+ /* in_memory */ false,
+ /* should_wipe */ fReset || fReindexChainState);
+
+ chainstate->CoinsErrorCatcher().AddReadErrCallback([]() {
+ uiInterface.ThreadSafeMessageBox(
+ _("Error reading from database, shutting down.").translated,
+ "", CClientUIInterface::MSG_ERROR);
+ });
+
+ // If necessary, upgrade from older database format.
+ // This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
+ if (!chainstate->CoinsDB().Upgrade()) {
+ strLoadError = _("Error upgrading chainstate database").translated;
+ failed_chainstate_init = true;
+ break;
+ }
- is_coinsview_empty = fReset || fReindexChainState ||
- ::ChainstateActive().CoinsTip().GetBestBlock().IsNull();
- if (!is_coinsview_empty) {
- // LoadChainTip initializes the chain based on CoinsTip()'s best block
- if (!::ChainstateActive().LoadChainTip(chainparams)) {
- strLoadError = _("Error initializing block database").translated;
+ // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
+ if (!chainstate->ReplayBlocks(chainparams)) {
+ strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.").translated;
+ failed_chainstate_init = true;
break;
}
- assert(::ChainActive().Tip() != nullptr);
+
+ // The on-disk coinsdb is now in a good state, create the cache
+ chainstate->InitCoinsCache();
+ assert(chainstate->CanFlushToDisk());
+
+ if (!is_coinsview_empty(chainstate)) {
+ // LoadChainTip initializes the chain based on CoinsTip()'s best block
+ if (!chainstate->LoadChainTip(chainparams)) {
+ strLoadError = _("Error initializing block database").translated;
+ failed_chainstate_init = true;
+ break; // out of the per-chainstate loop
+ }
+ assert(chainstate->m_chain.Tip() != nullptr);
+ }
+ }
+
+ if (failed_chainstate_init) {
+ break; // out of the chainstate activation do-while
}
} catch (const std::exception& e) {
LogPrintf("%s\n", e.what());
@@ -1577,49 +1649,76 @@ bool AppInitMain(NodeContext& node)
break;
}
- if (!fReset) {
- // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
- // It both disconnects blocks based on ::ChainActive(), and drops block data in
- // BlockIndex() based on lack of available witness data.
- uiInterface.InitMessage(_("Rewinding blocks...").translated);
- if (!RewindBlockIndex(chainparams)) {
- strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain").translated;
- break;
+ bool failed_rewind{false};
+ // Can't hold cs_main while calling RewindBlockIndex, so retrieve the relevant
+ // chainstates beforehand.
+ for (CChainState* chainstate : WITH_LOCK(::cs_main, return g_chainman.GetAll())) {
+ if (!fReset) {
+ // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
+ // It both disconnects blocks based on the chainstate, and drops block data in
+ // BlockIndex() based on lack of available witness data.
+ uiInterface.InitMessage(_("Rewinding blocks...").translated);
+ if (!chainstate->RewindBlockIndex(chainparams)) {
+ strLoadError = _(
+ "Unable to rewind the database to a pre-fork state. "
+ "You will need to redownload the blockchain").translated;
+ failed_rewind = true;
+ break; // out of the per-chainstate loop
+ }
}
}
+ if (failed_rewind) {
+ break; // out of the chainstate activation do-while
+ }
+
+ bool failed_verification = false;
+
try {
LOCK(cs_main);
- if (!is_coinsview_empty) {
- uiInterface.InitMessage(_("Verifying blocks...").translated);
- if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
- LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n",
- MIN_BLOCKS_TO_KEEP);
- }
-
- CBlockIndex* tip = ::ChainActive().Tip();
- RPCNotifyBlockChange(true, tip);
- if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
- strLoadError = _("The block database contains a block which appears to be from the future. "
- "This may be due to your computer's date and time being set incorrectly. "
- "Only rebuild the block database if you are sure that your computer's date and time are correct").translated;
- break;
- }
- if (!CVerifyDB().VerifyDB(chainparams, &::ChainstateActive().CoinsDB(), gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
- gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
- strLoadError = _("Corrupted block database detected").translated;
- break;
+ for (CChainState* chainstate : g_chainman.GetAll()) {
+ if (!is_coinsview_empty(chainstate)) {
+ uiInterface.InitMessage(_("Verifying blocks...").translated);
+ if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
+ LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n",
+ MIN_BLOCKS_TO_KEEP);
+ }
+
+ const CBlockIndex* tip = chainstate->m_chain.Tip();
+ RPCNotifyBlockChange(true, tip);
+ if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
+ strLoadError = _("The block database contains a block which appears to be from the future. "
+ "This may be due to your computer's date and time being set incorrectly. "
+ "Only rebuild the block database if you are sure that your computer's date and time are correct").translated;
+ failed_verification = true;
+ break;
+ }
+
+ // Only verify the DB of the active chainstate. This is fixed in later
+ // work when we allow VerifyDB to be parameterized by chainstate.
+ if (&::ChainstateActive() == chainstate &&
+ !CVerifyDB().VerifyDB(
+ chainparams, &chainstate->CoinsDB(),
+ gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
+ gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
+ strLoadError = _("Corrupted block database detected").translated;
+ failed_verification = true;
+ break;
+ }
}
}
} catch (const std::exception& e) {
LogPrintf("%s\n", e.what());
strLoadError = _("Error opening block database").translated;
+ failed_verification = true;
break;
}
- fLoaded = true;
- LogPrintf(" block index %15dms\n", GetTimeMillis() - load_block_index_start_time);
+ if (!failed_verification) {
+ fLoaded = true;
+ LogPrintf(" block index %15dms\n", GetTimeMillis() - load_block_index_start_time);
+ }
} while(false);
if (!fLoaded && !ShutdownRequested()) {
@@ -1650,11 +1749,6 @@ bool AppInitMain(NodeContext& node)
return false;
}
- // Now that the chain state is loaded, 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.mempool);
- node.mempool = &::mempool;
-
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.
@@ -1688,8 +1782,11 @@ bool AppInitMain(NodeContext& node)
LogPrintf("Unsetting NODE_NETWORK on prune mode\n");
nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK);
if (!fReindex) {
- uiInterface.InitMessage(_("Pruning blockstore...").translated);
- ::ChainstateActive().PruneAndFlush();
+ LOCK(cs_main);
+ for (CChainState* chainstate : g_chainman.GetAll()) {
+ uiInterface.InitMessage(_("Pruning blockstore...").translated);
+ chainstate->PruneAndFlush();
+ }
}
}
@@ -1819,42 +1916,23 @@ bool AppInitMain(NodeContext& node)
connOptions.m_specified_outgoing = connect;
}
}
- if (!node.connman->Start(scheduler, connOptions)) {
+ if (!node.connman->Start(*node.scheduler, connOptions)) {
return false;
}
- // Read asmap file if configured
- if (gArgs.IsArgSet("-asmap")) {
- std::string asmap_file = gArgs.GetArg("-asmap", "");
- if (asmap_file.empty()) {
- asmap_file = DEFAULT_ASMAP_FILENAME;
- }
- const fs::path asmap_path = GetDataDir() / asmap_file;
- std::vector<bool> asmap = CAddrMan::DecodeAsmap(asmap_path);
- if (asmap.size() == 0) {
- InitError(strprintf(_("Could not find or parse specified asmap: '%s'").translated, asmap_path));
- return false;
- }
- node.connman->SetAsmap(asmap);
- const uint256 asmap_version = SerializeHash(asmap);
- LogPrintf("Using asmap version %s for IP bucketing.\n", asmap_version.ToString());
- } else {
- LogPrintf("Using /16 prefix for IP bucketing.\n");
- }
-
// ********************************************************* Step 13: finished
SetRPCWarmupFinished();
uiInterface.InitMessage(_("Done loading").translated);
for (const auto& client : node.chain_clients) {
- client->start(scheduler);
+ client->start(*node.scheduler);
}
BanMan* banman = node.banman.get();
- scheduler.scheduleEvery([banman]{
+ node.scheduler->scheduleEvery([banman]{
banman->DumpBanlist();
- }, DUMP_BANS_INTERVAL * 1000);
+ }, DUMP_BANS_INTERVAL);
return true;
}
diff --git a/src/init.h b/src/init.h
index f74ae5a47a..ef568b6f38 100644
--- a/src/init.h
+++ b/src/init.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -54,9 +54,9 @@ bool AppInitLockDataDirectory();
bool AppInitMain(NodeContext& node);
/**
- * Setup the arguments for gArgs
+ * Register all arguments with the ArgsManager
*/
-void SetupServerArgs();
+void SetupServerArgs(NodeContext& node);
/** Returns licensing information (for -version) */
std::string LicenseInfo();
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
index 643bb58d56..c5262e4bc0 100644
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -38,157 +38,68 @@
namespace interfaces {
namespace {
-class LockImpl : public Chain::Lock, public UniqueLock<RecursiveMutex>
+bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock)
{
- Optional<int> getHeight() override
- {
- LockAssertion lock(::cs_main);
- int height = ::ChainActive().Height();
- if (height >= 0) {
- return height;
- }
- return nullopt;
- }
- Optional<int> getBlockHeight(const uint256& hash) override
- {
- LockAssertion lock(::cs_main);
- CBlockIndex* block = LookupBlockIndex(hash);
- if (block && ::ChainActive().Contains(block)) {
- return block->nHeight;
- }
- return nullopt;
- }
- uint256 getBlockHash(int height) override
- {
- LockAssertion lock(::cs_main);
- CBlockIndex* block = ::ChainActive()[height];
- assert(block != nullptr);
- return block->GetBlockHash();
- }
- int64_t getBlockTime(int height) override
- {
- LockAssertion lock(::cs_main);
- CBlockIndex* block = ::ChainActive()[height];
- assert(block != nullptr);
- return block->GetBlockTime();
- }
- int64_t getBlockMedianTimePast(int height) override
- {
- LockAssertion lock(::cs_main);
- CBlockIndex* block = ::ChainActive()[height];
- assert(block != nullptr);
- return block->GetMedianTimePast();
- }
- bool haveBlockOnDisk(int height) override
- {
- LockAssertion lock(::cs_main);
- CBlockIndex* block = ::ChainActive()[height];
- return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
- }
- Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
- {
- LockAssertion lock(::cs_main);
- CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height);
- if (block) {
- if (hash) *hash = block->GetBlockHash();
- return block->nHeight;
- }
- return nullopt;
- }
- Optional<int> findPruned(int start_height, Optional<int> stop_height) override
+ if (!index) return false;
+ if (block.m_hash) *block.m_hash = index->GetBlockHash();
+ if (block.m_height) *block.m_height = index->nHeight;
+ 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_data) {
+ REVERSE_LOCK(lock);
+ if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull();
+ }
+ return true;
+}
+
+class NotificationsProxy : public CValidationInterface
+{
+public:
+ explicit NotificationsProxy(std::shared_ptr<Chain::Notifications> notifications)
+ : m_notifications(std::move(notifications)) {}
+ virtual ~NotificationsProxy() = default;
+ void TransactionAddedToMempool(const CTransactionRef& tx) override
{
- LockAssertion lock(::cs_main);
- if (::fPruneMode) {
- CBlockIndex* block = stop_height ? ::ChainActive()[*stop_height] : ::ChainActive().Tip();
- while (block && block->nHeight >= start_height) {
- if ((block->nStatus & BLOCK_HAVE_DATA) == 0) {
- return block->nHeight;
- }
- block = block->pprev;
- }
- }
- return nullopt;
+ m_notifications->transactionAddedToMempool(tx);
}
- Optional<int> findFork(const uint256& hash, Optional<int>* height) override
+ void TransactionRemovedFromMempool(const CTransactionRef& tx) override
{
- LockAssertion lock(::cs_main);
- const CBlockIndex* block = LookupBlockIndex(hash);
- const CBlockIndex* fork = block ? ::ChainActive().FindFork(block) : nullptr;
- if (height) {
- if (block) {
- *height = block->nHeight;
- } else {
- height->reset();
- }
- }
- if (fork) {
- return fork->nHeight;
- }
- return nullopt;
+ m_notifications->transactionRemovedFromMempool(tx);
}
- CBlockLocator getTipLocator() override
+ void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
{
- LockAssertion lock(::cs_main);
- return ::ChainActive().GetLocator();
+ m_notifications->blockConnected(*block, index->nHeight);
}
- Optional<int> findLocatorFork(const CBlockLocator& locator) override
+ void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
{
- LockAssertion lock(::cs_main);
- if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) {
- return fork->nHeight;
- }
- return nullopt;
+ m_notifications->blockDisconnected(*block, index->nHeight);
}
- bool checkFinalTx(const CTransaction& tx) override
+ void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override
{
- LockAssertion lock(::cs_main);
- return CheckFinalTx(tx);
+ m_notifications->updatedBlockTip();
}
-
- using UniqueLock::UniqueLock;
+ void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->chainStateFlushed(locator); }
+ std::shared_ptr<Chain::Notifications> m_notifications;
};
-class NotificationsHandlerImpl : public Handler, CValidationInterface
+class NotificationsHandlerImpl : public Handler
{
public:
- explicit NotificationsHandlerImpl(Chain& chain, Chain::Notifications& notifications)
- : m_chain(chain), m_notifications(&notifications)
+ explicit NotificationsHandlerImpl(std::shared_ptr<Chain::Notifications> notifications)
+ : m_proxy(std::make_shared<NotificationsProxy>(std::move(notifications)))
{
- RegisterValidationInterface(this);
+ RegisterSharedValidationInterface(m_proxy);
}
~NotificationsHandlerImpl() override { disconnect(); }
void disconnect() override
{
- if (m_notifications) {
- m_notifications = nullptr;
- UnregisterValidationInterface(this);
+ if (m_proxy) {
+ UnregisterSharedValidationInterface(m_proxy);
+ m_proxy.reset();
}
}
- void TransactionAddedToMempool(const CTransactionRef& tx) override
- {
- m_notifications->TransactionAddedToMempool(tx);
- }
- void TransactionRemovedFromMempool(const CTransactionRef& tx) override
- {
- m_notifications->TransactionRemovedFromMempool(tx);
- }
- void BlockConnected(const std::shared_ptr<const CBlock>& block,
- const CBlockIndex* index,
- const std::vector<CTransactionRef>& tx_conflicted) override
- {
- m_notifications->BlockConnected(*block, tx_conflicted, index->nHeight);
- }
- void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
- {
- m_notifications->BlockDisconnected(*block, index->nHeight);
- }
- void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override
- {
- m_notifications->UpdatedBlockTip();
- }
- void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->ChainStateFlushed(locator); }
- Chain& m_chain;
- Chain::Notifications* m_notifications;
+ std::shared_ptr<NotificationsProxy> m_proxy;
};
class RpcHandlerImpl : public Handler
@@ -234,34 +145,109 @@ class ChainImpl : public Chain
{
public:
explicit ChainImpl(NodeContext& node) : m_node(node) {}
- std::unique_ptr<Chain::Lock> lock(bool try_lock) override
- {
- auto result = MakeUnique<LockImpl>(::cs_main, "cs_main", __FILE__, __LINE__, try_lock);
- if (try_lock && result && !*result) return {};
- // std::move necessary on some compilers due to conversion from
- // LockImpl to Lock pointer
- return std::move(result);
- }
- bool findBlock(const uint256& hash, CBlock* block, int64_t* time, int64_t* time_max) override
- {
- CBlockIndex* index;
- {
- LOCK(cs_main);
- index = LookupBlockIndex(hash);
- if (!index) {
- return false;
- }
- if (time) {
- *time = index->GetBlockTime();
- }
- if (time_max) {
- *time_max = index->GetBlockTimeMax();
- }
+ Optional<int> getHeight() override
+ {
+ LOCK(::cs_main);
+ int height = ::ChainActive().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];
+ assert(block);
+ return block->GetBlockHash();
+ }
+ bool haveBlockOnDisk(int height) override
+ {
+ LOCK(cs_main);
+ CBlockIndex* block = ::ChainActive()[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();
+ }
+ bool checkFinalTx(const CTransaction& tx) override
+ {
+ LOCK(cs_main);
+ return CheckFinalTx(tx);
+ }
+ Optional<int> findLocatorFork(const CBlockLocator& locator) override
+ {
+ LOCK(cs_main);
+ if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) {
+ return fork->nHeight;
}
- if (block && !ReadBlockFromDisk(*block, index, Params().GetConsensus())) {
- block->SetNull();
+ return nullopt;
+ }
+ bool findBlock(const uint256& hash, const FoundBlock& block) override
+ {
+ WAIT_LOCK(cs_main, lock);
+ return FillBlock(LookupBlockIndex(hash), block, lock);
+ }
+ 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);
+ }
+ bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
+ {
+ WAIT_LOCK(cs_main, lock);
+ if (const CBlockIndex* block = LookupBlockIndex(block_hash)) {
+ if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
+ return FillBlock(ancestor, ancestor_out, lock);
+ }
}
- return true;
+ return FillBlock(nullptr, ancestor_out, lock);
+ }
+ bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
+ {
+ WAIT_LOCK(cs_main, lock);
+ 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);
+ }
+ 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 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);
}
void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
double guessVerificationProgress(const uint256& block_hash) override
@@ -269,6 +255,25 @@ public:
LOCK(cs_main);
return GuessVerificationProgress(Params().TxData(), LookupBlockIndex(block_hash));
}
+ bool hasBlocks(const uint256& block_hash, int min_height, Optional<int> max_height) override
+ {
+ // hasBlocks returns true if all ancestors of block_hash in specified
+ // range have block data (are not pruned), false if any ancestors in
+ // specified range are missing data.
+ //
+ // For simplicity and robustness, min_height and max_height are only
+ // used to limit the range, and passing min_height that's too low or
+ // max_height that's too high will not crash or change the result.
+ LOCK(::cs_main);
+ if (CBlockIndex* block = LookupBlockIndex(block_hash)) {
+ if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height);
+ for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) {
+ // Check pprev to not segfault if min_height is too low
+ if (block->nHeight <= min_height || !block->pprev) return true;
+ }
+ }
+ return false;
+ }
RBFTransactionState isRBFOptIn(const CTransaction& tx) override
{
LOCK(::mempool.cs);
@@ -280,7 +285,10 @@ public:
auto it = ::mempool.GetIter(txid);
return it && (*it)->GetCountWithDescendants() > 1;
}
- bool broadcastTransaction(const CTransactionRef& tx, std::string& err_string, const CAmount& max_tx_fee, bool relay) override
+ bool broadcastTransaction(const CTransactionRef& tx,
+ const CAmount& max_tx_fee,
+ bool relay,
+ std::string& err_string) override
{
const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, relay, /*wait_callback*/ false);
// Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures.
@@ -342,9 +350,9 @@ public:
{
::uiInterface.ShowProgress(title, progress, resume_possible);
}
- std::unique_ptr<Handler> handleNotifications(Notifications& notifications) override
+ std::unique_ptr<Handler> handleNotifications(std::shared_ptr<Notifications> notifications) override
{
- return MakeUnique<NotificationsHandlerImpl>(*this, notifications);
+ return MakeUnique<NotificationsHandlerImpl>(std::move(notifications));
}
void waitForNotificationsIfTipChanged(const uint256& old_tip) override
{
@@ -368,7 +376,7 @@ public:
{
LOCK2(::cs_main, ::mempool.cs);
for (const CTxMemPoolEntry& entry : ::mempool.mapTx) {
- notifications.TransactionAddedToMempool(entry.GetSharedTx());
+ notifications.transactionAddedToMempool(entry.GetSharedTx());
}
}
NodeContext& m_node;
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 7304f82749..e33fe54ac8 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -30,6 +30,27 @@ namespace interfaces {
class Handler;
class Wallet;
+//! Helper for findBlock to selectively return pieces of block data.
+class FoundBlock
+{
+public:
+ FoundBlock& hash(uint256& hash) { m_hash = &hash; return *this; }
+ FoundBlock& height(int& height) { m_height = &height; return *this; }
+ 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; }
+ //! 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; }
+
+ uint256* m_hash = nullptr;
+ int* m_height = nullptr;
+ int64_t* m_time = nullptr;
+ int64_t* m_max_time = nullptr;
+ int64_t* m_mtp_time = nullptr;
+ CBlock* m_data = nullptr;
+};
+
//! Interface giving clients (wallet processes, maybe other analysis tools in
//! the future) ability to access to the chain state, receive notifications,
//! estimate fees, and submit transactions.
@@ -38,12 +59,7 @@ class Wallet;
//! internal workings of the bitcoin node, and not being very convenient to use.
//! Chain methods should be cleaned up and simplified over time. Examples:
//!
-//! * The Chain::lock() method, which lets clients delay chain tip updates
-//! should be removed when clients are able to respond to updates
-//! asynchronously
-//! (https://github.com/bitcoin/bitcoin/pull/10973#issuecomment-380101269).
-//!
-//! * The initMessage() and showProgress() methods which the wallet uses to send
+//! * The initMessages() and showProgress() methods which the wallet uses to send
//! notifications to the GUI should go away when GUI and wallet can directly
//! communicate with each other without going through the node
//! (https://github.com/bitcoin/bitcoin/pull/15288#discussion_r253321096).
@@ -51,90 +67,86 @@ class Wallet;
//! * The handleRpc, registerRpcs, rpcEnableDeprecated methods and other RPC
//! methods can go away if wallets listen for HTTP requests on their own
//! ports instead of registering to handle requests on the node HTTP port.
+//!
+//! * Move fee estimation queries to an asynchronous interface and let the
+//! 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.
class Chain
{
public:
virtual ~Chain() {}
- //! Interface for querying locked chain state, used by legacy code that
- //! assumes state won't change between calls. New code should avoid using
- //! the Lock interface and instead call higher-level Chain methods
- //! that return more information so the chain doesn't need to stay locked
- //! between calls.
- class Lock
- {
- public:
- virtual ~Lock() {}
-
- //! Get current chain height, not including genesis block (returns 0 if
- //! chain only contains genesis block, nullopt if chain does not contain
- //! 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;
-
- //! Get block time. Height must be valid or this function will abort.
- virtual int64_t getBlockTime(int height) = 0;
-
- //! Get block median time past. Height must be valid or this function
- //! will abort.
- virtual int64_t getBlockMedianTimePast(int height) = 0;
-
- //! Check that the block is available on disk (i.e. has not been
- //! 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;
-
- //! Return height of last block in the specified range which is pruned, or
- //! nullopt if no block in the range is pruned. Range is inclusive.
- virtual Optional<int> findPruned(int start_height = 0, Optional<int> stop_height = nullopt) = 0;
-
- //! Return height of the specified block if it is on the chain, otherwise
- //! return the height of the highest block on chain that's an ancestor
- //! of the specified block, or nullopt if there is no common ancestor.
- //! Also return the height of the specified block as an optional output
- //! parameter (to avoid the cost of a second hash lookup in case this
- //! information is desired).
- virtual Optional<int> findFork(const uint256& hash, Optional<int>* height) = 0;
-
- //! Get locator for the current chain tip.
- virtual CBlockLocator getTipLocator() = 0;
-
- //! Return height of the highest block on chain in common with the locator,
- //! which will either be the original block used to create the locator,
- //! or one of its ancestors.
- virtual Optional<int> findLocatorFork(const CBlockLocator& locator) = 0;
-
- //! Check if transaction will be final given chain height current time.
- virtual bool checkFinalTx(const CTransaction& tx) = 0;
- };
+ //! Get current chain height, not including genesis block (returns 0 if
+ //! chain only contains genesis block, nullopt if chain does not contain
+ //! any blocks)
+ virtual Optional<int> getHeight() = 0;
- //! Return Lock interface. Chain is locked when this is called, and
- //! unlocked when the returned interface is freed.
- virtual std::unique_ptr<Lock> lock(bool try_lock = false) = 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;
+
+ //! Check that the block is available on disk (i.e. has not been
+ //! 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;
+
+ //! Return height of the highest block on chain in common with the locator,
+ //! which will either be the original block used to create the locator,
+ //! or one of its ancestors.
+ virtual Optional<int> findLocatorFork(const CBlockLocator& locator) = 0;
+
+ //! Check if transaction will be final given chain height current time.
+ virtual bool checkFinalTx(const CTransaction& tx) = 0;
//! Return whether node has the block and optionally return block metadata
//! or contents.
- //!
- //! If a block pointer is provided to retrieve the block contents, and the
- //! block exists but doesn't have data (for example due to pruning), the
- //! block will be empty and all fields set to null.
- virtual bool findBlock(const uint256& hash,
- CBlock* block = nullptr,
- int64_t* time = nullptr,
- int64_t* max_time = nullptr) = 0;
+ virtual bool findBlock(const uint256& hash, const FoundBlock& block={}) = 0;
+
+ //! Find first block in the chain with timestamp >= the given time
+ //! and height >= than the given height, return false if there is no block
+ //! with a high enough timestamp and height. Optionally return block
+ //! 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;
+
+ //! Return whether block descends from a specified ancestor, and
+ //! optionally return ancestor information.
+ virtual bool findAncestorByHash(const uint256& block_hash,
+ const uint256& ancestor_hash,
+ const FoundBlock& ancestor_out={}) = 0;
+
+ //! Find most recent common ancestor between two blocks and optionally
+ //! return block information.
+ virtual bool findCommonAncestor(const uint256& block_hash1,
+ const uint256& block_hash2,
+ const FoundBlock& ancestor_out={},
+ const FoundBlock& block1_out={},
+ const FoundBlock& block2_out={}) = 0;
//! Look up unspent output information. Returns coins in the mempool and in
//! the current chain UTXO set. Iterates through all the keys in the map and
@@ -145,6 +157,11 @@ public:
//! the specified block hash are verified.
virtual double guessVerificationProgress(const uint256& block_hash) = 0;
+ //! Return true if data is available for all blocks in the specified range
+ //! of blocks. This checks all blocks that are ancestors of block_hash in
+ //! the height range from min_height to max_height, inclusive.
+ virtual bool hasBlocks(const uint256& block_hash, int min_height = 0, Optional<int> max_height = {}) = 0;
+
//! Check if transaction is RBF opt in.
virtual RBFTransactionState isRBFOptIn(const CTransaction& tx) = 0;
@@ -154,7 +171,10 @@ public:
//! Transaction is added to memory pool, if the transaction fee is below the
//! amount specified by max_tx_fee, and broadcast to all peers if relay is set to true.
//! Return false if the transaction could not be added due to the fee or for another reason.
- virtual bool broadcastTransaction(const CTransactionRef& tx, std::string& err_string, const CAmount& max_tx_fee, bool relay) = 0;
+ virtual bool broadcastTransaction(const CTransactionRef& tx,
+ const CAmount& max_tx_fee,
+ bool relay,
+ std::string& err_string) = 0;
//! Calculate mempool ancestor and descendant counts for the given transaction.
virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0;
@@ -217,16 +237,16 @@ public:
{
public:
virtual ~Notifications() {}
- virtual void TransactionAddedToMempool(const CTransactionRef& tx) {}
- virtual void TransactionRemovedFromMempool(const CTransactionRef& ptx) {}
- virtual void BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& tx_conflicted, int height) {}
- virtual void BlockDisconnected(const CBlock& block, int height) {}
- virtual void UpdatedBlockTip() {}
- virtual void ChainStateFlushed(const CBlockLocator& locator) {}
+ virtual void transactionAddedToMempool(const CTransactionRef& tx) {}
+ virtual void transactionRemovedFromMempool(const CTransactionRef& ptx) {}
+ virtual void blockConnected(const CBlock& block, int height) {}
+ virtual void blockDisconnected(const CBlock& block, int height) {}
+ virtual void updatedBlockTip() {}
+ virtual void chainStateFlushed(const CBlockLocator& locator) {}
};
//! Register handler for notifications.
- virtual std::unique_ptr<Handler> handleNotifications(Notifications& notifications) = 0;
+ virtual std::unique_ptr<Handler> handleNotifications(std::shared_ptr<Notifications> notifications) = 0;
//! Wait for pending notifications to be processed unless block hash points to the current
//! chain tip.
@@ -245,7 +265,7 @@ public:
//! Current RPC serialization flags.
virtual int rpcSerializationFlags() = 0;
- //! Synchronously send TransactionAddedToMempool notifications about all
+ //! Synchronously send transactionAddedToMempool notifications about all
//! current mempool transactions to the specified handler and return after
//! the last one is sent. These notifications aren't coordinated with async
//! notifications sent by handleNotifications, so out of date async
@@ -280,6 +300,12 @@ public:
//! Shut down client.
virtual void stop() = 0;
+
+ //! Set mock time.
+ virtual void setMockTime(int64_t time) = 0;
+
+ //! Return interfaces for accessing wallets (if any).
+ virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
};
//! Return implementation of Chain interface.
diff --git a/src/interfaces/handler.cpp b/src/interfaces/handler.cpp
index 95035c1b54..4134a4527f 100644
--- a/src/interfaces/handler.cpp
+++ b/src/interfaces/handler.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
diff --git a/src/interfaces/handler.h b/src/interfaces/handler.h
index fbac3c6b71..11baf9dd65 100644
--- a/src/interfaces/handler.h
+++ b/src/interfaces/handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 8a64a9d26a..5ebbd61584 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -37,6 +37,8 @@
#include <univalue.h>
+#include <boost/signals2/signal.hpp>
+
class CWallet;
fs::path GetWalletDir();
std::vector<fs::path> ListWalletDir();
@@ -95,7 +97,7 @@ public:
StopMapPort();
}
}
- void setupServerArgs() override { return SetupServerArgs(); }
+ void setupServerArgs() override { return SetupServerArgs(m_context); }
bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); }
size_t getNodeCount(CConnman::NumConnections flags) override
{
@@ -150,14 +152,14 @@ public:
}
return false;
}
- bool disconnect(const CNetAddr& net_addr) override
+ bool disconnectByAddress(const CNetAddr& net_addr) override
{
if (m_context.connman) {
return m_context.connman->DisconnectNode(net_addr);
}
return false;
}
- bool disconnect(NodeId id) override
+ bool disconnectById(NodeId id) override
{
if (m_context.connman) {
return m_context.connman->DisconnectNode(id);
@@ -251,8 +253,9 @@ public:
std::vector<std::unique_ptr<Wallet>> getWallets() override
{
std::vector<std::unique_ptr<Wallet>> wallets;
- for (const std::shared_ptr<CWallet>& wallet : GetWallets()) {
- wallets.emplace_back(MakeWallet(wallet));
+ for (auto& client : m_context.chain_clients) {
+ auto client_wallets = client->getWallets();
+ std::move(client_wallets.begin(), client_wallets.end(), std::back_inserter(wallets));
}
return wallets;
}
@@ -260,12 +263,11 @@ public:
{
return MakeWallet(LoadWallet(*m_context.chain, name, error, warnings));
}
- WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::unique_ptr<Wallet>& result) override
+ std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, WalletCreationStatus& status) override
{
std::shared_ptr<CWallet> wallet;
- WalletCreationStatus status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
- result = MakeWallet(wallet);
- return status;
+ status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
+ return MakeWallet(wallet);
}
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
{
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 38aeb06324..53a20886cd 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -124,10 +124,10 @@ public:
virtual bool unban(const CSubNet& ip) = 0;
//! Disconnect node by address.
- virtual bool disconnect(const CNetAddr& net_addr) = 0;
+ virtual bool disconnectByAddress(const CNetAddr& net_addr) = 0;
//! Disconnect node by id.
- virtual bool disconnect(NodeId id) = 0;
+ virtual bool disconnectById(NodeId id) = 0;
//! Get total bytes recv.
virtual int64_t getTotalBytesRecv() = 0;
@@ -204,7 +204,7 @@ public:
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::vector<std::string>& warnings) = 0;
//! Create a wallet from file
- virtual WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::unique_ptr<Wallet>& result) = 0;
+ virtual std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, WalletCreationStatus& status) = 0;
//! Register handler for init messages.
using InitMessageFn = std::function<void(const std::string& message)>;
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index baea71d0bb..752448aac7 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
@@ -14,12 +14,12 @@
#include <sync.h>
#include <ui_interface.h>
#include <uint256.h>
+#include <util/check.h>
#include <util/system.h>
#include <wallet/feebumper.h>
#include <wallet/fees.h>
#include <wallet/ismine.h>
#include <wallet/load.h>
-#include <wallet/psbtwallet.h>
#include <wallet/rpcwallet.h>
#include <wallet/wallet.h>
@@ -60,16 +60,16 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
}
//! Construct wallet tx status struct.
-WalletTxStatus MakeWalletTxStatus(interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx)
+WalletTxStatus MakeWalletTxStatus(CWallet& wallet, const CWalletTx& wtx)
{
WalletTxStatus result;
- result.block_height = locked_chain.getBlockHeight(wtx.m_confirm.hashBlock).get_value_or(std::numeric_limits<int>::max());
+ result.block_height = wtx.m_confirm.block_height > 0 ? wtx.m_confirm.block_height : std::numeric_limits<int>::max();
result.blocks_to_maturity = wtx.GetBlocksToMaturity();
result.depth_in_main_chain = wtx.GetDepthInMainChain();
result.time_received = wtx.nTimeReceived;
result.lock_time = wtx.tx->nLockTime;
- result.is_final = locked_chain.checkFinalTx(*wtx.tx);
- result.is_trusted = wtx.IsTrusted(locked_chain);
+ result.is_final = wallet.chain().checkFinalTx(*wtx.tx);
+ result.is_trusted = wtx.IsTrusted();
result.is_abandoned = wtx.isAbandoned();
result.is_coinbase = wtx.IsCoinBase();
result.is_in_main_chain = wtx.IsInMainChain();
@@ -119,19 +119,15 @@ public:
}
bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) override
{
- std::unique_ptr<SigningProvider> provider = m_wallet->GetSigningProvider(script);
+ std::unique_ptr<SigningProvider> provider = m_wallet->GetSolvingProvider(script);
if (provider) {
return provider->GetPubKey(address, pub_key);
}
return false;
}
- bool getPrivKey(const CScript& script, const CKeyID& address, CKey& key) override
+ SigningResult signMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) override
{
- std::unique_ptr<SigningProvider> provider = m_wallet->GetSigningProvider(script);
- if (provider) {
- return provider->GetKey(address, key);
- }
- return false;
+ return m_wallet->SignMessage(message, pkhash, str_sig);
}
bool isSpendable(const CTxDestination& dest) override { return m_wallet->IsMine(dest) & ISMINE_SPENDABLE; }
bool haveWatchOnly() override
@@ -156,12 +152,12 @@ public:
std::string* purpose) override
{
LOCK(m_wallet->cs_wallet);
- auto it = m_wallet->mapAddressBook.find(dest);
- if (it == m_wallet->mapAddressBook.end()) {
+ auto it = m_wallet->m_address_book.find(dest);
+ if (it == m_wallet->m_address_book.end() || it->second.IsChange()) {
return false;
}
if (name) {
- *name = it->second.name;
+ *name = it->second.GetLabel();
}
if (is_mine) {
*is_mine = m_wallet->IsMine(dest);
@@ -175,8 +171,9 @@ public:
{
LOCK(m_wallet->cs_wallet);
std::vector<WalletAddress> result;
- for (const auto& item : m_wallet->mapAddressBook) {
- result.emplace_back(item.first, m_wallet->IsMine(item.first), item.second.name, item.second.purpose);
+ for (const auto& item : m_wallet->m_address_book) {
+ if (item.second.IsChange()) continue;
+ result.emplace_back(item.first, m_wallet->IsMine(item.first), item.second.GetLabel(), item.second.purpose);
}
return result;
}
@@ -199,25 +196,21 @@ public:
}
void lockCoin(const COutPoint& output) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
return m_wallet->LockCoin(output);
}
void unlockCoin(const COutPoint& output) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
return m_wallet->UnlockCoin(output);
}
bool isLockedCoin(const COutPoint& output) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
return m_wallet->IsLockedCoin(output.hash, output.n);
}
void listLockedCoins(std::vector<COutPoint>& outputs) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
return m_wallet->ListLockedCoins(outputs);
}
@@ -228,10 +221,9 @@ public:
CAmount& fee,
std::string& fail_reason) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
CTransactionRef tx;
- if (!m_wallet->CreateTransaction(*locked_chain, recipients, tx, fee, change_pos,
+ if (!m_wallet->CreateTransaction(recipients, tx, fee, change_pos,
fail_reason, coin_control, sign)) {
return {};
}
@@ -241,14 +233,12 @@ public:
WalletValueMap value_map,
WalletOrderForm order_form) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form));
}
bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet->TransactionCanBeAbandoned(txid); }
bool abandonTransaction(const uint256& txid) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
return m_wallet->AbandonTransaction(txid);
}
@@ -258,19 +248,12 @@ public:
}
bool createBumpTransaction(const uint256& txid,
const CCoinControl& coin_control,
- CAmount total_fee,
std::vector<std::string>& errors,
CAmount& old_fee,
CAmount& new_fee,
CMutableTransaction& mtx) override
{
- if (total_fee > 0) {
- return feebumper::CreateTotalBumpTransaction(m_wallet.get(), txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) ==
- feebumper::Result::OK;
- } else {
- return feebumper::CreateRateBumpTransaction(*m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx) ==
- feebumper::Result::OK;
- }
+ return feebumper::CreateRateBumpTransaction(*m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx) == feebumper::Result::OK;
}
bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(*m_wallet.get(), mtx); }
bool commitBumpTransaction(const uint256& txid,
@@ -283,7 +266,6 @@ public:
}
CTransactionRef getTx(const uint256& txid) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
auto mi = m_wallet->mapWallet.find(txid);
if (mi != m_wallet->mapWallet.end()) {
@@ -293,7 +275,6 @@ public:
}
WalletTx getWalletTx(const uint256& txid) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
auto mi = m_wallet->mapWallet.find(txid);
if (mi != m_wallet->mapWallet.end()) {
@@ -303,7 +284,6 @@ public:
}
std::vector<WalletTx> getWalletTxs() override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
std::vector<WalletTx> result;
result.reserve(m_wallet->mapWallet.size());
@@ -317,10 +297,6 @@ public:
int& num_blocks,
int64_t& block_time) override
{
- auto locked_chain = m_wallet->chain().lock(true /* try_lock */);
- if (!locked_chain) {
- return false;
- }
TRY_LOCK(m_wallet->cs_wallet, locked_wallet);
if (!locked_wallet) {
return false;
@@ -329,14 +305,10 @@ public:
if (mi == m_wallet->mapWallet.end()) {
return false;
}
- if (Optional<int> height = locked_chain->getHeight()) {
- num_blocks = *height;
- block_time = locked_chain->getBlockTime(*height);
- } else {
- num_blocks = -1;
- block_time = -1;
- }
- tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
+ num_blocks = m_wallet->GetLastBlockHeight();
+ block_time = -1;
+ CHECK_NONFATAL(m_wallet->chain().findBlock(m_wallet->GetLastBlockHash(), FoundBlock().time(block_time)));
+ tx_status = MakeWalletTxStatus(*m_wallet, mi->second);
return true;
}
WalletTx getWalletTxDetails(const uint256& txid,
@@ -345,25 +317,24 @@ public:
bool& in_mempool,
int& num_blocks) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
auto mi = m_wallet->mapWallet.find(txid);
if (mi != m_wallet->mapWallet.end()) {
- num_blocks = locked_chain->getHeight().get_value_or(-1);
+ num_blocks = m_wallet->GetLastBlockHeight();
in_mempool = mi->second.InMempool();
order_form = mi->second.vOrderForm;
- tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
+ tx_status = MakeWalletTxStatus(*m_wallet, mi->second);
return MakeWalletTx(*m_wallet, mi->second);
}
return {};
}
- TransactionError fillPSBT(PartiallySignedTransaction& psbtx,
- bool& complete,
- int sighash_type = 1 /* SIGHASH_ALL */,
- bool sign = true,
- bool bip32derivs = false) override
+ TransactionError fillPSBT(int sighash_type,
+ bool sign,
+ bool bip32derivs,
+ PartiallySignedTransaction& psbtx,
+ bool& complete) override
{
- return FillPSBT(m_wallet.get(), psbtx, complete, sighash_type, sign, bip32derivs);
+ return m_wallet->FillPSBT(psbtx, complete, sighash_type, sign, bip32derivs);
}
WalletBalances getBalances() override
{
@@ -380,16 +351,15 @@ public:
}
return result;
}
- bool tryGetBalances(WalletBalances& balances, int& num_blocks) override
+ bool tryGetBalances(WalletBalances& balances, int& num_blocks, bool force, int cached_num_blocks) override
{
- auto locked_chain = m_wallet->chain().lock(true /* try_lock */);
- if (!locked_chain) return false;
TRY_LOCK(m_wallet->cs_wallet, locked_wallet);
if (!locked_wallet) {
return false;
}
+ num_blocks = m_wallet->GetLastBlockHeight();
+ if (!force && num_blocks == cached_num_blocks) return false;
balances = getBalances();
- num_blocks = locked_chain->getHeight().get_value_or(-1);
return true;
}
CAmount getBalance() override { return m_wallet->GetBalance().m_mine_trusted; }
@@ -399,34 +369,29 @@ public:
}
isminetype txinIsMine(const CTxIn& txin) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
return m_wallet->IsMine(txin);
}
isminetype txoutIsMine(const CTxOut& txout) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
return m_wallet->IsMine(txout);
}
CAmount getDebit(const CTxIn& txin, isminefilter filter) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
return m_wallet->GetDebit(txin, filter);
}
CAmount getCredit(const CTxOut& txout, isminefilter filter) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
return m_wallet->GetCredit(txout, filter);
}
CoinsList listCoins() override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
CoinsList result;
- for (const auto& entry : m_wallet->ListCoins(*locked_chain)) {
+ for (const auto& entry : m_wallet->ListCoins()) {
auto& group = result[entry.first];
for (const auto& coin : entry.second) {
group.emplace_back(COutPoint(coin.tx->GetHash(), coin.i),
@@ -437,7 +402,6 @@ public:
}
std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) override
{
- auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
std::vector<WalletTxOut> result;
result.reserve(outputs.size());
@@ -469,7 +433,7 @@ public:
unsigned int getConfirmTarget() override { return m_wallet->m_confirm_target; }
bool hdEnabled() override { return m_wallet->IsHDEnabled(); }
bool canGetAddresses() override { return m_wallet->CanGetAddresses(); }
- bool IsWalletFlagSet(uint64_t flag) override { return m_wallet->IsWalletFlagSet(flag); }
+ bool privateKeysDisabled() override { return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS); }
OutputType getDefaultAddressType() override { return m_wallet->m_default_address_type; }
OutputType getDefaultChangeType() override { return m_wallet->m_default_change_type; }
CAmount getDefaultMaxTxFee() override { return m_wallet->m_default_max_tx_fee; }
@@ -477,6 +441,7 @@ public:
{
RemoveWallet(m_wallet);
}
+ bool isLegacy() override { return m_wallet->IsLegacy(); }
std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
{
return MakeHandler(m_wallet->NotifyUnload.connect(fn));
@@ -508,6 +473,7 @@ public:
{
return MakeHandler(m_wallet->NotifyCanGetAddressesChanged.connect(fn));
}
+ CWallet* wallet() override { return m_wallet.get(); }
std::shared_ptr<CWallet> m_wallet;
};
@@ -529,6 +495,15 @@ public:
void start(CScheduler& scheduler) override { return StartWallets(scheduler); }
void flush() override { return FlushWallets(); }
void stop() override { return StopWallets(); }
+ void setMockTime(int64_t time) override { return SetMockTime(time); }
+ std::vector<std::unique_ptr<Wallet>> getWallets() override
+ {
+ std::vector<std::unique_ptr<Wallet>> wallets;
+ for (const auto& wallet : GetWallets()) {
+ wallets.emplace_back(MakeWallet(wallet));
+ }
+ return wallets;
+ }
~WalletClientImpl() override { UnloadWallets(); }
Chain& m_chain;
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index d4280e8091..e5e3b80663 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
@@ -10,11 +10,11 @@
#include <script/standard.h> // For CTxDestination
#include <support/allocators/secure.h> // For SecureString
#include <ui_interface.h> // For ChangeType
+#include <util/message.h>
#include <functional>
#include <map>
#include <memory>
-#include <psbt.h>
#include <stdint.h>
#include <string>
#include <tuple>
@@ -25,12 +25,13 @@ class CCoinControl;
class CFeeRate;
class CKey;
class CWallet;
-enum isminetype : unsigned int;
enum class FeeReason;
-typedef uint8_t isminefilter;
-
enum class OutputType;
+enum class TransactionError;
+enum isminetype : unsigned int;
struct CRecipient;
+struct PartiallySignedTransaction;
+typedef uint8_t isminefilter;
namespace interfaces {
@@ -84,8 +85,8 @@ public:
//! Get public key.
virtual bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) = 0;
- //! Get private key.
- virtual bool getPrivKey(const CScript& script, const CKeyID& address, CKey& key) = 0;
+ //! Sign message
+ virtual SigningResult signMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) = 0;
//! Return whether wallet has private key.
virtual bool isSpendable(const CTxDestination& dest) = 0;
@@ -154,7 +155,6 @@ public:
//! Create bump transaction.
virtual bool createBumpTransaction(const uint256& txid,
const CCoinControl& coin_control,
- CAmount total_fee,
std::vector<std::string>& errors,
CAmount& old_fee,
CAmount& new_fee,
@@ -192,17 +192,20 @@ public:
int& num_blocks) = 0;
//! Fill PSBT.
- virtual TransactionError fillPSBT(PartiallySignedTransaction& psbtx,
- bool& complete,
- int sighash_type = 1 /* SIGHASH_ALL */,
- bool sign = true,
- bool bip32derivs = false) = 0;
+ virtual TransactionError fillPSBT(int sighash_type,
+ bool sign,
+ bool bip32derivs,
+ PartiallySignedTransaction& psbtx,
+ bool& complete) = 0;
//! Get balances.
virtual WalletBalances getBalances() = 0;
- //! Get balances if possible without blocking.
- virtual bool tryGetBalances(WalletBalances& balances, int& num_blocks) = 0;
+ //! Get balances if possible without waiting for chain and wallet locks.
+ virtual bool tryGetBalances(WalletBalances& balances,
+ int& num_blocks,
+ bool force,
+ int cached_num_blocks) = 0;
//! Get balance.
virtual CAmount getBalance() = 0;
@@ -248,8 +251,8 @@ public:
// Return whether the wallet is blank.
virtual bool canGetAddresses() = 0;
- // check if a certain wallet flag is set.
- virtual bool IsWalletFlagSet(uint64_t flag) = 0;
+ // Return whether private keys enabled.
+ virtual bool privateKeysDisabled() = 0;
// Get default address type.
virtual OutputType getDefaultAddressType() = 0;
@@ -263,6 +266,9 @@ public:
// Remove wallet.
virtual void remove() = 0;
+ //! Return whether is a legacy wallet
+ virtual bool isLegacy() = 0;
+
//! Register handler for unload message.
using UnloadFn = std::function<void()>;
virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
@@ -294,6 +300,9 @@ public:
//! Register handler for keypool changed messages.
using CanGetAddressesChangedFn = std::function<void()>;
virtual std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) = 0;
+
+ //! Return pointer to internal wallet class, useful for testing.
+ virtual CWallet* wallet() { return nullptr; }
};
//! Information about one wallet address.
diff --git a/src/leveldb/.appveyor.yml b/src/leveldb/.appveyor.yml
new file mode 100644
index 0000000000..c24b17e805
--- /dev/null
+++ b/src/leveldb/.appveyor.yml
@@ -0,0 +1,35 @@
+# Build matrix / environment variables are explained on:
+# https://www.appveyor.com/docs/appveyor-yml/
+# This file can be validated on: https://ci.appveyor.com/tools/validate-yaml
+
+version: "{build}"
+
+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
+
+platform:
+ - x86
+ - x64
+
+configuration:
+ - RelWithDebInfo
+ - Debug
+
+build_script:
+ - git submodule update --init --recursive
+ - mkdir build
+ - cd build
+ - if "%platform%"=="x64" set CMAKE_GENERATOR=%CMAKE_GENERATOR% Win64
+ - cmake --version
+ - cmake .. -G "%CMAKE_GENERATOR%"
+ -DCMAKE_CONFIGURATION_TYPES="%CONFIGURATION%"
+ - cmake --build . --config "%CONFIGURATION%"
+ - cd ..
+
+test_script:
+ - cd build && ctest --verbose --build-config "%CONFIGURATION%" && cd ..
diff --git a/src/leveldb/.clang-format b/src/leveldb/.clang-format
new file mode 100644
index 0000000000..f493f75382
--- /dev/null
+++ b/src/leveldb/.clang-format
@@ -0,0 +1,18 @@
+# Run manually to reformat a file:
+# clang-format -i --style=file <file>
+# find . -iname '*.cc' -o -iname '*.h' -o -iname '*.h.in' | xargs clang-format -i --style=file
+BasedOnStyle: Google
+DerivePointerAlignment: false
+
+# Public headers are in a different location in the internal Google repository.
+# Order them so that when imported to the authoritative repository they will be
+# in correct alphabetical order.
+IncludeCategories:
+ - Regex: '^(<|"(benchmarks|db|helpers)/)'
+ Priority: 1
+ - Regex: '^"(leveldb)/'
+ Priority: 2
+ - Regex: '^(<|"(issues|port|table|third_party|util)/)'
+ Priority: 3
+ - Regex: '.*'
+ Priority: 4
diff --git a/src/leveldb/.gitignore b/src/leveldb/.gitignore
index 71d87a4eeb..c4b242534f 100644
--- a/src/leveldb/.gitignore
+++ b/src/leveldb/.gitignore
@@ -1,13 +1,8 @@
-build_config.mk
-*.a
-*.o
-*.dylib*
-*.so
-*.so.*
-*_test
-db_bench
-leveldbutil
-Release
-Debug
-Benchmark
-vs2010.*
+# Editors.
+*.sw*
+.vscode
+.DS_Store
+
+# Build directory.
+build/
+out/
diff --git a/src/leveldb/.travis.yml b/src/leveldb/.travis.yml
index f5bd74c454..42cbe64fd0 100644
--- a/src/leveldb/.travis.yml
+++ b/src/leveldb/.travis.yml
@@ -1,13 +1,82 @@
+# Build matrix / environment variables are explained on:
+# http://about.travis-ci.org/docs/user/build-configuration/
+# This file can be validated on: http://lint.travis-ci.org/
+
language: cpp
+dist: bionic
+osx_image: xcode10.3
+
compiler:
-- clang
- gcc
+- clang
os:
- linux
- osx
-sudo: false
-before_install:
-- echo $LANG
-- echo $LC_ALL
+
+env:
+- BUILD_TYPE=Debug
+- BUILD_TYPE=RelWithDebInfo
+
+addons:
+ apt:
+ sources:
+ - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main'
+ key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
+ - sourceline: 'ppa:ubuntu-toolchain-r/test'
+ packages:
+ - clang-9
+ - cmake
+ - gcc-9
+ - g++-9
+ - libgoogle-perftools-dev
+ - libkyotocabinet-dev
+ - libsnappy-dev
+ - libsqlite3-dev
+ - ninja-build
+ homebrew:
+ packages:
+ - cmake
+ - crc32c
+ - gcc@9
+ - gperftools
+ - kyoto-cabinet
+ - llvm@9
+ - ninja
+ - snappy
+ - sqlite3
+ update: true
+
+install:
+# The following Homebrew packages aren't linked by default, and need to be
+# prepended to the path explicitly.
+- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
+ export PATH="$(brew --prefix llvm)/bin:$PATH";
+ fi
+# /usr/bin/gcc points to an older compiler on both Linux and macOS.
+- if [ "$CXX" = "g++" ]; then export CXX="g++-9" CC="gcc-9"; fi
+# /usr/bin/clang points to an older compiler on both Linux and macOS.
+#
+# Homebrew's llvm package doesn't ship a versioned clang++ binary, so the values
+# below don't work on macOS. Fortunately, the path change above makes the
+# default values (clang and clang++) resolve to the correct compiler on macOS.
+- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
+ if [ "$CXX" = "clang++" ]; then export CXX="clang++-9" CC="clang-9"; fi;
+ fi
+- echo ${CC}
+- echo ${CXX}
+- ${CXX} --version
+- cmake --version
+
+before_script:
+- mkdir -p build && cd build
+- cmake .. -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE
+ -DCMAKE_INSTALL_PREFIX=$HOME/.local
+- cmake --build .
+- cd ..
+
script:
-- make -j 4 check
+- cd build && ctest --verbose && cd ..
+- "if [ -f build/db_bench ] ; then build/db_bench ; fi"
+- "if [ -f build/db_bench_sqlite3 ] ; then build/db_bench_sqlite3 ; fi"
+- "if [ -f build/db_bench_tree_db ] ; then build/db_bench_tree_db ; fi"
+- cd build && cmake --build . --target install
diff --git a/src/leveldb/CMakeLists.txt b/src/leveldb/CMakeLists.txt
new file mode 100644
index 0000000000..1cb46256c2
--- /dev/null
+++ b/src/leveldb/CMakeLists.txt
@@ -0,0 +1,465 @@
+# Copyright 2017 The LevelDB Authors. All rights reserved.
+# 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.
+
+cmake_minimum_required(VERSION 3.9)
+# Keep the version below in sync with the one in db.h
+project(leveldb VERSION 1.22.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)
+
+if (WIN32)
+ set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_WINDOWS)
+ # TODO(cmumford): Make UNICODE configurable for Windows.
+ add_definitions(-D_UNICODE -DUNICODE)
+else (WIN32)
+ set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_POSIX)
+endif (WIN32)
+
+option(LEVELDB_BUILD_TESTS "Build LevelDB's unit tests" ON)
+option(LEVELDB_BUILD_BENCHMARKS "Build LevelDB's benchmarks" ON)
+option(LEVELDB_INSTALL "Install LevelDB's header and library" ON)
+
+include(TestBigEndian)
+test_big_endian(LEVELDB_IS_BIG_ENDIAN)
+
+include(CheckIncludeFile)
+check_include_file("unistd.h" HAVE_UNISTD_H)
+
+include(CheckLibraryExists)
+check_library_exists(crc32c crc32c_value "" HAVE_CRC32C)
+check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)
+check_library_exists(tcmalloc malloc "" HAVE_TCMALLOC)
+
+include(CheckCXXSymbolExists)
+# Using check_cxx_symbol_exists() instead of check_c_symbol_exists() because
+# we're including the header from C++, and feature detection should use the same
+# compiler language that the project will use later. Principles aside, some
+# versions of do not expose fdatasync() in <unistd.h> in standard C mode
+# (-std=c11), but do expose the function in standard C++ mode (-std=c++11).
+check_cxx_symbol_exists(fdatasync "unistd.h" HAVE_FDATASYNC)
+check_cxx_symbol_exists(F_FULLFSYNC "fcntl.h" HAVE_FULLFSYNC)
+check_cxx_symbol_exists(O_CLOEXEC "fcntl.h" HAVE_O_CLOEXEC)
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ # Disable C++ exceptions.
+ string(REGEX REPLACE "/EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
+ add_definitions(-D_HAS_EXCEPTIONS=0)
+
+ # Disable RTTI.
+ string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
+else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ # Enable strict prototype warnings for C code in clang and gcc.
+ if(NOT CMAKE_C_FLAGS MATCHES "-Wstrict-prototypes")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-prototypes")
+ endif(NOT CMAKE_C_FLAGS MATCHES "-Wstrict-prototypes")
+
+ # Disable C++ exceptions.
+ string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
+
+ # Disable RTTI.
+ string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+
+# Test whether -Wthread-safety is available. See
+# https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
+include(CheckCXXCompilerFlag)
+check_cxx_compiler_flag(-Wthread-safety HAVE_CLANG_THREAD_SAFETY)
+
+include(CheckCXXSourceCompiles)
+
+# Test whether C++17 __has_include is available.
+check_cxx_source_compiles("
+#if defined(__has_include) && __has_include(<string>)
+#include <string>
+#endif
+int main() { std::string str; return 0; }
+" HAVE_CXX17_HAS_INCLUDE)
+
+set(LEVELDB_PUBLIC_INCLUDE_DIR "include/leveldb")
+set(LEVELDB_PORT_CONFIG_DIR "include/port")
+
+configure_file(
+ "port/port_config.h.in"
+ "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
+)
+
+include_directories(
+ "${PROJECT_BINARY_DIR}/include"
+ "."
+)
+
+if(BUILD_SHARED_LIBS)
+ # Only export LEVELDB_EXPORT symbols from the shared library.
+ add_compile_options(-fvisibility=hidden)
+endif(BUILD_SHARED_LIBS)
+
+# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
+include(GNUInstallDirs)
+
+add_library(leveldb "")
+target_sources(leveldb
+ PRIVATE
+ "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
+ "db/builder.cc"
+ "db/builder.h"
+ "db/c.cc"
+ "db/db_impl.cc"
+ "db/db_impl.h"
+ "db/db_iter.cc"
+ "db/db_iter.h"
+ "db/dbformat.cc"
+ "db/dbformat.h"
+ "db/dumpfile.cc"
+ "db/filename.cc"
+ "db/filename.h"
+ "db/log_format.h"
+ "db/log_reader.cc"
+ "db/log_reader.h"
+ "db/log_writer.cc"
+ "db/log_writer.h"
+ "db/memtable.cc"
+ "db/memtable.h"
+ "db/repair.cc"
+ "db/skiplist.h"
+ "db/snapshot.h"
+ "db/table_cache.cc"
+ "db/table_cache.h"
+ "db/version_edit.cc"
+ "db/version_edit.h"
+ "db/version_set.cc"
+ "db/version_set.h"
+ "db/write_batch_internal.h"
+ "db/write_batch.cc"
+ "port/port_stdcxx.h"
+ "port/port.h"
+ "port/thread_annotations.h"
+ "table/block_builder.cc"
+ "table/block_builder.h"
+ "table/block.cc"
+ "table/block.h"
+ "table/filter_block.cc"
+ "table/filter_block.h"
+ "table/format.cc"
+ "table/format.h"
+ "table/iterator_wrapper.h"
+ "table/iterator.cc"
+ "table/merger.cc"
+ "table/merger.h"
+ "table/table_builder.cc"
+ "table/table.cc"
+ "table/two_level_iterator.cc"
+ "table/two_level_iterator.h"
+ "util/arena.cc"
+ "util/arena.h"
+ "util/bloom.cc"
+ "util/cache.cc"
+ "util/coding.cc"
+ "util/coding.h"
+ "util/comparator.cc"
+ "util/crc32c.cc"
+ "util/crc32c.h"
+ "util/env.cc"
+ "util/filter_policy.cc"
+ "util/hash.cc"
+ "util/hash.h"
+ "util/logging.cc"
+ "util/logging.h"
+ "util/mutexlock.h"
+ "util/no_destructor.h"
+ "util/options.cc"
+ "util/random.h"
+ "util/status.cc"
+
+ # Only CMake 3.3+ supports PUBLIC sources in targets exported by "install".
+ $<$<VERSION_GREATER:CMAKE_VERSION,3.2>:PUBLIC>
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/c.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/cache.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/comparator.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/db.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/dumpfile.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/env.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/export.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/filter_policy.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/iterator.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/options.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/slice.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/status.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/table_builder.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/table.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/write_batch.h"
+)
+
+if (WIN32)
+ target_sources(leveldb
+ PRIVATE
+ "util/env_windows.cc"
+ "util/windows_logger.h"
+ )
+else (WIN32)
+ target_sources(leveldb
+ PRIVATE
+ "util/env_posix.cc"
+ "util/posix_logger.h"
+ )
+endif (WIN32)
+
+# MemEnv is not part of the interface and could be pulled to a separate library.
+target_sources(leveldb
+ PRIVATE
+ "helpers/memenv/memenv.cc"
+ "helpers/memenv/memenv.h"
+)
+
+target_include_directories(leveldb
+ PUBLIC
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+set_target_properties(leveldb
+ PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
+
+target_compile_definitions(leveldb
+ PRIVATE
+ # Used by include/export.h when building shared libraries.
+ LEVELDB_COMPILE_LIBRARY
+ # Used by port/port.h.
+ ${LEVELDB_PLATFORM_NAME}=1
+)
+if (NOT HAVE_CXX17_HAS_INCLUDE)
+ target_compile_definitions(leveldb
+ PRIVATE
+ LEVELDB_HAS_PORT_CONFIG_H=1
+ )
+endif(NOT HAVE_CXX17_HAS_INCLUDE)
+
+if(BUILD_SHARED_LIBS)
+ target_compile_definitions(leveldb
+ PUBLIC
+ # Used by include/export.h.
+ LEVELDB_SHARED_LIBRARY
+ )
+endif(BUILD_SHARED_LIBS)
+
+if(HAVE_CLANG_THREAD_SAFETY)
+ target_compile_options(leveldb
+ PUBLIC
+ -Werror -Wthread-safety)
+endif(HAVE_CLANG_THREAD_SAFETY)
+
+if(HAVE_CRC32C)
+ target_link_libraries(leveldb crc32c)
+endif(HAVE_CRC32C)
+if(HAVE_SNAPPY)
+ target_link_libraries(leveldb snappy)
+endif(HAVE_SNAPPY)
+if(HAVE_TCMALLOC)
+ target_link_libraries(leveldb tcmalloc)
+endif(HAVE_TCMALLOC)
+
+# Needed by port_stdcxx.h
+find_package(Threads REQUIRED)
+target_link_libraries(leveldb Threads::Threads)
+
+add_executable(leveldbutil
+ "db/leveldbutil.cc"
+)
+target_link_libraries(leveldbutil leveldb)
+
+if(LEVELDB_BUILD_TESTS)
+ enable_testing()
+
+ function(leveldb_test test_file)
+ get_filename_component(test_target_name "${test_file}" NAME_WE)
+
+ add_executable("${test_target_name}" "")
+ target_sources("${test_target_name}"
+ PRIVATE
+ "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
+ "util/testharness.cc"
+ "util/testharness.h"
+ "util/testutil.cc"
+ "util/testutil.h"
+
+ "${test_file}"
+ )
+ target_link_libraries("${test_target_name}" leveldb)
+ target_compile_definitions("${test_target_name}"
+ PRIVATE
+ ${LEVELDB_PLATFORM_NAME}=1
+ )
+ if (NOT HAVE_CXX17_HAS_INCLUDE)
+ target_compile_definitions("${test_target_name}"
+ PRIVATE
+ LEVELDB_HAS_PORT_CONFIG_H=1
+ )
+ endif(NOT HAVE_CXX17_HAS_INCLUDE)
+
+ add_test(NAME "${test_target_name}" COMMAND "${test_target_name}")
+ endfunction(leveldb_test)
+
+ leveldb_test("db/c_test.c")
+ leveldb_test("db/fault_injection_test.cc")
+
+ leveldb_test("issues/issue178_test.cc")
+ leveldb_test("issues/issue200_test.cc")
+ leveldb_test("issues/issue320_test.cc")
+
+ leveldb_test("util/env_test.cc")
+ leveldb_test("util/status_test.cc")
+ leveldb_test("util/no_destructor_test.cc")
+
+ if(NOT BUILD_SHARED_LIBS)
+ leveldb_test("db/autocompact_test.cc")
+ leveldb_test("db/corruption_test.cc")
+ leveldb_test("db/db_test.cc")
+ leveldb_test("db/dbformat_test.cc")
+ leveldb_test("db/filename_test.cc")
+ leveldb_test("db/log_test.cc")
+ leveldb_test("db/recovery_test.cc")
+ leveldb_test("db/skiplist_test.cc")
+ leveldb_test("db/version_edit_test.cc")
+ leveldb_test("db/version_set_test.cc")
+ leveldb_test("db/write_batch_test.cc")
+
+ leveldb_test("helpers/memenv/memenv_test.cc")
+
+ leveldb_test("table/filter_block_test.cc")
+ leveldb_test("table/table_test.cc")
+
+ leveldb_test("util/arena_test.cc")
+ leveldb_test("util/bloom_test.cc")
+ leveldb_test("util/cache_test.cc")
+ leveldb_test("util/coding_test.cc")
+ leveldb_test("util/crc32c_test.cc")
+ leveldb_test("util/hash_test.cc")
+ leveldb_test("util/logging_test.cc")
+
+ # TODO(costan): This test also uses
+ # "util/env_{posix|windows}_test_helper.h"
+ if (WIN32)
+ leveldb_test("util/env_windows_test.cc")
+ else (WIN32)
+ leveldb_test("util/env_posix_test.cc")
+ endif (WIN32)
+ endif(NOT BUILD_SHARED_LIBS)
+endif(LEVELDB_BUILD_TESTS)
+
+if(LEVELDB_BUILD_BENCHMARKS)
+ function(leveldb_benchmark bench_file)
+ get_filename_component(bench_target_name "${bench_file}" NAME_WE)
+
+ add_executable("${bench_target_name}" "")
+ target_sources("${bench_target_name}"
+ PRIVATE
+ "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
+ "util/histogram.cc"
+ "util/histogram.h"
+ "util/testharness.cc"
+ "util/testharness.h"
+ "util/testutil.cc"
+ "util/testutil.h"
+
+ "${bench_file}"
+ )
+ target_link_libraries("${bench_target_name}" leveldb)
+ target_compile_definitions("${bench_target_name}"
+ PRIVATE
+ ${LEVELDB_PLATFORM_NAME}=1
+ )
+ if (NOT HAVE_CXX17_HAS_INCLUDE)
+ target_compile_definitions("${bench_target_name}"
+ PRIVATE
+ LEVELDB_HAS_PORT_CONFIG_H=1
+ )
+ endif(NOT HAVE_CXX17_HAS_INCLUDE)
+ endfunction(leveldb_benchmark)
+
+ if(NOT BUILD_SHARED_LIBS)
+ leveldb_benchmark("benchmarks/db_bench.cc")
+ endif(NOT BUILD_SHARED_LIBS)
+
+ check_library_exists(sqlite3 sqlite3_open "" HAVE_SQLITE3)
+ if(HAVE_SQLITE3)
+ leveldb_benchmark("benchmarks/db_bench_sqlite3.cc")
+ target_link_libraries(db_bench_sqlite3 sqlite3)
+ endif(HAVE_SQLITE3)
+
+ # check_library_exists is insufficient here because the library names have
+ # different manglings when compiled with clang or gcc, at least when installed
+ # with Homebrew on Mac.
+ set(OLD_CMAKE_REQURED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ list(APPEND CMAKE_REQUIRED_LIBRARIES kyotocabinet)
+ check_cxx_source_compiles("
+#include <kcpolydb.h>
+
+int main() {
+ kyotocabinet::TreeDB* db = new kyotocabinet::TreeDB();
+ delete db;
+ return 0;
+}
+ " HAVE_KYOTOCABINET)
+ set(CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQURED_LIBRARIES})
+ if(HAVE_KYOTOCABINET)
+ leveldb_benchmark("benchmarks/db_bench_tree_db.cc")
+ target_link_libraries(db_bench_tree_db kyotocabinet)
+ endif(HAVE_KYOTOCABINET)
+endif(LEVELDB_BUILD_BENCHMARKS)
+
+if(LEVELDB_INSTALL)
+ install(TARGETS leveldb
+ EXPORT leveldbTargets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ )
+ install(
+ FILES
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/c.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/cache.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/comparator.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/db.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/dumpfile.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/env.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/export.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/filter_policy.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/iterator.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/options.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/slice.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/status.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/table_builder.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/table.h"
+ "${LEVELDB_PUBLIC_INCLUDE_DIR}/write_batch.h"
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/leveldb
+ )
+
+ include(CMakePackageConfigHelpers)
+ write_basic_package_version_file(
+ "${PROJECT_BINARY_DIR}/leveldbConfigVersion.cmake"
+ COMPATIBILITY SameMajorVersion
+ )
+ install(
+ EXPORT leveldbTargets
+ NAMESPACE leveldb::
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/leveldb"
+ )
+ install(
+ FILES
+ "cmake/leveldbConfig.cmake"
+ "${PROJECT_BINARY_DIR}/leveldbConfigVersion.cmake"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/leveldb"
+ )
+endif(LEVELDB_INSTALL)
diff --git a/src/leveldb/CONTRIBUTING.md b/src/leveldb/CONTRIBUTING.md
index cd600ff46b..a74572a596 100644
--- a/src/leveldb/CONTRIBUTING.md
+++ b/src/leveldb/CONTRIBUTING.md
@@ -31,6 +31,6 @@ the CLA.
## Writing Code ##
-If your contribution contains code, please make sure that it follows
-[the style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml).
+If your contribution contains code, please make sure that it follows
+[the style guide](http://google.github.io/styleguide/cppguide.html).
Otherwise we will have to ask you to make changes, and that's no fun for anyone.
diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile
deleted file mode 100644
index f7cc7d736c..0000000000
--- a/src/leveldb/Makefile
+++ /dev/null
@@ -1,424 +0,0 @@
-# Copyright (c) 2011 The LevelDB Authors. All rights reserved.
-# 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.
-
-#-----------------------------------------------
-# Uncomment exactly one of the lines labelled (A), (B), and (C) below
-# to switch between compilation modes.
-
-# (A) Production use (optimized mode)
-OPT ?= -O2 -DNDEBUG
-# (B) Debug mode, w/ full line-level debugging symbols
-# OPT ?= -g2
-# (C) Profiling mode: opt, but w/debugging symbols
-# OPT ?= -O2 -g2 -DNDEBUG
-#-----------------------------------------------
-
-# detect what platform we're building on
-$(shell CC="$(CC)" CXX="$(CXX)" TARGET_OS="$(TARGET_OS)" \
- ./build_detect_platform build_config.mk ./)
-# this file is generated by the previous line to set build flags and sources
-include build_config.mk
-
-TESTS = \
- db/autocompact_test \
- db/c_test \
- db/corruption_test \
- db/db_test \
- db/dbformat_test \
- db/fault_injection_test \
- db/filename_test \
- db/log_test \
- db/recovery_test \
- db/skiplist_test \
- db/version_edit_test \
- db/version_set_test \
- db/write_batch_test \
- helpers/memenv/memenv_test \
- issues/issue178_test \
- issues/issue200_test \
- table/filter_block_test \
- table/table_test \
- util/arena_test \
- util/bloom_test \
- util/cache_test \
- util/coding_test \
- util/crc32c_test \
- util/env_posix_test \
- util/env_test \
- util/hash_test
-
-UTILS = \
- db/db_bench \
- db/leveldbutil
-
-# Put the object files in a subdirectory, but the application at the top of the object dir.
-PROGNAMES := $(notdir $(TESTS) $(UTILS))
-
-# On Linux may need libkyotocabinet-dev for dependency.
-BENCHMARKS = \
- doc/bench/db_bench_sqlite3 \
- doc/bench/db_bench_tree_db
-
-CFLAGS += -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)
-CXXFLAGS += -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT)
-
-LDFLAGS += $(PLATFORM_LDFLAGS)
-LIBS += $(PLATFORM_LIBS)
-
-SIMULATOR_OUTDIR=out-ios-x86
-DEVICE_OUTDIR=out-ios-arm
-
-ifeq ($(PLATFORM), IOS)
-# Note: iOS should probably be using libtool, not ar.
-AR=xcrun ar
-SIMULATORSDK=$(shell xcrun -sdk iphonesimulator --show-sdk-path)
-DEVICESDK=$(shell xcrun -sdk iphoneos --show-sdk-path)
-DEVICE_CFLAGS = -isysroot "$(DEVICESDK)" -arch armv6 -arch armv7 -arch armv7s -arch arm64
-SIMULATOR_CFLAGS = -isysroot "$(SIMULATORSDK)" -arch i686 -arch x86_64
-STATIC_OUTDIR=out-ios-universal
-else
-STATIC_OUTDIR=out-static
-SHARED_OUTDIR=out-shared
-STATIC_PROGRAMS := $(addprefix $(STATIC_OUTDIR)/, $(PROGNAMES))
-SHARED_PROGRAMS := $(addprefix $(SHARED_OUTDIR)/, db_bench)
-endif
-
-STATIC_LIBOBJECTS := $(addprefix $(STATIC_OUTDIR)/, $(SOURCES:.cc=.o))
-STATIC_MEMENVOBJECTS := $(addprefix $(STATIC_OUTDIR)/, $(MEMENV_SOURCES:.cc=.o))
-
-DEVICE_LIBOBJECTS := $(addprefix $(DEVICE_OUTDIR)/, $(SOURCES:.cc=.o))
-DEVICE_MEMENVOBJECTS := $(addprefix $(DEVICE_OUTDIR)/, $(MEMENV_SOURCES:.cc=.o))
-
-SIMULATOR_LIBOBJECTS := $(addprefix $(SIMULATOR_OUTDIR)/, $(SOURCES:.cc=.o))
-SIMULATOR_MEMENVOBJECTS := $(addprefix $(SIMULATOR_OUTDIR)/, $(MEMENV_SOURCES:.cc=.o))
-
-SHARED_LIBOBJECTS := $(addprefix $(SHARED_OUTDIR)/, $(SOURCES:.cc=.o))
-SHARED_MEMENVOBJECTS := $(addprefix $(SHARED_OUTDIR)/, $(MEMENV_SOURCES:.cc=.o))
-
-TESTUTIL := $(STATIC_OUTDIR)/util/testutil.o
-TESTHARNESS := $(STATIC_OUTDIR)/util/testharness.o $(TESTUTIL)
-
-STATIC_TESTOBJS := $(addprefix $(STATIC_OUTDIR)/, $(addsuffix .o, $(TESTS)))
-STATIC_UTILOBJS := $(addprefix $(STATIC_OUTDIR)/, $(addsuffix .o, $(UTILS)))
-STATIC_ALLOBJS := $(STATIC_LIBOBJECTS) $(STATIC_MEMENVOBJECTS) $(STATIC_TESTOBJS) $(STATIC_UTILOBJS) $(TESTHARNESS)
-DEVICE_ALLOBJS := $(DEVICE_LIBOBJECTS) $(DEVICE_MEMENVOBJECTS)
-SIMULATOR_ALLOBJS := $(SIMULATOR_LIBOBJECTS) $(SIMULATOR_MEMENVOBJECTS)
-
-default: all
-
-# Should we build shared libraries?
-ifneq ($(PLATFORM_SHARED_EXT),)
-
-# Many leveldb test apps use non-exported API's. Only build a subset for testing.
-SHARED_ALLOBJS := $(SHARED_LIBOBJECTS) $(SHARED_MEMENVOBJECTS) $(TESTHARNESS)
-
-ifneq ($(PLATFORM_SHARED_VERSIONED),true)
-SHARED_LIB1 = libleveldb.$(PLATFORM_SHARED_EXT)
-SHARED_LIB2 = $(SHARED_LIB1)
-SHARED_LIB3 = $(SHARED_LIB1)
-SHARED_LIBS = $(SHARED_LIB1)
-SHARED_MEMENVLIB = $(SHARED_OUTDIR)/libmemenv.a
-else
-# Update db.h if you change these.
-SHARED_VERSION_MAJOR = 1
-SHARED_VERSION_MINOR = 20
-SHARED_LIB1 = libleveldb.$(PLATFORM_SHARED_EXT)
-SHARED_LIB2 = $(SHARED_LIB1).$(SHARED_VERSION_MAJOR)
-SHARED_LIB3 = $(SHARED_LIB1).$(SHARED_VERSION_MAJOR).$(SHARED_VERSION_MINOR)
-SHARED_LIBS = $(SHARED_OUTDIR)/$(SHARED_LIB1) $(SHARED_OUTDIR)/$(SHARED_LIB2) $(SHARED_OUTDIR)/$(SHARED_LIB3)
-$(SHARED_OUTDIR)/$(SHARED_LIB1): $(SHARED_OUTDIR)/$(SHARED_LIB3)
- ln -fs $(SHARED_LIB3) $(SHARED_OUTDIR)/$(SHARED_LIB1)
-$(SHARED_OUTDIR)/$(SHARED_LIB2): $(SHARED_OUTDIR)/$(SHARED_LIB3)
- ln -fs $(SHARED_LIB3) $(SHARED_OUTDIR)/$(SHARED_LIB2)
-SHARED_MEMENVLIB = $(SHARED_OUTDIR)/libmemenv.a
-endif
-
-$(SHARED_OUTDIR)/$(SHARED_LIB3): $(SHARED_LIBOBJECTS)
- $(CXX) $(LDFLAGS) $(PLATFORM_SHARED_LDFLAGS)$(SHARED_LIB2) $(SHARED_LIBOBJECTS) -o $(SHARED_OUTDIR)/$(SHARED_LIB3) $(LIBS)
-
-endif # PLATFORM_SHARED_EXT
-
-all: $(SHARED_LIBS) $(SHARED_PROGRAMS) $(STATIC_OUTDIR)/libleveldb.a $(STATIC_OUTDIR)/libmemenv.a $(STATIC_PROGRAMS)
-
-check: $(STATIC_PROGRAMS)
- for t in $(notdir $(TESTS)); do echo "***** Running $$t"; $(STATIC_OUTDIR)/$$t || exit 1; done
-
-clean:
- -rm -rf out-static out-shared out-ios-x86 out-ios-arm out-ios-universal
- -rm -f build_config.mk
- -rm -rf ios-x86 ios-arm
-
-$(STATIC_OUTDIR):
- mkdir $@
-
-$(STATIC_OUTDIR)/db: | $(STATIC_OUTDIR)
- mkdir $@
-
-$(STATIC_OUTDIR)/helpers/memenv: | $(STATIC_OUTDIR)
- mkdir -p $@
-
-$(STATIC_OUTDIR)/port: | $(STATIC_OUTDIR)
- mkdir $@
-
-$(STATIC_OUTDIR)/table: | $(STATIC_OUTDIR)
- mkdir $@
-
-$(STATIC_OUTDIR)/util: | $(STATIC_OUTDIR)
- mkdir $@
-
-.PHONY: STATIC_OBJDIRS
-STATIC_OBJDIRS: \
- $(STATIC_OUTDIR)/db \
- $(STATIC_OUTDIR)/port \
- $(STATIC_OUTDIR)/table \
- $(STATIC_OUTDIR)/util \
- $(STATIC_OUTDIR)/helpers/memenv
-
-$(SHARED_OUTDIR):
- mkdir $@
-
-$(SHARED_OUTDIR)/db: | $(SHARED_OUTDIR)
- mkdir $@
-
-$(SHARED_OUTDIR)/helpers/memenv: | $(SHARED_OUTDIR)
- mkdir -p $@
-
-$(SHARED_OUTDIR)/port: | $(SHARED_OUTDIR)
- mkdir $@
-
-$(SHARED_OUTDIR)/table: | $(SHARED_OUTDIR)
- mkdir $@
-
-$(SHARED_OUTDIR)/util: | $(SHARED_OUTDIR)
- mkdir $@
-
-.PHONY: SHARED_OBJDIRS
-SHARED_OBJDIRS: \
- $(SHARED_OUTDIR)/db \
- $(SHARED_OUTDIR)/port \
- $(SHARED_OUTDIR)/table \
- $(SHARED_OUTDIR)/util \
- $(SHARED_OUTDIR)/helpers/memenv
-
-$(DEVICE_OUTDIR):
- mkdir $@
-
-$(DEVICE_OUTDIR)/db: | $(DEVICE_OUTDIR)
- mkdir $@
-
-$(DEVICE_OUTDIR)/helpers/memenv: | $(DEVICE_OUTDIR)
- mkdir -p $@
-
-$(DEVICE_OUTDIR)/port: | $(DEVICE_OUTDIR)
- mkdir $@
-
-$(DEVICE_OUTDIR)/table: | $(DEVICE_OUTDIR)
- mkdir $@
-
-$(DEVICE_OUTDIR)/util: | $(DEVICE_OUTDIR)
- mkdir $@
-
-.PHONY: DEVICE_OBJDIRS
-DEVICE_OBJDIRS: \
- $(DEVICE_OUTDIR)/db \
- $(DEVICE_OUTDIR)/port \
- $(DEVICE_OUTDIR)/table \
- $(DEVICE_OUTDIR)/util \
- $(DEVICE_OUTDIR)/helpers/memenv
-
-$(SIMULATOR_OUTDIR):
- mkdir $@
-
-$(SIMULATOR_OUTDIR)/db: | $(SIMULATOR_OUTDIR)
- mkdir $@
-
-$(SIMULATOR_OUTDIR)/helpers/memenv: | $(SIMULATOR_OUTDIR)
- mkdir -p $@
-
-$(SIMULATOR_OUTDIR)/port: | $(SIMULATOR_OUTDIR)
- mkdir $@
-
-$(SIMULATOR_OUTDIR)/table: | $(SIMULATOR_OUTDIR)
- mkdir $@
-
-$(SIMULATOR_OUTDIR)/util: | $(SIMULATOR_OUTDIR)
- mkdir $@
-
-.PHONY: SIMULATOR_OBJDIRS
-SIMULATOR_OBJDIRS: \
- $(SIMULATOR_OUTDIR)/db \
- $(SIMULATOR_OUTDIR)/port \
- $(SIMULATOR_OUTDIR)/table \
- $(SIMULATOR_OUTDIR)/util \
- $(SIMULATOR_OUTDIR)/helpers/memenv
-
-$(STATIC_ALLOBJS): | STATIC_OBJDIRS
-$(DEVICE_ALLOBJS): | DEVICE_OBJDIRS
-$(SIMULATOR_ALLOBJS): | SIMULATOR_OBJDIRS
-$(SHARED_ALLOBJS): | SHARED_OBJDIRS
-
-ifeq ($(PLATFORM), IOS)
-$(DEVICE_OUTDIR)/libleveldb.a: $(DEVICE_LIBOBJECTS)
- rm -f $@
- $(AR) -rs $@ $(DEVICE_LIBOBJECTS)
-
-$(SIMULATOR_OUTDIR)/libleveldb.a: $(SIMULATOR_LIBOBJECTS)
- rm -f $@
- $(AR) -rs $@ $(SIMULATOR_LIBOBJECTS)
-
-$(DEVICE_OUTDIR)/libmemenv.a: $(DEVICE_MEMENVOBJECTS)
- rm -f $@
- $(AR) -rs $@ $(DEVICE_MEMENVOBJECTS)
-
-$(SIMULATOR_OUTDIR)/libmemenv.a: $(SIMULATOR_MEMENVOBJECTS)
- rm -f $@
- $(AR) -rs $@ $(SIMULATOR_MEMENVOBJECTS)
-
-# For iOS, create universal object libraries to be used on both the simulator and
-# a device.
-$(STATIC_OUTDIR)/libleveldb.a: $(STATIC_OUTDIR) $(DEVICE_OUTDIR)/libleveldb.a $(SIMULATOR_OUTDIR)/libleveldb.a
- lipo -create $(DEVICE_OUTDIR)/libleveldb.a $(SIMULATOR_OUTDIR)/libleveldb.a -output $@
-
-$(STATIC_OUTDIR)/libmemenv.a: $(STATIC_OUTDIR) $(DEVICE_OUTDIR)/libmemenv.a $(SIMULATOR_OUTDIR)/libmemenv.a
- lipo -create $(DEVICE_OUTDIR)/libmemenv.a $(SIMULATOR_OUTDIR)/libmemenv.a -output $@
-else
-$(STATIC_OUTDIR)/libleveldb.a:$(STATIC_LIBOBJECTS)
- rm -f $@
- $(AR) -rs $@ $(STATIC_LIBOBJECTS)
-
-$(STATIC_OUTDIR)/libmemenv.a:$(STATIC_MEMENVOBJECTS)
- rm -f $@
- $(AR) -rs $@ $(STATIC_MEMENVOBJECTS)
-endif
-
-$(SHARED_MEMENVLIB):$(SHARED_MEMENVOBJECTS)
- rm -f $@
- $(AR) -rs $@ $(SHARED_MEMENVOBJECTS)
-
-$(STATIC_OUTDIR)/db_bench:db/db_bench.cc $(STATIC_LIBOBJECTS) $(TESTUTIL)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/db_bench.cc $(STATIC_LIBOBJECTS) $(TESTUTIL) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/db_bench_sqlite3:doc/bench/db_bench_sqlite3.cc $(STATIC_LIBOBJECTS) $(TESTUTIL)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) doc/bench/db_bench_sqlite3.cc $(STATIC_LIBOBJECTS) $(TESTUTIL) -o $@ -lsqlite3 $(LIBS)
-
-$(STATIC_OUTDIR)/db_bench_tree_db:doc/bench/db_bench_tree_db.cc $(STATIC_LIBOBJECTS) $(TESTUTIL)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) doc/bench/db_bench_tree_db.cc $(STATIC_LIBOBJECTS) $(TESTUTIL) -o $@ -lkyotocabinet $(LIBS)
-
-$(STATIC_OUTDIR)/leveldbutil:db/leveldbutil.cc $(STATIC_LIBOBJECTS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/leveldbutil.cc $(STATIC_LIBOBJECTS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/arena_test:util/arena_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) util/arena_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/autocompact_test:db/autocompact_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/autocompact_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/bloom_test:util/bloom_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) util/bloom_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/c_test:$(STATIC_OUTDIR)/db/c_test.o $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(STATIC_OUTDIR)/db/c_test.o $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/cache_test:util/cache_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) util/cache_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/coding_test:util/coding_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) util/coding_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/corruption_test:db/corruption_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/corruption_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/crc32c_test:util/crc32c_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) util/crc32c_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/db_test:db/db_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/db_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/dbformat_test:db/dbformat_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/dbformat_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/env_posix_test:util/env_posix_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) util/env_posix_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/env_test:util/env_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) util/env_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/fault_injection_test:db/fault_injection_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/fault_injection_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/filename_test:db/filename_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/filename_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/filter_block_test:table/filter_block_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) table/filter_block_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/hash_test:util/hash_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) util/hash_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/issue178_test:issues/issue178_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) issues/issue178_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/issue200_test:issues/issue200_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) issues/issue200_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/log_test:db/log_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/log_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/recovery_test:db/recovery_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/recovery_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/table_test:table/table_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) table/table_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/skiplist_test:db/skiplist_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/skiplist_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/version_edit_test:db/version_edit_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/version_edit_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/version_set_test:db/version_set_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/version_set_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/write_batch_test:db/write_batch_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) db/write_batch_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
-
-$(STATIC_OUTDIR)/memenv_test:$(STATIC_OUTDIR)/helpers/memenv/memenv_test.o $(STATIC_OUTDIR)/libmemenv.a $(STATIC_OUTDIR)/libleveldb.a $(TESTHARNESS)
- $(XCRUN) $(CXX) $(LDFLAGS) $(STATIC_OUTDIR)/helpers/memenv/memenv_test.o $(STATIC_OUTDIR)/libmemenv.a $(STATIC_OUTDIR)/libleveldb.a $(TESTHARNESS) -o $@ $(LIBS)
-
-$(SHARED_OUTDIR)/db_bench:$(SHARED_OUTDIR)/db/db_bench.o $(SHARED_LIBS) $(TESTUTIL)
- $(XCRUN) $(CXX) $(LDFLAGS) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SHARED_OUTDIR)/db/db_bench.o $(TESTUTIL) $(SHARED_OUTDIR)/$(SHARED_LIB3) -o $@ $(LIBS)
-
-.PHONY: run-shared
-run-shared: $(SHARED_OUTDIR)/db_bench
- LD_LIBRARY_PATH=$(SHARED_OUTDIR) $(SHARED_OUTDIR)/db_bench
-
-$(SIMULATOR_OUTDIR)/%.o: %.cc
- xcrun -sdk iphonesimulator $(CXX) $(CXXFLAGS) $(SIMULATOR_CFLAGS) -c $< -o $@
-
-$(DEVICE_OUTDIR)/%.o: %.cc
- xcrun -sdk iphoneos $(CXX) $(CXXFLAGS) $(DEVICE_CFLAGS) -c $< -o $@
-
-$(SIMULATOR_OUTDIR)/%.o: %.c
- xcrun -sdk iphonesimulator $(CC) $(CFLAGS) $(SIMULATOR_CFLAGS) -c $< -o $@
-
-$(DEVICE_OUTDIR)/%.o: %.c
- xcrun -sdk iphoneos $(CC) $(CFLAGS) $(DEVICE_CFLAGS) -c $< -o $@
-
-$(STATIC_OUTDIR)/%.o: %.cc
- $(CXX) $(CXXFLAGS) -c $< -o $@
-
-$(STATIC_OUTDIR)/%.o: %.c
- $(CC) $(CFLAGS) -c $< -o $@
-
-$(SHARED_OUTDIR)/%.o: %.cc
- $(CXX) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) -c $< -o $@
-
-$(SHARED_OUTDIR)/%.o: %.c
- $(CC) $(CFLAGS) $(PLATFORM_SHARED_CFLAGS) -c $< -o $@
-
-$(STATIC_OUTDIR)/port/port_posix_sse.o: port/port_posix_sse.cc
- $(CXX) $(CXXFLAGS) $(PLATFORM_SSEFLAGS) -c $< -o $@
-
-$(SHARED_OUTDIR)/port/port_posix_sse.o: port/port_posix_sse.cc
- $(CXX) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(PLATFORM_SSEFLAGS) -c $< -o $@
diff --git a/src/leveldb/README.md b/src/leveldb/README.md
index a010c50858..dadfd5693e 100644
--- a/src/leveldb/README.md
+++ b/src/leveldb/README.md
@@ -1,10 +1,12 @@
**LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.**
[![Build Status](https://travis-ci.org/google/leveldb.svg?branch=master)](https://travis-ci.org/google/leveldb)
+[![Build status](https://ci.appveyor.com/api/projects/status/g2j5j4rfkda6eyw5/branch/master?svg=true)](https://ci.appveyor.com/project/pwnall/leveldb)
Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com)
# Features
+
* Keys and values are arbitrary byte arrays.
* Data is stored sorted by key.
* Callers can provide a custom comparison function to override the sort order.
@@ -16,15 +18,55 @@ Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com)
* External activity (file system operations etc.) is relayed through a virtual interface so users can customize the operating system interactions.
# Documentation
- [LevelDB library documentation](https://github.com/google/leveldb/blob/master/doc/index.md) is online and bundled with the source code.
+ [LevelDB library documentation](https://github.com/google/leveldb/blob/master/doc/index.md) is online and bundled with the source code.
# Limitations
+
* This is not a SQL database. It does not have a relational data model, it does not support SQL queries, and it has no support for indexes.
* Only a single process (possibly multi-threaded) can access a particular database at a time.
* There is no client-server support builtin to the library. An application that needs such support will have to wrap their own server around the library.
+# Building
+
+This project supports [CMake](https://cmake.org/) out of the box.
+
+### Build for POSIX
+
+Quick start:
+
+```bash
+mkdir -p build && cd build
+cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build .
+```
+
+### Building for Windows
+
+First generate the Visual Studio 2017 project/solution files:
+
+```cmd
+mkdir build
+cd build
+cmake -G "Visual Studio 15" ..
+```
+The default default will build for x86. For 64-bit run:
+
+```cmd
+cmake -G "Visual Studio 15 Win64" ..
+```
+
+To compile the Windows solution from the command-line:
+
+```cmd
+devenv /build Debug leveldb.sln
+```
+
+or open leveldb.sln in Visual Studio and build from within.
+
+Please see the CMake documentation and `CMakeLists.txt` for more advanced usage.
+
# Contributing to the leveldb Project
+
The leveldb project welcomes contributions. leveldb's primary goal is to be
a reliable and fast key/value store. Changes that are in line with the
features/limitations outlined above, and meet the requirements below,
@@ -32,10 +74,10 @@ will be considered.
Contribution requirements:
-1. **POSIX only**. We _generally_ will only accept changes that are both
- compiled, and tested on a POSIX platform - usually Linux. Very small
- changes will sometimes be accepted, but consider that more of an
- exception than the rule.
+1. **Tested platforms only**. We _generally_ will only accept changes for
+ platforms that are compiled and tested. This means POSIX (for Linux and
+ macOS) or Windows. Very small changes will sometimes be accepted, but
+ consider that more of an exception than the rule.
2. **Stable API**. We strive very hard to maintain a stable API. Changes that
require changes for projects using leveldb _might_ be rejected without
@@ -44,7 +86,16 @@ Contribution requirements:
3. **Tests**: All changes must be accompanied by a new (or changed) test, or
a sufficient explanation as to why a new (or changed) test is not required.
+4. **Consistent Style**: This project conforms to the
+ [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html).
+ To ensure your changes are properly formatted please run:
+
+ ```
+ clang-format -i --style=file <file>
+ ```
+
## Submitting a Pull Request
+
Before any pull request will be accepted the author must first sign a
Contributor License Agreement (CLA) at https://cla.developers.google.com/.
@@ -138,37 +189,37 @@ uncompressed blocks in memory, the read performance improves again:
See [doc/index.md](doc/index.md) for more explanation. See
[doc/impl.md](doc/impl.md) for a brief overview of the implementation.
-The public interface is in include/*.h. Callers should not include or
+The public interface is in include/leveldb/*.h. Callers should not include or
rely on the details of any other header files in this package. Those
internal APIs may be changed without warning.
Guide to header files:
-* **include/db.h**: Main interface to the DB: Start here
+* **include/leveldb/db.h**: Main interface to the DB: Start here.
-* **include/options.h**: Control over the behavior of an entire database,
+* **include/leveldb/options.h**: Control over the behavior of an entire database,
and also control over the behavior of individual reads and writes.
-* **include/comparator.h**: Abstraction for user-specified comparison function.
+* **include/leveldb/comparator.h**: Abstraction for user-specified comparison function.
If you want just bytewise comparison of keys, you can use the default
comparator, but clients can write their own comparator implementations if they
-want custom ordering (e.g. to handle different character encodings, etc.)
+want custom ordering (e.g. to handle different character encodings, etc.).
-* **include/iterator.h**: Interface for iterating over data. You can get
+* **include/leveldb/iterator.h**: Interface for iterating over data. You can get
an iterator from a DB object.
-* **include/write_batch.h**: Interface for atomically applying multiple
+* **include/leveldb/write_batch.h**: Interface for atomically applying multiple
updates to a database.
-* **include/slice.h**: A simple module for maintaining a pointer and a
+* **include/leveldb/slice.h**: A simple module for maintaining a pointer and a
length into some other byte array.
-* **include/status.h**: Status is returned from many of the public interfaces
+* **include/leveldb/status.h**: Status is returned from many of the public interfaces
and is used to report success and various kinds of errors.
-* **include/env.h**:
+* **include/leveldb/env.h**:
Abstraction of the OS environment. A posix implementation of this interface is
-in util/env_posix.cc
+in util/env_posix.cc.
-* **include/table.h, include/table_builder.h**: Lower-level modules that most
-clients probably won't use directly
+* **include/leveldb/table.h, include/leveldb/table_builder.h**: Lower-level modules that most
+clients probably won't use directly.
diff --git a/src/leveldb/WINDOWS.md b/src/leveldb/WINDOWS.md
deleted file mode 100644
index 5b76c2448f..0000000000
--- a/src/leveldb/WINDOWS.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# Building LevelDB On Windows
-
-## Prereqs
-
-Install the [Windows Software Development Kit version 7.1](http://www.microsoft.com/downloads/dlx/en-us/listdetailsview.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b).
-
-Download and extract the [Snappy source distribution](http://snappy.googlecode.com/files/snappy-1.0.5.tar.gz)
-
-1. Open the "Windows SDK 7.1 Command Prompt" :
- Start Menu -> "Microsoft Windows SDK v7.1" > "Windows SDK 7.1 Command Prompt"
-2. Change the directory to the leveldb project
-
-## Building the Static lib
-
-* 32 bit Version
-
- setenv /x86
- msbuild.exe /p:Configuration=Release /p:Platform=Win32 /p:Snappy=..\snappy-1.0.5
-
-* 64 bit Version
-
- setenv /x64
- msbuild.exe /p:Configuration=Release /p:Platform=x64 /p:Snappy=..\snappy-1.0.5
-
-
-## Building and Running the Benchmark app
-
-* 32 bit Version
-
- setenv /x86
- msbuild.exe /p:Configuration=Benchmark /p:Platform=Win32 /p:Snappy=..\snappy-1.0.5
- Benchmark\leveldb.exe
-
-* 64 bit Version
-
- setenv /x64
- msbuild.exe /p:Configuration=Benchmark /p:Platform=x64 /p:Snappy=..\snappy-1.0.5
- x64\Benchmark\leveldb.exe
-
diff --git a/src/leveldb/db/db_bench.cc b/src/leveldb/benchmarks/db_bench.cc
index 3ad19a512b..3696023b70 100644
--- a/src/leveldb/db/db_bench.cc
+++ b/src/leveldb/benchmarks/db_bench.cc
@@ -2,14 +2,14 @@
// 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.
-#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
-#include "db/db_impl.h"
-#include "db/version_set.h"
+#include <sys/types.h>
+
#include "leveldb/cache.h"
#include "leveldb/db.h"
#include "leveldb/env.h"
+#include "leveldb/filter_policy.h"
#include "leveldb/write_batch.h"
#include "port/port.h"
#include "util/crc32c.h"
@@ -35,7 +35,6 @@
// seekrandom -- N random seeks
// open -- cost of opening a DB
// crc32c -- repeated crc32c of 4K of data
-// acquireload -- load N*1000 times
// Meta operations:
// compact -- Compact the entire DB
// stats -- Print DB stats
@@ -57,9 +56,7 @@ static const char* FLAGS_benchmarks =
"fill100K,"
"crc32c,"
"snappycomp,"
- "snappyuncomp,"
- "acquireload,"
- ;
+ "snappyuncomp,";
// Number of key/values to place in database
static int FLAGS_num = 1000000;
@@ -112,12 +109,12 @@ static bool FLAGS_use_existing_db = false;
static bool FLAGS_reuse_logs = false;
// Use the db with the following name.
-static const char* FLAGS_db = NULL;
+static const char* FLAGS_db = nullptr;
namespace leveldb {
namespace {
-leveldb::Env* g_env = NULL;
+leveldb::Env* g_env = nullptr;
// Helper for quickly generating random data.
class RandomGenerator {
@@ -158,7 +155,7 @@ static Slice TrimSpace(Slice s) {
start++;
}
size_t limit = s.size();
- while (limit > start && isspace(s[limit-1])) {
+ while (limit > start && isspace(s[limit - 1])) {
limit--;
}
return Slice(s.data() + start, limit - start);
@@ -190,14 +187,12 @@ class Stats {
void Start() {
next_report_ = 100;
- last_op_finish_ = start_;
hist_.Clear();
done_ = 0;
bytes_ = 0;
seconds_ = 0;
- start_ = g_env->NowMicros();
- finish_ = start_;
message_.clear();
+ start_ = finish_ = last_op_finish_ = g_env->NowMicros();
}
void Merge(const Stats& other) {
@@ -217,9 +212,7 @@ class Stats {
seconds_ = (finish_ - start_) * 1e-6;
}
- void AddMessage(Slice msg) {
- AppendWithSpace(&message_, msg);
- }
+ void AddMessage(Slice msg) { AppendWithSpace(&message_, msg); }
void FinishedSingleOp() {
if (FLAGS_histogram) {
@@ -235,21 +228,26 @@ class Stats {
done_++;
if (done_ >= next_report_) {
- if (next_report_ < 1000) next_report_ += 100;
- else if (next_report_ < 5000) next_report_ += 500;
- else if (next_report_ < 10000) next_report_ += 1000;
- else if (next_report_ < 50000) next_report_ += 5000;
- else if (next_report_ < 100000) next_report_ += 10000;
- else if (next_report_ < 500000) next_report_ += 50000;
- else next_report_ += 100000;
+ if (next_report_ < 1000)
+ next_report_ += 100;
+ else if (next_report_ < 5000)
+ next_report_ += 500;
+ else if (next_report_ < 10000)
+ next_report_ += 1000;
+ else if (next_report_ < 50000)
+ next_report_ += 5000;
+ else if (next_report_ < 100000)
+ next_report_ += 10000;
+ else if (next_report_ < 500000)
+ next_report_ += 50000;
+ else
+ next_report_ += 100000;
fprintf(stderr, "... finished %d ops%30s\r", done_, "");
fflush(stderr);
}
}
- void AddBytes(int64_t n) {
- bytes_ += n;
- }
+ void AddBytes(int64_t n) { bytes_ += n; }
void Report(const Slice& name) {
// Pretend at least one op was done in case we are running a benchmark
@@ -268,11 +266,8 @@ class Stats {
}
AppendWithSpace(&extra, message_);
- fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n",
- name.ToString().c_str(),
- seconds_ * 1e6 / done_,
- (extra.empty() ? "" : " "),
- extra.c_str());
+ fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", name.ToString().c_str(),
+ seconds_ * 1e6 / done_, (extra.empty() ? "" : " "), extra.c_str());
if (FLAGS_histogram) {
fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());
}
@@ -283,8 +278,8 @@ class Stats {
// State shared by all concurrent executions of the same benchmark.
struct SharedState {
port::Mutex mu;
- port::CondVar cv;
- int total;
+ port::CondVar cv GUARDED_BY(mu);
+ int total GUARDED_BY(mu);
// Each thread goes through the following states:
// (1) initializing
@@ -292,24 +287,22 @@ struct SharedState {
// (3) running
// (4) done
- int num_initialized;
- int num_done;
- bool start;
+ int num_initialized GUARDED_BY(mu);
+ int num_done GUARDED_BY(mu);
+ bool start GUARDED_BY(mu);
- SharedState() : cv(&mu) { }
+ SharedState(int total)
+ : cv(&mu), total(total), num_initialized(0), num_done(0), start(false) {}
};
// Per-thread state for concurrent executions of the same benchmark.
struct ThreadState {
- int tid; // 0..n-1 when running in n threads
- Random rand; // Has different seeds for different threads
+ int tid; // 0..n-1 when running in n threads
+ Random rand; // Has different seeds for different threads
Stats stats;
SharedState* shared;
- ThreadState(int index)
- : tid(index),
- rand(1000 + index) {
- }
+ ThreadState(int index) : tid(index), rand(1000 + index), shared(nullptr) {}
};
} // namespace
@@ -335,20 +328,20 @@ class Benchmark {
static_cast<int>(FLAGS_value_size * FLAGS_compression_ratio + 0.5));
fprintf(stdout, "Entries: %d\n", num_);
fprintf(stdout, "RawSize: %.1f MB (estimated)\n",
- ((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_)
- / 1048576.0));
+ ((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_) /
+ 1048576.0));
fprintf(stdout, "FileSize: %.1f MB (estimated)\n",
- (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_)
- / 1048576.0));
+ (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) /
+ 1048576.0));
PrintWarnings();
fprintf(stdout, "------------------------------------------------\n");
}
void PrintWarnings() {
#if defined(__GNUC__) && !defined(__OPTIMIZE__)
- fprintf(stdout,
- "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n"
- );
+ fprintf(
+ stdout,
+ "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n");
#endif
#ifndef NDEBUG
fprintf(stdout,
@@ -366,22 +359,22 @@ class Benchmark {
}
void PrintEnvironment() {
- fprintf(stderr, "LevelDB: version %d.%d\n",
- kMajorVersion, kMinorVersion);
+ fprintf(stderr, "LevelDB: version %d.%d\n", kMajorVersion,
+ kMinorVersion);
#if defined(__linux)
- time_t now = time(NULL);
+ time_t now = time(nullptr);
fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
- if (cpuinfo != NULL) {
+ if (cpuinfo != nullptr) {
char line[1000];
int num_cpus = 0;
std::string cpu_type;
std::string cache_size;
- while (fgets(line, sizeof(line), cpuinfo) != NULL) {
+ while (fgets(line, sizeof(line), cpuinfo) != nullptr) {
const char* sep = strchr(line, ':');
- if (sep == NULL) {
+ if (sep == nullptr) {
continue;
}
Slice key = TrimSpace(Slice(line, sep - 1 - line));
@@ -402,16 +395,16 @@ class Benchmark {
public:
Benchmark()
- : cache_(FLAGS_cache_size >= 0 ? NewLRUCache(FLAGS_cache_size) : NULL),
- filter_policy_(FLAGS_bloom_bits >= 0
- ? NewBloomFilterPolicy(FLAGS_bloom_bits)
- : NULL),
- db_(NULL),
- num_(FLAGS_num),
- value_size_(FLAGS_value_size),
- entries_per_batch_(1),
- reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),
- heap_counter_(0) {
+ : cache_(FLAGS_cache_size >= 0 ? NewLRUCache(FLAGS_cache_size) : nullptr),
+ filter_policy_(FLAGS_bloom_bits >= 0
+ ? NewBloomFilterPolicy(FLAGS_bloom_bits)
+ : nullptr),
+ db_(nullptr),
+ num_(FLAGS_num),
+ value_size_(FLAGS_value_size),
+ entries_per_batch_(1),
+ reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),
+ heap_counter_(0) {
std::vector<std::string> files;
g_env->GetChildren(FLAGS_db, &files);
for (size_t i = 0; i < files.size(); i++) {
@@ -435,12 +428,12 @@ class Benchmark {
Open();
const char* benchmarks = FLAGS_benchmarks;
- while (benchmarks != NULL) {
+ while (benchmarks != nullptr) {
const char* sep = strchr(benchmarks, ',');
Slice name;
- if (sep == NULL) {
+ if (sep == nullptr) {
name = benchmarks;
- benchmarks = NULL;
+ benchmarks = nullptr;
} else {
name = Slice(benchmarks, sep - benchmarks);
benchmarks = sep + 1;
@@ -453,7 +446,7 @@ class Benchmark {
entries_per_batch_ = 1;
write_options_ = WriteOptions();
- void (Benchmark::*method)(ThreadState*) = NULL;
+ void (Benchmark::*method)(ThreadState*) = nullptr;
bool fresh_db = false;
int num_threads = FLAGS_threads;
@@ -510,8 +503,6 @@ class Benchmark {
method = &Benchmark::Compact;
} else if (name == Slice("crc32c")) {
method = &Benchmark::Crc32c;
- } else if (name == Slice("acquireload")) {
- method = &Benchmark::AcquireLoad;
} else if (name == Slice("snappycomp")) {
method = &Benchmark::SnappyCompress;
} else if (name == Slice("snappyuncomp")) {
@@ -523,7 +514,7 @@ class Benchmark {
} else if (name == Slice("sstables")) {
PrintStats("leveldb.sstables");
} else {
- if (name != Slice()) { // No error message for empty name
+ if (!name.empty()) { // No error message for empty name
fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str());
}
}
@@ -532,16 +523,16 @@ class Benchmark {
if (FLAGS_use_existing_db) {
fprintf(stdout, "%-12s : skipped (--use_existing_db is true)\n",
name.ToString().c_str());
- method = NULL;
+ method = nullptr;
} else {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
DestroyDB(FLAGS_db, Options());
Open();
}
}
- if (method != NULL) {
+ if (method != nullptr) {
RunBenchmark(num_threads, name, method);
}
}
@@ -585,11 +576,7 @@ class Benchmark {
void RunBenchmark(int n, Slice name,
void (Benchmark::*method)(ThreadState*)) {
- SharedState shared;
- shared.total = n;
- shared.num_initialized = 0;
- shared.num_done = 0;
- shared.start = false;
+ SharedState shared(n);
ThreadArg* arg = new ThreadArg[n];
for (int i = 0; i < n; i++) {
@@ -643,22 +630,6 @@ class Benchmark {
thread->stats.AddMessage(label);
}
- void AcquireLoad(ThreadState* thread) {
- int dummy;
- port::AtomicPointer ap(&dummy);
- int count = 0;
- void *ptr = NULL;
- thread->stats.AddMessage("(each op is 1000 loads)");
- while (count < 100000) {
- for (int i = 0; i < 1000; i++) {
- ptr = ap.Acquire_Load();
- }
- count++;
- thread->stats.FinishedSingleOp();
- }
- if (ptr == NULL) exit(1); // Disable unused variable warning.
- }
-
void SnappyCompress(ThreadState* thread) {
RandomGenerator gen;
Slice input = gen.Generate(Options().block_size);
@@ -692,8 +663,8 @@ class Benchmark {
int64_t bytes = 0;
char* uncompressed = new char[input.size()];
while (ok && bytes < 1024 * 1048576) { // Compress 1G
- ok = port::Snappy_Uncompress(compressed.data(), compressed.size(),
- uncompressed);
+ ok = port::Snappy_Uncompress(compressed.data(), compressed.size(),
+ uncompressed);
bytes += input.size();
thread->stats.FinishedSingleOp();
}
@@ -707,7 +678,7 @@ class Benchmark {
}
void Open() {
- assert(db_ == NULL);
+ assert(db_ == nullptr);
Options options;
options.env = g_env;
options.create_if_missing = !FLAGS_use_existing_db;
@@ -733,13 +704,9 @@ class Benchmark {
}
}
- void WriteSeq(ThreadState* thread) {
- DoWrite(thread, true);
- }
+ void WriteSeq(ThreadState* thread) { DoWrite(thread, true); }
- void WriteRandom(ThreadState* thread) {
- DoWrite(thread, false);
- }
+ void WriteRandom(ThreadState* thread) { DoWrite(thread, false); }
void DoWrite(ThreadState* thread, bool seq) {
if (num_ != FLAGS_num) {
@@ -755,7 +722,7 @@ class Benchmark {
for (int i = 0; i < num_; i += entries_per_batch_) {
batch.Clear();
for (int j = 0; j < entries_per_batch_; j++) {
- const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num);
+ const int k = seq ? i + j : (thread->rand.Next() % FLAGS_num);
char key[100];
snprintf(key, sizeof(key), "%016d", k);
batch.Put(key, gen.Generate(value_size_));
@@ -865,7 +832,7 @@ class Benchmark {
for (int i = 0; i < num_; i += entries_per_batch_) {
batch.Clear();
for (int j = 0; j < entries_per_batch_; j++) {
- const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num);
+ const int k = seq ? i + j : (thread->rand.Next() % FLAGS_num);
char key[100];
snprintf(key, sizeof(key), "%016d", k);
batch.Delete(key);
@@ -879,13 +846,9 @@ class Benchmark {
}
}
- void DeleteSeq(ThreadState* thread) {
- DoDelete(thread, true);
- }
+ void DeleteSeq(ThreadState* thread) { DoDelete(thread, true); }
- void DeleteRandom(ThreadState* thread) {
- DoDelete(thread, false);
- }
+ void DeleteRandom(ThreadState* thread) { DoDelete(thread, false); }
void ReadWhileWriting(ThreadState* thread) {
if (thread->tid > 0) {
@@ -917,9 +880,7 @@ class Benchmark {
}
}
- void Compact(ThreadState* thread) {
- db_->CompactRange(NULL, NULL);
- }
+ void Compact(ThreadState* thread) { db_->CompactRange(nullptr, nullptr); }
void PrintStats(const char* key) {
std::string stats;
@@ -1008,10 +969,10 @@ int main(int argc, char** argv) {
leveldb::g_env = leveldb::Env::Default();
// Choose a location for the test database if none given with --db=<path>
- if (FLAGS_db == NULL) {
- leveldb::g_env->GetTestDirectory(&default_db_path);
- default_db_path += "/dbbench";
- FLAGS_db = default_db_path.c_str();
+ if (FLAGS_db == nullptr) {
+ leveldb::g_env->GetTestDirectory(&default_db_path);
+ default_db_path += "/dbbench";
+ FLAGS_db = default_db_path.c_str();
}
leveldb::Benchmark benchmark;
diff --git a/src/leveldb/doc/bench/db_bench_sqlite3.cc b/src/leveldb/benchmarks/db_bench_sqlite3.cc
index e63aaa8dcc..f183f4fcfd 100644
--- a/src/leveldb/doc/bench/db_bench_sqlite3.cc
+++ b/src/leveldb/benchmarks/db_bench_sqlite3.cc
@@ -2,9 +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.
+#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
-#include <sqlite3.h>
+
#include "util/histogram.h"
#include "util/random.h"
#include "util/testutil.h"
@@ -38,8 +39,7 @@ static const char* FLAGS_benchmarks =
"fillrand100K,"
"fillseq100K,"
"readseq,"
- "readrand100K,"
- ;
+ "readrand100K,";
// Number of key/values to place in database
static int FLAGS_num = 1000000;
@@ -76,10 +76,9 @@ static bool FLAGS_transaction = true;
static bool FLAGS_WAL_enabled = true;
// Use the db with the following name.
-static const char* FLAGS_db = NULL;
+static const char* FLAGS_db = nullptr;
-inline
-static void ExecErrorCheck(int status, char *err_msg) {
+inline static void ExecErrorCheck(int status, char* err_msg) {
if (status != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
@@ -87,27 +86,25 @@ static void ExecErrorCheck(int status, char *err_msg) {
}
}
-inline
-static void StepErrorCheck(int status) {
+inline static void StepErrorCheck(int status) {
if (status != SQLITE_DONE) {
fprintf(stderr, "SQL step error: status = %d\n", status);
exit(1);
}
}
-inline
-static void ErrorCheck(int status) {
+inline static void ErrorCheck(int status) {
if (status != SQLITE_OK) {
fprintf(stderr, "sqlite3 error: status = %d\n", status);
exit(1);
}
}
-inline
-static void WalCheckpoint(sqlite3* db_) {
+inline static void WalCheckpoint(sqlite3* db_) {
// Flush all writes to disk
if (FLAGS_WAL_enabled) {
- sqlite3_wal_checkpoint_v2(db_, NULL, SQLITE_CHECKPOINT_FULL, NULL, NULL);
+ sqlite3_wal_checkpoint_v2(db_, nullptr, SQLITE_CHECKPOINT_FULL, nullptr,
+ nullptr);
}
}
@@ -152,7 +149,7 @@ static Slice TrimSpace(Slice s) {
start++;
}
int limit = s.size();
- while (limit > start && isspace(s[limit-1])) {
+ while (limit > start && isspace(s[limit - 1])) {
limit--;
}
return Slice(s.data() + start, limit - start);
@@ -176,7 +173,7 @@ class Benchmark {
// State kept for progress messages
int done_;
- int next_report_; // When to report next
+ int next_report_; // When to report next
void PrintHeader() {
const int kKeySize = 16;
@@ -185,17 +182,17 @@ class Benchmark {
fprintf(stdout, "Values: %d bytes each\n", FLAGS_value_size);
fprintf(stdout, "Entries: %d\n", num_);
fprintf(stdout, "RawSize: %.1f MB (estimated)\n",
- ((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_)
- / 1048576.0));
+ ((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_) /
+ 1048576.0));
PrintWarnings();
fprintf(stdout, "------------------------------------------------\n");
}
void PrintWarnings() {
#if defined(__GNUC__) && !defined(__OPTIMIZE__)
- fprintf(stdout,
- "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n"
- );
+ fprintf(
+ stdout,
+ "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n");
#endif
#ifndef NDEBUG
fprintf(stdout,
@@ -207,18 +204,18 @@ class Benchmark {
fprintf(stderr, "SQLite: version %s\n", SQLITE_VERSION);
#if defined(__linux)
- time_t now = time(NULL);
+ time_t now = time(nullptr);
fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
- if (cpuinfo != NULL) {
+ if (cpuinfo != nullptr) {
char line[1000];
int num_cpus = 0;
std::string cpu_type;
std::string cache_size;
- while (fgets(line, sizeof(line), cpuinfo) != NULL) {
+ while (fgets(line, sizeof(line), cpuinfo) != nullptr) {
const char* sep = strchr(line, ':');
- if (sep == NULL) {
+ if (sep == nullptr) {
continue;
}
Slice key = TrimSpace(Slice(line, sep - 1 - line));
@@ -261,13 +258,20 @@ class Benchmark {
done_++;
if (done_ >= next_report_) {
- if (next_report_ < 1000) next_report_ += 100;
- else if (next_report_ < 5000) next_report_ += 500;
- else if (next_report_ < 10000) next_report_ += 1000;
- else if (next_report_ < 50000) next_report_ += 5000;
- else if (next_report_ < 100000) next_report_ += 10000;
- else if (next_report_ < 500000) next_report_ += 50000;
- else next_report_ += 100000;
+ if (next_report_ < 1000)
+ next_report_ += 100;
+ else if (next_report_ < 5000)
+ next_report_ += 500;
+ else if (next_report_ < 10000)
+ next_report_ += 1000;
+ else if (next_report_ < 50000)
+ next_report_ += 5000;
+ else if (next_report_ < 100000)
+ next_report_ += 10000;
+ else if (next_report_ < 500000)
+ next_report_ += 50000;
+ else
+ next_report_ += 100000;
fprintf(stderr, "... finished %d ops%30s\r", done_, "");
fflush(stderr);
}
@@ -285,16 +289,14 @@ class Benchmark {
snprintf(rate, sizeof(rate), "%6.1f MB/s",
(bytes_ / 1048576.0) / (finish - start_));
if (!message_.empty()) {
- message_ = std::string(rate) + " " + message_;
+ message_ = std::string(rate) + " " + message_;
} else {
message_ = rate;
}
}
- fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n",
- name.ToString().c_str(),
- (finish - start_) * 1e6 / done_,
- (message_.empty() ? "" : " "),
+ fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", name.ToString().c_str(),
+ (finish - start_) * 1e6 / done_, (message_.empty() ? "" : " "),
message_.c_str());
if (FLAGS_histogram) {
fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());
@@ -303,22 +305,16 @@ class Benchmark {
}
public:
- enum Order {
- SEQUENTIAL,
- RANDOM
- };
- enum DBState {
- FRESH,
- EXISTING
- };
+ enum Order { SEQUENTIAL, RANDOM };
+ enum DBState { FRESH, EXISTING };
Benchmark()
- : db_(NULL),
- db_num_(0),
- num_(FLAGS_num),
- reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),
- bytes_(0),
- rand_(301) {
+ : db_(nullptr),
+ db_num_(0),
+ num_(FLAGS_num),
+ reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),
+ bytes_(0),
+ rand_(301) {
std::vector<std::string> files;
std::string test_dir;
Env::Default()->GetTestDirectory(&test_dir);
@@ -345,12 +341,12 @@ class Benchmark {
Open();
const char* benchmarks = FLAGS_benchmarks;
- while (benchmarks != NULL) {
+ while (benchmarks != nullptr) {
const char* sep = strchr(benchmarks, ',');
Slice name;
- if (sep == NULL) {
+ if (sep == nullptr) {
name = benchmarks;
- benchmarks = NULL;
+ benchmarks = nullptr;
} else {
name = Slice(benchmarks, sep - benchmarks);
benchmarks = sep + 1;
@@ -415,20 +411,18 @@ class Benchmark {
}
void Open() {
- assert(db_ == NULL);
+ assert(db_ == nullptr);
int status;
char file_name[100];
- char* err_msg = NULL;
+ char* err_msg = nullptr;
db_num_++;
// Open database
std::string tmp_dir;
Env::Default()->GetTestDirectory(&tmp_dir);
- snprintf(file_name, sizeof(file_name),
- "%s/dbbench_sqlite3-%d.db",
- tmp_dir.c_str(),
- db_num_);
+ snprintf(file_name, sizeof(file_name), "%s/dbbench_sqlite3-%d.db",
+ tmp_dir.c_str(), db_num_);
status = sqlite3_open(file_name, &db_);
if (status) {
fprintf(stderr, "open error: %s\n", sqlite3_errmsg(db_));
@@ -439,7 +433,7 @@ class Benchmark {
char cache_size[100];
snprintf(cache_size, sizeof(cache_size), "PRAGMA cache_size = %d",
FLAGS_num_pages);
- status = sqlite3_exec(db_, cache_size, NULL, NULL, &err_msg);
+ status = sqlite3_exec(db_, cache_size, nullptr, nullptr, &err_msg);
ExecErrorCheck(status, err_msg);
// FLAGS_page_size is defaulted to 1024
@@ -447,7 +441,7 @@ class Benchmark {
char page_size[100];
snprintf(page_size, sizeof(page_size), "PRAGMA page_size = %d",
FLAGS_page_size);
- status = sqlite3_exec(db_, page_size, NULL, NULL, &err_msg);
+ status = sqlite3_exec(db_, page_size, nullptr, nullptr, &err_msg);
ExecErrorCheck(status, err_msg);
}
@@ -457,26 +451,28 @@ class Benchmark {
// LevelDB's default cache size is a combined 4 MB
std::string WAL_checkpoint = "PRAGMA wal_autocheckpoint = 4096";
- status = sqlite3_exec(db_, WAL_stmt.c_str(), NULL, NULL, &err_msg);
+ status = sqlite3_exec(db_, WAL_stmt.c_str(), nullptr, nullptr, &err_msg);
ExecErrorCheck(status, err_msg);
- status = sqlite3_exec(db_, WAL_checkpoint.c_str(), NULL, NULL, &err_msg);
+ status =
+ sqlite3_exec(db_, WAL_checkpoint.c_str(), nullptr, nullptr, &err_msg);
ExecErrorCheck(status, err_msg);
}
// Change locking mode to exclusive and create tables/index for database
std::string locking_stmt = "PRAGMA locking_mode = EXCLUSIVE";
std::string create_stmt =
- "CREATE TABLE test (key blob, value blob, PRIMARY KEY(key))";
- std::string stmt_array[] = { locking_stmt, create_stmt };
+ "CREATE TABLE test (key blob, value blob, PRIMARY KEY(key))";
+ std::string stmt_array[] = {locking_stmt, create_stmt};
int stmt_array_length = sizeof(stmt_array) / sizeof(std::string);
for (int i = 0; i < stmt_array_length; i++) {
- status = sqlite3_exec(db_, stmt_array[i].c_str(), NULL, NULL, &err_msg);
+ status =
+ sqlite3_exec(db_, stmt_array[i].c_str(), nullptr, nullptr, &err_msg);
ExecErrorCheck(status, err_msg);
}
}
- void Write(bool write_sync, Order order, DBState state,
- int num_entries, int value_size, int entries_per_batch) {
+ void Write(bool write_sync, Order order, DBState state, int num_entries,
+ int value_size, int entries_per_batch) {
// Create new database if state == FRESH
if (state == FRESH) {
if (FLAGS_use_existing_db) {
@@ -484,7 +480,7 @@ class Benchmark {
return;
}
sqlite3_close(db_);
- db_ = NULL;
+ db_ = nullptr;
Open();
Start();
}
@@ -495,7 +491,7 @@ class Benchmark {
message_ = msg;
}
- char* err_msg = NULL;
+ char* err_msg = nullptr;
int status;
sqlite3_stmt *replace_stmt, *begin_trans_stmt, *end_trans_stmt;
@@ -504,20 +500,20 @@ class Benchmark {
std::string end_trans_str = "END TRANSACTION;";
// Check for synchronous flag in options
- std::string sync_stmt = (write_sync) ? "PRAGMA synchronous = FULL" :
- "PRAGMA synchronous = OFF";
- status = sqlite3_exec(db_, sync_stmt.c_str(), NULL, NULL, &err_msg);
+ std::string sync_stmt =
+ (write_sync) ? "PRAGMA synchronous = FULL" : "PRAGMA synchronous = OFF";
+ status = sqlite3_exec(db_, sync_stmt.c_str(), nullptr, nullptr, &err_msg);
ExecErrorCheck(status, err_msg);
// Preparing sqlite3 statements
- status = sqlite3_prepare_v2(db_, replace_str.c_str(), -1,
- &replace_stmt, NULL);
+ status = sqlite3_prepare_v2(db_, replace_str.c_str(), -1, &replace_stmt,
+ nullptr);
ErrorCheck(status);
status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1,
- &begin_trans_stmt, NULL);
+ &begin_trans_stmt, nullptr);
ErrorCheck(status);
- status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1,
- &end_trans_stmt, NULL);
+ status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, &end_trans_stmt,
+ nullptr);
ErrorCheck(status);
bool transaction = (entries_per_batch > 1);
@@ -535,16 +531,16 @@ class Benchmark {
const char* value = gen_.Generate(value_size).data();
// Create values for key-value pair
- const int k = (order == SEQUENTIAL) ? i + j :
- (rand_.Next() % num_entries);
+ const int k =
+ (order == SEQUENTIAL) ? i + j : (rand_.Next() % num_entries);
char key[100];
snprintf(key, sizeof(key), "%016d", k);
// Bind KV values into replace_stmt
status = sqlite3_bind_blob(replace_stmt, 1, key, 16, SQLITE_STATIC);
ErrorCheck(status);
- status = sqlite3_bind_blob(replace_stmt, 2, value,
- value_size, SQLITE_STATIC);
+ status = sqlite3_bind_blob(replace_stmt, 2, value, value_size,
+ SQLITE_STATIC);
ErrorCheck(status);
// Execute replace_stmt
@@ -588,12 +584,12 @@ class Benchmark {
// Preparing sqlite3 statements
status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1,
- &begin_trans_stmt, NULL);
+ &begin_trans_stmt, nullptr);
ErrorCheck(status);
- status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1,
- &end_trans_stmt, NULL);
+ status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, &end_trans_stmt,
+ nullptr);
ErrorCheck(status);
- status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &read_stmt, NULL);
+ status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &read_stmt, nullptr);
ErrorCheck(status);
bool transaction = (entries_per_batch > 1);
@@ -618,7 +614,8 @@ class Benchmark {
ErrorCheck(status);
// Execute read statement
- while ((status = sqlite3_step(read_stmt)) == SQLITE_ROW) {}
+ while ((status = sqlite3_step(read_stmt)) == SQLITE_ROW) {
+ }
StepErrorCheck(status);
// Reset SQLite statement for another use
@@ -648,10 +645,10 @@ class Benchmark {
void ReadSequential() {
int status;
- sqlite3_stmt *pStmt;
+ sqlite3_stmt* pStmt;
std::string read_str = "SELECT * FROM test ORDER BY key";
- status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &pStmt, NULL);
+ status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &pStmt, nullptr);
ErrorCheck(status);
for (int i = 0; i < reads_ && SQLITE_ROW == sqlite3_step(pStmt); i++) {
bytes_ += sqlite3_column_bytes(pStmt, 1) + sqlite3_column_bytes(pStmt, 2);
@@ -661,7 +658,6 @@ class Benchmark {
status = sqlite3_finalize(pStmt);
ErrorCheck(status);
}
-
};
} // namespace leveldb
@@ -706,10 +702,10 @@ int main(int argc, char** argv) {
}
// Choose a location for the test database if none given with --db=<path>
- if (FLAGS_db == NULL) {
- leveldb::Env::Default()->GetTestDirectory(&default_db_path);
- default_db_path += "/dbbench";
- FLAGS_db = default_db_path.c_str();
+ if (FLAGS_db == nullptr) {
+ leveldb::Env::Default()->GetTestDirectory(&default_db_path);
+ default_db_path += "/dbbench";
+ FLAGS_db = default_db_path.c_str();
}
leveldb::Benchmark benchmark;
diff --git a/src/leveldb/doc/bench/db_bench_tree_db.cc b/src/leveldb/benchmarks/db_bench_tree_db.cc
index 4ca381f11f..b2f6646d89 100644
--- a/src/leveldb/doc/bench/db_bench_tree_db.cc
+++ b/src/leveldb/benchmarks/db_bench_tree_db.cc
@@ -2,9 +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.
+#include <kcpolydb.h>
#include <stdio.h>
#include <stdlib.h>
-#include <kcpolydb.h>
+
#include "util/histogram.h"
#include "util/random.h"
#include "util/testutil.h"
@@ -34,8 +35,7 @@ static const char* FLAGS_benchmarks =
"fillrand100K,"
"fillseq100K,"
"readseq100K,"
- "readrand100K,"
- ;
+ "readrand100K,";
// Number of key/values to place in database
static int FLAGS_num = 1000000;
@@ -69,11 +69,9 @@ static bool FLAGS_use_existing_db = false;
static bool FLAGS_compression = true;
// Use the db with the following name.
-static const char* FLAGS_db = NULL;
+static const char* FLAGS_db = nullptr;
-inline
-static void DBSynchronize(kyotocabinet::TreeDB* db_)
-{
+inline static void DBSynchronize(kyotocabinet::TreeDB* db_) {
// Synchronize will flush writes to disk
if (!db_->synchronize()) {
fprintf(stderr, "synchronize error: %s\n", db_->error().name());
@@ -121,7 +119,7 @@ static Slice TrimSpace(Slice s) {
start++;
}
int limit = s.size();
- while (limit > start && isspace(s[limit-1])) {
+ while (limit > start && isspace(s[limit - 1])) {
limit--;
}
return Slice(s.data() + start, limit - start);
@@ -146,7 +144,7 @@ class Benchmark {
// State kept for progress messages
int done_;
- int next_report_; // When to report next
+ int next_report_; // When to report next
void PrintHeader() {
const int kKeySize = 16;
@@ -157,20 +155,20 @@ class Benchmark {
static_cast<int>(FLAGS_value_size * FLAGS_compression_ratio + 0.5));
fprintf(stdout, "Entries: %d\n", num_);
fprintf(stdout, "RawSize: %.1f MB (estimated)\n",
- ((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_)
- / 1048576.0));
+ ((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_) /
+ 1048576.0));
fprintf(stdout, "FileSize: %.1f MB (estimated)\n",
- (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_)
- / 1048576.0));
+ (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) /
+ 1048576.0));
PrintWarnings();
fprintf(stdout, "------------------------------------------------\n");
}
void PrintWarnings() {
#if defined(__GNUC__) && !defined(__OPTIMIZE__)
- fprintf(stdout,
- "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n"
- );
+ fprintf(
+ stdout,
+ "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n");
#endif
#ifndef NDEBUG
fprintf(stdout,
@@ -183,18 +181,18 @@ class Benchmark {
kyotocabinet::VERSION, kyotocabinet::LIBVER, kyotocabinet::LIBREV);
#if defined(__linux)
- time_t now = time(NULL);
+ time_t now = time(nullptr);
fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
- if (cpuinfo != NULL) {
+ if (cpuinfo != nullptr) {
char line[1000];
int num_cpus = 0;
std::string cpu_type;
std::string cache_size;
- while (fgets(line, sizeof(line), cpuinfo) != NULL) {
+ while (fgets(line, sizeof(line), cpuinfo) != nullptr) {
const char* sep = strchr(line, ':');
- if (sep == NULL) {
+ if (sep == nullptr) {
continue;
}
Slice key = TrimSpace(Slice(line, sep - 1 - line));
@@ -237,13 +235,20 @@ class Benchmark {
done_++;
if (done_ >= next_report_) {
- if (next_report_ < 1000) next_report_ += 100;
- else if (next_report_ < 5000) next_report_ += 500;
- else if (next_report_ < 10000) next_report_ += 1000;
- else if (next_report_ < 50000) next_report_ += 5000;
- else if (next_report_ < 100000) next_report_ += 10000;
- else if (next_report_ < 500000) next_report_ += 50000;
- else next_report_ += 100000;
+ if (next_report_ < 1000)
+ next_report_ += 100;
+ else if (next_report_ < 5000)
+ next_report_ += 500;
+ else if (next_report_ < 10000)
+ next_report_ += 1000;
+ else if (next_report_ < 50000)
+ next_report_ += 5000;
+ else if (next_report_ < 100000)
+ next_report_ += 10000;
+ else if (next_report_ < 500000)
+ next_report_ += 50000;
+ else
+ next_report_ += 100000;
fprintf(stderr, "... finished %d ops%30s\r", done_, "");
fflush(stderr);
}
@@ -261,16 +266,14 @@ class Benchmark {
snprintf(rate, sizeof(rate), "%6.1f MB/s",
(bytes_ / 1048576.0) / (finish - start_));
if (!message_.empty()) {
- message_ = std::string(rate) + " " + message_;
+ message_ = std::string(rate) + " " + message_;
} else {
message_ = rate;
}
}
- fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n",
- name.ToString().c_str(),
- (finish - start_) * 1e6 / done_,
- (message_.empty() ? "" : " "),
+ fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", name.ToString().c_str(),
+ (finish - start_) * 1e6 / done_, (message_.empty() ? "" : " "),
message_.c_str());
if (FLAGS_histogram) {
fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());
@@ -279,21 +282,15 @@ class Benchmark {
}
public:
- enum Order {
- SEQUENTIAL,
- RANDOM
- };
- enum DBState {
- FRESH,
- EXISTING
- };
+ enum Order { SEQUENTIAL, RANDOM };
+ enum DBState { FRESH, EXISTING };
Benchmark()
- : db_(NULL),
- num_(FLAGS_num),
- reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),
- bytes_(0),
- rand_(301) {
+ : db_(nullptr),
+ num_(FLAGS_num),
+ reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),
+ bytes_(0),
+ rand_(301) {
std::vector<std::string> files;
std::string test_dir;
Env::Default()->GetTestDirectory(&test_dir);
@@ -321,12 +318,12 @@ class Benchmark {
Open(false);
const char* benchmarks = FLAGS_benchmarks;
- while (benchmarks != NULL) {
+ while (benchmarks != nullptr) {
const char* sep = strchr(benchmarks, ',');
Slice name;
- if (sep == NULL) {
+ if (sep == nullptr) {
name = benchmarks;
- benchmarks = NULL;
+ benchmarks = nullptr;
} else {
name = Slice(benchmarks, sep - benchmarks);
benchmarks = sep + 1;
@@ -386,8 +383,8 @@ class Benchmark {
}
private:
- void Open(bool sync) {
- assert(db_ == NULL);
+ void Open(bool sync) {
+ assert(db_ == nullptr);
// Initialize db_
db_ = new kyotocabinet::TreeDB();
@@ -395,16 +392,14 @@ class Benchmark {
db_num_++;
std::string test_dir;
Env::Default()->GetTestDirectory(&test_dir);
- snprintf(file_name, sizeof(file_name),
- "%s/dbbench_polyDB-%d.kct",
- test_dir.c_str(),
- db_num_);
+ snprintf(file_name, sizeof(file_name), "%s/dbbench_polyDB-%d.kct",
+ test_dir.c_str(), db_num_);
// Create tuning options and open the database
- int open_options = kyotocabinet::PolyDB::OWRITER |
- kyotocabinet::PolyDB::OCREATE;
- int tune_options = kyotocabinet::TreeDB::TSMALL |
- kyotocabinet::TreeDB::TLINEAR;
+ int open_options =
+ kyotocabinet::PolyDB::OWRITER | kyotocabinet::PolyDB::OCREATE;
+ int tune_options =
+ kyotocabinet::TreeDB::TSMALL | kyotocabinet::TreeDB::TLINEAR;
if (FLAGS_compression) {
tune_options |= kyotocabinet::TreeDB::TCOMPRESS;
db_->tune_compressor(&comp_);
@@ -412,7 +407,7 @@ class Benchmark {
db_->tune_options(tune_options);
db_->tune_page_cache(FLAGS_cache_size);
db_->tune_page(FLAGS_page_size);
- db_->tune_map(256LL<<20);
+ db_->tune_map(256LL << 20);
if (sync) {
open_options |= kyotocabinet::PolyDB::OAUTOSYNC;
}
@@ -421,8 +416,8 @@ class Benchmark {
}
}
- void Write(bool sync, Order order, DBState state,
- int num_entries, int value_size, int entries_per_batch) {
+ void Write(bool sync, Order order, DBState state, int num_entries,
+ int value_size, int entries_per_batch) {
// Create new database if state == FRESH
if (state == FRESH) {
if (FLAGS_use_existing_db) {
@@ -430,7 +425,7 @@ class Benchmark {
return;
}
delete db_;
- db_ = NULL;
+ db_ = nullptr;
Open(sync);
Start(); // Do not count time taken to destroy/open
}
@@ -442,8 +437,7 @@ class Benchmark {
}
// Write to database
- for (int i = 0; i < num_entries; i++)
- {
+ for (int i = 0; i < num_entries; i++) {
const int k = (order == SEQUENTIAL) ? i : (rand_.Next() % num_entries);
char key[100];
snprintf(key, sizeof(key), "%016d", k);
@@ -516,10 +510,10 @@ int main(int argc, char** argv) {
}
// Choose a location for the test database if none given with --db=<path>
- if (FLAGS_db == NULL) {
- leveldb::Env::Default()->GetTestDirectory(&default_db_path);
- default_db_path += "/dbbench";
- FLAGS_db = default_db_path.c_str();
+ if (FLAGS_db == nullptr) {
+ leveldb::Env::Default()->GetTestDirectory(&default_db_path);
+ default_db_path += "/dbbench";
+ FLAGS_db = default_db_path.c_str();
}
leveldb::Benchmark benchmark;
diff --git a/src/leveldb/build_detect_platform b/src/leveldb/build_detect_platform
deleted file mode 100755
index 4a94715900..0000000000
--- a/src/leveldb/build_detect_platform
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/bin/sh
-#
-# Detects OS we're compiling on and outputs a file specified by the first
-# argument, which in turn gets read while processing Makefile.
-#
-# The output will set the following variables:
-# CC C Compiler path
-# CXX C++ Compiler path
-# PLATFORM_LDFLAGS Linker flags
-# PLATFORM_LIBS Libraries flags
-# PLATFORM_SHARED_EXT Extension for shared libraries
-# PLATFORM_SHARED_LDFLAGS Flags for building shared library
-# This flag is embedded just before the name
-# of the shared library without intervening spaces
-# PLATFORM_SHARED_CFLAGS Flags for compiling objects for shared library
-# PLATFORM_CCFLAGS C compiler flags
-# PLATFORM_CXXFLAGS C++ compiler flags. Will contain:
-# PLATFORM_SHARED_VERSIONED Set to 'true' if platform supports versioned
-# shared libraries, empty otherwise.
-#
-# The PLATFORM_CCFLAGS and PLATFORM_CXXFLAGS might include the following:
-#
-# -DLEVELDB_ATOMIC_PRESENT if <atomic> is present
-# -DLEVELDB_PLATFORM_POSIX for Posix-based platforms
-# -DSNAPPY if the Snappy library is present
-#
-
-OUTPUT=$1
-PREFIX=$2
-if test -z "$OUTPUT" || test -z "$PREFIX"; then
- echo "usage: $0 <output-filename> <directory_prefix>" >&2
- exit 1
-fi
-
-# Delete existing output, if it exists
-rm -f $OUTPUT
-touch $OUTPUT
-
-if test -z "$CC"; then
- CC=cc
-fi
-
-if test -z "$CXX"; then
- CXX=g++
-fi
-
-if test -z "$TMPDIR"; then
- TMPDIR=/tmp
-fi
-
-# Detect OS
-if test -z "$TARGET_OS"; then
- TARGET_OS=`uname -s`
-fi
-
-COMMON_FLAGS=
-CROSS_COMPILE=
-PLATFORM_CCFLAGS=
-PLATFORM_CXXFLAGS=
-PLATFORM_LDFLAGS=
-PLATFORM_LIBS=
-PLATFORM_SHARED_EXT="so"
-PLATFORM_SHARED_LDFLAGS="-shared -Wl,-soname -Wl,"
-PLATFORM_SHARED_CFLAGS="-fPIC"
-PLATFORM_SHARED_VERSIONED=true
-PLATFORM_SSEFLAGS=
-
-MEMCMP_FLAG=
-if [ "$CXX" = "g++" ]; then
- # Use libc's memcmp instead of GCC's memcmp. This results in ~40%
- # performance improvement on readrandom under gcc 4.4.3 on Linux/x86.
- MEMCMP_FLAG="-fno-builtin-memcmp"
-fi
-
-case "$TARGET_OS" in
- CYGWIN_*)
- PLATFORM=OS_LINUX
- COMMON_FLAGS="$MEMCMP_FLAG -lpthread -DOS_LINUX -DCYGWIN"
- PLATFORM_LDFLAGS="-lpthread"
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- ;;
- Darwin)
- PLATFORM=OS_MACOSX
- COMMON_FLAGS="$MEMCMP_FLAG -DOS_MACOSX"
- PLATFORM_SHARED_EXT=dylib
- [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd`
- PLATFORM_SHARED_LDFLAGS="-dynamiclib -install_name $INSTALL_PATH/"
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- ;;
- Linux)
- PLATFORM=OS_LINUX
- COMMON_FLAGS="$MEMCMP_FLAG -pthread -DOS_LINUX"
- PLATFORM_LDFLAGS="-pthread"
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- ;;
- SunOS)
- PLATFORM=OS_SOLARIS
- COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_SOLARIS"
- PLATFORM_LIBS="-lpthread -lrt"
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- ;;
- FreeBSD)
- PLATFORM=OS_FREEBSD
- COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_FREEBSD"
- PLATFORM_LIBS="-lpthread"
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- ;;
- GNU/kFreeBSD)
- PLATFORM=OS_KFREEBSD
- COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_KFREEBSD"
- PLATFORM_LIBS="-lpthread"
- PORT_FILE=port/port_posix.cc
- ;;
- NetBSD)
- PLATFORM=OS_NETBSD
- COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_NETBSD"
- PLATFORM_LIBS="-lpthread -lgcc_s"
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- ;;
- OpenBSD)
- PLATFORM=OS_OPENBSD
- COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_OPENBSD"
- PLATFORM_LDFLAGS="-pthread"
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- ;;
- DragonFly)
- PLATFORM=OS_DRAGONFLYBSD
- COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_DRAGONFLYBSD"
- PLATFORM_LIBS="-lpthread"
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- ;;
- OS_ANDROID_CROSSCOMPILE)
- PLATFORM=OS_ANDROID
- COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_ANDROID -DLEVELDB_PLATFORM_POSIX"
- PLATFORM_LDFLAGS="" # All pthread features are in the Android C library
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- CROSS_COMPILE=true
- ;;
- HP-UX)
- PLATFORM=OS_HPUX
- COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_HPUX"
- PLATFORM_LDFLAGS="-pthread"
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- # man ld: +h internal_name
- PLATFORM_SHARED_LDFLAGS="-shared -Wl,+h -Wl,"
- ;;
- IOS)
- PLATFORM=IOS
- COMMON_FLAGS="$MEMCMP_FLAG -DOS_MACOSX"
- [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd`
- PORT_FILE=port/port_posix.cc
- PORT_SSE_FILE=port/port_posix_sse.cc
- PLATFORM_SHARED_EXT=
- PLATFORM_SHARED_LDFLAGS=
- PLATFORM_SHARED_CFLAGS=
- PLATFORM_SHARED_VERSIONED=
- ;;
- OS_WINDOWS_CROSSCOMPILE | NATIVE_WINDOWS)
- PLATFORM=OS_WINDOWS
- COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_WINDOWS -DLEVELDB_PLATFORM_WINDOWS -DWINVER=0x0500 -D__USE_MINGW_ANSI_STDIO=1"
- PLATFORM_SOURCES="util/env_win.cc"
- PLATFORM_LIBS="-lshlwapi"
- PORT_FILE=port/port_win.cc
- CROSS_COMPILE=true
- ;;
- *)
- echo "Unknown platform!" >&2
- exit 1
-esac
-
-# We want to make a list of all cc files within util, db, table, and helpers
-# except for the test and benchmark files. By default, find will output a list
-# of all files matching either rule, so we need to append -print to make the
-# prune take effect.
-DIRS="$PREFIX/db $PREFIX/util $PREFIX/table"
-
-set -f # temporarily disable globbing so that our patterns aren't expanded
-PRUNE_TEST="-name *test*.cc -prune"
-PRUNE_BENCH="-name *_bench.cc -prune"
-PRUNE_TOOL="-name leveldbutil.cc -prune"
-PORTABLE_FILES=`find $DIRS $PRUNE_TEST -o $PRUNE_BENCH -o $PRUNE_TOOL -o -name '*.cc' -print | sort | sed "s,^$PREFIX/,," | tr "\n" " "`
-
-set +f # re-enable globbing
-
-# The sources consist of the portable files, plus the platform-specific port
-# file.
-echo "SOURCES=$PORTABLE_FILES $PORT_FILE $PORT_SSE_FILE" >> $OUTPUT
-echo "MEMENV_SOURCES=helpers/memenv/memenv.cc" >> $OUTPUT
-
-if [ "$CROSS_COMPILE" = "true" ]; then
- # Cross-compiling; do not try any compilation tests.
- true
-else
- CXXOUTPUT="${TMPDIR}/leveldb_build_detect_platform-cxx.$$"
-
- # If -std=c++0x works, use <atomic> as fallback for when memory barriers
- # are not available.
- $CXX $CXXFLAGS -std=c++0x -x c++ - -o $CXXOUTPUT 2>/dev/null <<EOF
- #include <atomic>
- int main() {}
-EOF
- if [ "$?" = 0 ]; then
- COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX -DLEVELDB_ATOMIC_PRESENT"
- PLATFORM_CXXFLAGS="-std=c++0x"
- else
- COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX"
- fi
-
- # Test whether tcmalloc is available
- $CXX $CXXFLAGS -x c++ - -o $CXXOUTPUT -ltcmalloc 2>/dev/null <<EOF
- int main() {}
-EOF
- if [ "$?" = 0 ]; then
- PLATFORM_LIBS="$PLATFORM_LIBS -ltcmalloc"
- fi
-
- rm -f $CXXOUTPUT 2>/dev/null
-
- # Test if gcc SSE 4.2 is supported
- $CXX $CXXFLAGS -x c++ - -o $CXXOUTPUT -msse4.2 2>/dev/null <<EOF
- int main() {}
-EOF
- if [ "$?" = 0 ]; then
- PLATFORM_SSEFLAGS="-msse4.2"
- fi
-
- rm -f $CXXOUTPUT 2>/dev/null
-fi
-
-# Use the SSE 4.2 CRC32C intrinsics iff runtime checks indicate compiler supports them.
-if [ -n "$PLATFORM_SSEFLAGS" ]; then
- PLATFORM_SSEFLAGS="$PLATFORM_SSEFLAGS -DLEVELDB_PLATFORM_POSIX_SSE"
-fi
-
-PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS"
-PLATFORM_CXXFLAGS="$PLATFORM_CXXFLAGS $COMMON_FLAGS"
-
-echo "CC=$CC" >> $OUTPUT
-echo "CXX=$CXX" >> $OUTPUT
-echo "PLATFORM=$PLATFORM" >> $OUTPUT
-echo "PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS" >> $OUTPUT
-echo "PLATFORM_LIBS=$PLATFORM_LIBS" >> $OUTPUT
-echo "PLATFORM_CCFLAGS=$PLATFORM_CCFLAGS" >> $OUTPUT
-echo "PLATFORM_CXXFLAGS=$PLATFORM_CXXFLAGS" >> $OUTPUT
-echo "PLATFORM_SSEFLAGS=$PLATFORM_SSEFLAGS" >> $OUTPUT
-echo "PLATFORM_SHARED_CFLAGS=$PLATFORM_SHARED_CFLAGS" >> $OUTPUT
-echo "PLATFORM_SHARED_EXT=$PLATFORM_SHARED_EXT" >> $OUTPUT
-echo "PLATFORM_SHARED_LDFLAGS=$PLATFORM_SHARED_LDFLAGS" >> $OUTPUT
-echo "PLATFORM_SHARED_VERSIONED=$PLATFORM_SHARED_VERSIONED" >> $OUTPUT
diff --git a/src/leveldb/cmake/leveldbConfig.cmake b/src/leveldb/cmake/leveldbConfig.cmake
new file mode 100644
index 0000000000..eea6e5c477
--- /dev/null
+++ b/src/leveldb/cmake/leveldbConfig.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/leveldbTargets.cmake")
diff --git a/src/leveldb/db/autocompact_test.cc b/src/leveldb/db/autocompact_test.cc
index d20a2362c3..e6c97a05a6 100644
--- a/src/leveldb/db/autocompact_test.cc
+++ b/src/leveldb/db/autocompact_test.cc
@@ -2,9 +2,9 @@
// 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.
-#include "leveldb/db.h"
#include "db/db_impl.h"
#include "leveldb/cache.h"
+#include "leveldb/db.h"
#include "util/testharness.h"
#include "util/testutil.h"
@@ -12,11 +12,6 @@ namespace leveldb {
class AutoCompactTest {
public:
- std::string dbname_;
- Cache* tiny_cache_;
- Options options_;
- DB* db_;
-
AutoCompactTest() {
dbname_ = test::TmpDir() + "/autocompact_test";
tiny_cache_ = NewLRUCache(100);
@@ -47,6 +42,12 @@ class AutoCompactTest {
}
void DoReads(int n);
+
+ private:
+ std::string dbname_;
+ Cache* tiny_cache_;
+ Options options_;
+ DB* db_;
};
static const int kValueSize = 200 * 1024;
@@ -81,17 +82,16 @@ void AutoCompactTest::DoReads(int n) {
ASSERT_LT(read, 100) << "Taking too long to compact";
Iterator* iter = db_->NewIterator(ReadOptions());
for (iter->SeekToFirst();
- iter->Valid() && iter->key().ToString() < limit_key;
- iter->Next()) {
+ iter->Valid() && iter->key().ToString() < limit_key; iter->Next()) {
// Drop data
}
delete iter;
// Wait a little bit to allow any triggered compactions to complete.
Env::Default()->SleepForMicroseconds(1000000);
uint64_t size = Size(Key(0), Key(n));
- fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n",
- read+1, size/1048576.0, Size(Key(n), Key(kCount))/1048576.0);
- if (size <= initial_size/10) {
+ fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n", read + 1,
+ size / 1048576.0, Size(Key(n), Key(kCount)) / 1048576.0);
+ if (size <= initial_size / 10) {
break;
}
}
@@ -100,19 +100,13 @@ void AutoCompactTest::DoReads(int n) {
// is pretty much unchanged.
const int64_t final_other_size = Size(Key(n), Key(kCount));
ASSERT_LE(final_other_size, initial_other_size + 1048576);
- ASSERT_GE(final_other_size, initial_other_size/5 - 1048576);
+ ASSERT_GE(final_other_size, initial_other_size / 5 - 1048576);
}
-TEST(AutoCompactTest, ReadAll) {
- DoReads(kCount);
-}
+TEST(AutoCompactTest, ReadAll) { DoReads(kCount); }
-TEST(AutoCompactTest, ReadHalf) {
- DoReads(kCount/2);
-}
+TEST(AutoCompactTest, ReadHalf) { DoReads(kCount / 2); }
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/builder.cc b/src/leveldb/db/builder.cc
index f419882197..9520ee4535 100644
--- a/src/leveldb/db/builder.cc
+++ b/src/leveldb/db/builder.cc
@@ -4,8 +4,8 @@
#include "db/builder.h"
-#include "db/filename.h"
#include "db/dbformat.h"
+#include "db/filename.h"
#include "db/table_cache.h"
#include "db/version_edit.h"
#include "leveldb/db.h"
@@ -14,12 +14,8 @@
namespace leveldb {
-Status BuildTable(const std::string& dbname,
- Env* env,
- const Options& options,
- TableCache* table_cache,
- Iterator* iter,
- FileMetaData* meta) {
+Status BuildTable(const std::string& dbname, Env* env, const Options& options,
+ TableCache* table_cache, Iterator* iter, FileMetaData* meta) {
Status s;
meta->file_size = 0;
iter->SeekToFirst();
@@ -41,14 +37,10 @@ Status BuildTable(const std::string& dbname,
}
// Finish and check for builder errors
+ s = builder->Finish();
if (s.ok()) {
- s = builder->Finish();
- if (s.ok()) {
- meta->file_size = builder->FileSize();
- assert(meta->file_size > 0);
- }
- } else {
- builder->Abandon();
+ meta->file_size = builder->FileSize();
+ assert(meta->file_size > 0);
}
delete builder;
@@ -60,12 +52,11 @@ Status BuildTable(const std::string& dbname,
s = file->Close();
}
delete file;
- file = NULL;
+ file = nullptr;
if (s.ok()) {
// Verify that the table is usable
- Iterator* it = table_cache->NewIterator(ReadOptions(),
- meta->number,
+ Iterator* it = table_cache->NewIterator(ReadOptions(), meta->number,
meta->file_size);
s = it->status();
delete it;
diff --git a/src/leveldb/db/builder.h b/src/leveldb/db/builder.h
index 62431fcf44..7bd0b8049b 100644
--- a/src/leveldb/db/builder.h
+++ b/src/leveldb/db/builder.h
@@ -22,12 +22,8 @@ class VersionEdit;
// *meta will be filled with metadata about the generated table.
// If no data is present in *iter, meta->file_size will be set to
// zero, and no Table file will be produced.
-extern Status BuildTable(const std::string& dbname,
- Env* env,
- const Options& options,
- TableCache* table_cache,
- Iterator* iter,
- FileMetaData* meta);
+Status BuildTable(const std::string& dbname, Env* env, const Options& options,
+ TableCache* table_cache, Iterator* iter, FileMetaData* meta);
} // namespace leveldb
diff --git a/src/leveldb/db/c.cc b/src/leveldb/db/c.cc
index b23e3dcc9d..3a492f9ac5 100644
--- a/src/leveldb/db/c.cc
+++ b/src/leveldb/db/c.cc
@@ -4,10 +4,9 @@
#include "leveldb/c.h"
-#include <stdlib.h>
-#ifndef WIN32
-#include <unistd.h>
-#endif
+#include <cstdint>
+#include <cstdlib>
+
#include "leveldb/cache.h"
#include "leveldb/comparator.h"
#include "leveldb/db.h"
@@ -45,69 +44,72 @@ using leveldb::WriteOptions;
extern "C" {
-struct leveldb_t { DB* rep; };
-struct leveldb_iterator_t { Iterator* rep; };
-struct leveldb_writebatch_t { WriteBatch rep; };
-struct leveldb_snapshot_t { const Snapshot* rep; };
-struct leveldb_readoptions_t { ReadOptions rep; };
-struct leveldb_writeoptions_t { WriteOptions rep; };
-struct leveldb_options_t { Options rep; };
-struct leveldb_cache_t { Cache* rep; };
-struct leveldb_seqfile_t { SequentialFile* rep; };
-struct leveldb_randomfile_t { RandomAccessFile* rep; };
-struct leveldb_writablefile_t { WritableFile* rep; };
-struct leveldb_logger_t { Logger* rep; };
-struct leveldb_filelock_t { FileLock* rep; };
+struct leveldb_t {
+ DB* rep;
+};
+struct leveldb_iterator_t {
+ Iterator* rep;
+};
+struct leveldb_writebatch_t {
+ WriteBatch rep;
+};
+struct leveldb_snapshot_t {
+ const Snapshot* rep;
+};
+struct leveldb_readoptions_t {
+ ReadOptions rep;
+};
+struct leveldb_writeoptions_t {
+ WriteOptions rep;
+};
+struct leveldb_options_t {
+ Options rep;
+};
+struct leveldb_cache_t {
+ Cache* rep;
+};
+struct leveldb_seqfile_t {
+ SequentialFile* rep;
+};
+struct leveldb_randomfile_t {
+ RandomAccessFile* rep;
+};
+struct leveldb_writablefile_t {
+ WritableFile* rep;
+};
+struct leveldb_logger_t {
+ Logger* rep;
+};
+struct leveldb_filelock_t {
+ FileLock* rep;
+};
struct leveldb_comparator_t : public Comparator {
- void* state_;
- void (*destructor_)(void*);
- int (*compare_)(
- void*,
- const char* a, size_t alen,
- const char* b, size_t blen);
- const char* (*name_)(void*);
+ ~leveldb_comparator_t() override { (*destructor_)(state_); }
- virtual ~leveldb_comparator_t() {
- (*destructor_)(state_);
- }
-
- virtual int Compare(const Slice& a, const Slice& b) const {
+ int Compare(const Slice& a, const Slice& b) const override {
return (*compare_)(state_, a.data(), a.size(), b.data(), b.size());
}
- virtual const char* Name() const {
- return (*name_)(state_);
- }
+ const char* Name() const override { return (*name_)(state_); }
// No-ops since the C binding does not support key shortening methods.
- virtual void FindShortestSeparator(std::string*, const Slice&) const { }
- virtual void FindShortSuccessor(std::string* key) const { }
-};
+ void FindShortestSeparator(std::string*, const Slice&) const override {}
+ void FindShortSuccessor(std::string* key) const override {}
-struct leveldb_filterpolicy_t : public FilterPolicy {
void* state_;
void (*destructor_)(void*);
+ int (*compare_)(void*, const char* a, size_t alen, const char* b,
+ size_t blen);
const char* (*name_)(void*);
- char* (*create_)(
- void*,
- const char* const* key_array, const size_t* key_length_array,
- int num_keys,
- size_t* filter_length);
- unsigned char (*key_match_)(
- void*,
- const char* key, size_t length,
- const char* filter, size_t filter_length);
-
- virtual ~leveldb_filterpolicy_t() {
- (*destructor_)(state_);
- }
+};
- virtual const char* Name() const {
- return (*name_)(state_);
- }
+struct leveldb_filterpolicy_t : public FilterPolicy {
+ ~leveldb_filterpolicy_t() override { (*destructor_)(state_); }
- virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
+ const char* Name() const override { return (*name_)(state_); }
+
+ void CreateFilter(const Slice* keys, int n, std::string* dst) const override {
std::vector<const char*> key_pointers(n);
std::vector<size_t> key_sizes(n);
for (int i = 0; i < n; i++) {
@@ -120,10 +122,19 @@ struct leveldb_filterpolicy_t : public FilterPolicy {
free(filter);
}
- virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const {
- return (*key_match_)(state_, key.data(), key.size(),
- filter.data(), filter.size());
+ bool KeyMayMatch(const Slice& key, const Slice& filter) const override {
+ return (*key_match_)(state_, key.data(), key.size(), filter.data(),
+ filter.size());
}
+
+ void* state_;
+ void (*destructor_)(void*);
+ const char* (*name_)(void*);
+ char* (*create_)(void*, const char* const* key_array,
+ const size_t* key_length_array, int num_keys,
+ size_t* filter_length);
+ uint8_t (*key_match_)(void*, const char* key, size_t length,
+ const char* filter, size_t filter_length);
};
struct leveldb_env_t {
@@ -132,10 +143,10 @@ struct leveldb_env_t {
};
static bool SaveError(char** errptr, const Status& s) {
- assert(errptr != NULL);
+ assert(errptr != nullptr);
if (s.ok()) {
return false;
- } else if (*errptr == NULL) {
+ } else if (*errptr == nullptr) {
*errptr = strdup(s.ToString().c_str());
} else {
// TODO(sanjay): Merge with existing error?
@@ -151,13 +162,11 @@ static char* CopyString(const std::string& str) {
return result;
}
-leveldb_t* leveldb_open(
- const leveldb_options_t* options,
- const char* name,
- char** errptr) {
+leveldb_t* leveldb_open(const leveldb_options_t* options, const char* name,
+ char** errptr) {
DB* db;
if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) {
- return NULL;
+ return nullptr;
}
leveldb_t* result = new leveldb_t;
result->rep = db;
@@ -169,40 +178,27 @@ void leveldb_close(leveldb_t* db) {
delete db;
}
-void leveldb_put(
- leveldb_t* db,
- const leveldb_writeoptions_t* options,
- const char* key, size_t keylen,
- const char* val, size_t vallen,
- char** errptr) {
+void leveldb_put(leveldb_t* db, const leveldb_writeoptions_t* options,
+ const char* key, size_t keylen, const char* val, size_t vallen,
+ char** errptr) {
SaveError(errptr,
db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen)));
}
-void leveldb_delete(
- leveldb_t* db,
- const leveldb_writeoptions_t* options,
- const char* key, size_t keylen,
- char** errptr) {
+void leveldb_delete(leveldb_t* db, const leveldb_writeoptions_t* options,
+ const char* key, size_t keylen, char** errptr) {
SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen)));
}
-
-void leveldb_write(
- leveldb_t* db,
- const leveldb_writeoptions_t* options,
- leveldb_writebatch_t* batch,
- char** errptr) {
+void leveldb_write(leveldb_t* db, const leveldb_writeoptions_t* options,
+ leveldb_writebatch_t* batch, char** errptr) {
SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
}
-char* leveldb_get(
- leveldb_t* db,
- const leveldb_readoptions_t* options,
- const char* key, size_t keylen,
- size_t* vallen,
- char** errptr) {
- char* result = NULL;
+char* leveldb_get(leveldb_t* db, const leveldb_readoptions_t* options,
+ const char* key, size_t keylen, size_t* vallen,
+ char** errptr) {
+ char* result = nullptr;
std::string tmp;
Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp);
if (s.ok()) {
@@ -218,45 +214,40 @@ char* leveldb_get(
}
leveldb_iterator_t* leveldb_create_iterator(
- leveldb_t* db,
- const leveldb_readoptions_t* options) {
+ leveldb_t* db, const leveldb_readoptions_t* options) {
leveldb_iterator_t* result = new leveldb_iterator_t;
result->rep = db->rep->NewIterator(options->rep);
return result;
}
-const leveldb_snapshot_t* leveldb_create_snapshot(
- leveldb_t* db) {
+const leveldb_snapshot_t* leveldb_create_snapshot(leveldb_t* db) {
leveldb_snapshot_t* result = new leveldb_snapshot_t;
result->rep = db->rep->GetSnapshot();
return result;
}
-void leveldb_release_snapshot(
- leveldb_t* db,
- const leveldb_snapshot_t* snapshot) {
+void leveldb_release_snapshot(leveldb_t* db,
+ const leveldb_snapshot_t* snapshot) {
db->rep->ReleaseSnapshot(snapshot->rep);
delete snapshot;
}
-char* leveldb_property_value(
- leveldb_t* db,
- const char* propname) {
+char* leveldb_property_value(leveldb_t* db, const char* propname) {
std::string tmp;
if (db->rep->GetProperty(Slice(propname), &tmp)) {
// We use strdup() since we expect human readable output.
return strdup(tmp.c_str());
} else {
- return NULL;
+ return nullptr;
}
}
-void leveldb_approximate_sizes(
- leveldb_t* db,
- int num_ranges,
- const char* const* range_start_key, const size_t* range_start_key_len,
- const char* const* range_limit_key, const size_t* range_limit_key_len,
- uint64_t* sizes) {
+void leveldb_approximate_sizes(leveldb_t* db, int num_ranges,
+ const char* const* range_start_key,
+ const size_t* range_start_key_len,
+ const char* const* range_limit_key,
+ const size_t* range_limit_key_len,
+ uint64_t* sizes) {
Range* ranges = new Range[num_ranges];
for (int i = 0; i < num_ranges; i++) {
ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]);
@@ -266,28 +257,23 @@ void leveldb_approximate_sizes(
delete[] ranges;
}
-void leveldb_compact_range(
- leveldb_t* db,
- const char* start_key, size_t start_key_len,
- const char* limit_key, size_t limit_key_len) {
+void leveldb_compact_range(leveldb_t* db, const char* start_key,
+ size_t start_key_len, const char* limit_key,
+ size_t limit_key_len) {
Slice a, b;
db->rep->CompactRange(
- // Pass NULL Slice if corresponding "const char*" is NULL
- (start_key ? (a = Slice(start_key, start_key_len), &a) : NULL),
- (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : NULL));
+ // Pass null Slice if corresponding "const char*" is null
+ (start_key ? (a = Slice(start_key, start_key_len), &a) : nullptr),
+ (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr));
}
-void leveldb_destroy_db(
- const leveldb_options_t* options,
- const char* name,
- char** errptr) {
+void leveldb_destroy_db(const leveldb_options_t* options, const char* name,
+ char** errptr) {
SaveError(errptr, DestroyDB(name, options->rep));
}
-void leveldb_repair_db(
- const leveldb_options_t* options,
- const char* name,
- char** errptr) {
+void leveldb_repair_db(const leveldb_options_t* options, const char* name,
+ char** errptr) {
SaveError(errptr, RepairDB(name, options->rep));
}
@@ -296,7 +282,7 @@ void leveldb_iter_destroy(leveldb_iterator_t* iter) {
delete iter;
}
-unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) {
+uint8_t leveldb_iter_valid(const leveldb_iterator_t* iter) {
return iter->rep->Valid();
}
@@ -312,13 +298,9 @@ void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) {
iter->rep->Seek(Slice(k, klen));
}
-void leveldb_iter_next(leveldb_iterator_t* iter) {
- iter->rep->Next();
-}
+void leveldb_iter_next(leveldb_iterator_t* iter) { iter->rep->Next(); }
-void leveldb_iter_prev(leveldb_iterator_t* iter) {
- iter->rep->Prev();
-}
+void leveldb_iter_prev(leveldb_iterator_t* iter) { iter->rep->Prev(); }
const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) {
Slice s = iter->rep->key();
@@ -340,41 +322,34 @@ leveldb_writebatch_t* leveldb_writebatch_create() {
return new leveldb_writebatch_t;
}
-void leveldb_writebatch_destroy(leveldb_writebatch_t* b) {
- delete b;
-}
+void leveldb_writebatch_destroy(leveldb_writebatch_t* b) { delete b; }
-void leveldb_writebatch_clear(leveldb_writebatch_t* b) {
- b->rep.Clear();
-}
+void leveldb_writebatch_clear(leveldb_writebatch_t* b) { b->rep.Clear(); }
-void leveldb_writebatch_put(
- leveldb_writebatch_t* b,
- const char* key, size_t klen,
- const char* val, size_t vlen) {
+void leveldb_writebatch_put(leveldb_writebatch_t* b, const char* key,
+ size_t klen, const char* val, size_t vlen) {
b->rep.Put(Slice(key, klen), Slice(val, vlen));
}
-void leveldb_writebatch_delete(
- leveldb_writebatch_t* b,
- const char* key, size_t klen) {
+void leveldb_writebatch_delete(leveldb_writebatch_t* b, const char* key,
+ size_t klen) {
b->rep.Delete(Slice(key, klen));
}
-void leveldb_writebatch_iterate(
- leveldb_writebatch_t* b,
- void* state,
- void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
- void (*deleted)(void*, const char* k, size_t klen)) {
+void leveldb_writebatch_iterate(const leveldb_writebatch_t* b, void* state,
+ void (*put)(void*, const char* k, size_t klen,
+ const char* v, size_t vlen),
+ void (*deleted)(void*, const char* k,
+ size_t klen)) {
class H : public WriteBatch::Handler {
public:
void* state_;
void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
void (*deleted_)(void*, const char* k, size_t klen);
- virtual void Put(const Slice& key, const Slice& value) {
+ void Put(const Slice& key, const Slice& value) override {
(*put_)(state_, key.data(), key.size(), value.data(), value.size());
}
- virtual void Delete(const Slice& key) {
+ void Delete(const Slice& key) override {
(*deleted_)(state_, key.data(), key.size());
}
};
@@ -385,47 +360,43 @@ void leveldb_writebatch_iterate(
b->rep.Iterate(&handler);
}
-leveldb_options_t* leveldb_options_create() {
- return new leveldb_options_t;
+void leveldb_writebatch_append(leveldb_writebatch_t* destination,
+ const leveldb_writebatch_t* source) {
+ destination->rep.Append(source->rep);
}
-void leveldb_options_destroy(leveldb_options_t* options) {
- delete options;
-}
+leveldb_options_t* leveldb_options_create() { return new leveldb_options_t; }
+
+void leveldb_options_destroy(leveldb_options_t* options) { delete options; }
-void leveldb_options_set_comparator(
- leveldb_options_t* opt,
- leveldb_comparator_t* cmp) {
+void leveldb_options_set_comparator(leveldb_options_t* opt,
+ leveldb_comparator_t* cmp) {
opt->rep.comparator = cmp;
}
-void leveldb_options_set_filter_policy(
- leveldb_options_t* opt,
- leveldb_filterpolicy_t* policy) {
+void leveldb_options_set_filter_policy(leveldb_options_t* opt,
+ leveldb_filterpolicy_t* policy) {
opt->rep.filter_policy = policy;
}
-void leveldb_options_set_create_if_missing(
- leveldb_options_t* opt, unsigned char v) {
+void leveldb_options_set_create_if_missing(leveldb_options_t* opt, uint8_t v) {
opt->rep.create_if_missing = v;
}
-void leveldb_options_set_error_if_exists(
- leveldb_options_t* opt, unsigned char v) {
+void leveldb_options_set_error_if_exists(leveldb_options_t* opt, uint8_t v) {
opt->rep.error_if_exists = v;
}
-void leveldb_options_set_paranoid_checks(
- leveldb_options_t* opt, unsigned char v) {
+void leveldb_options_set_paranoid_checks(leveldb_options_t* opt, uint8_t v) {
opt->rep.paranoid_checks = v;
}
void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) {
- opt->rep.env = (env ? env->rep : NULL);
+ opt->rep.env = (env ? env->rep : nullptr);
}
void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) {
- opt->rep.info_log = (l ? l->rep : NULL);
+ opt->rep.info_log = (l ? l->rep : nullptr);
}
void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) {
@@ -448,17 +419,18 @@ void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) {
opt->rep.block_restart_interval = n;
}
+void leveldb_options_set_max_file_size(leveldb_options_t* opt, size_t s) {
+ opt->rep.max_file_size = s;
+}
+
void leveldb_options_set_compression(leveldb_options_t* opt, int t) {
opt->rep.compression = static_cast<CompressionType>(t);
}
leveldb_comparator_t* leveldb_comparator_create(
- void* state,
- void (*destructor)(void*),
- int (*compare)(
- void*,
- const char* a, size_t alen,
- const char* b, size_t blen),
+ void* state, void (*destructor)(void*),
+ int (*compare)(void*, const char* a, size_t alen, const char* b,
+ size_t blen),
const char* (*name)(void*)) {
leveldb_comparator_t* result = new leveldb_comparator_t;
result->state_ = state;
@@ -468,22 +440,15 @@ leveldb_comparator_t* leveldb_comparator_create(
return result;
}
-void leveldb_comparator_destroy(leveldb_comparator_t* cmp) {
- delete cmp;
-}
+void leveldb_comparator_destroy(leveldb_comparator_t* cmp) { delete cmp; }
leveldb_filterpolicy_t* leveldb_filterpolicy_create(
- void* state,
- void (*destructor)(void*),
- char* (*create_filter)(
- void*,
- const char* const* key_array, const size_t* key_length_array,
- int num_keys,
- size_t* filter_length),
- unsigned char (*key_may_match)(
- void*,
- const char* key, size_t length,
- const char* filter, size_t filter_length),
+ void* state, void (*destructor)(void*),
+ char* (*create_filter)(void*, const char* const* key_array,
+ const size_t* key_length_array, int num_keys,
+ size_t* filter_length),
+ uint8_t (*key_may_match)(void*, const char* key, size_t length,
+ const char* filter, size_t filter_length),
const char* (*name)(void*)) {
leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t;
result->state_ = state;
@@ -503,7 +468,8 @@ leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) {
// they delegate to a NewBloomFilterPolicy() instead of user
// supplied C functions.
struct Wrapper : public leveldb_filterpolicy_t {
- const FilterPolicy* rep_;
+ static void DoNothing(void*) {}
+
~Wrapper() { delete rep_; }
const char* Name() const { return rep_->Name(); }
void CreateFilter(const Slice* keys, int n, std::string* dst) const {
@@ -512,11 +478,12 @@ leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) {
bool KeyMayMatch(const Slice& key, const Slice& filter) const {
return rep_->KeyMayMatch(key, filter);
}
- static void DoNothing(void*) { }
+
+ const FilterPolicy* rep_;
};
Wrapper* wrapper = new Wrapper;
wrapper->rep_ = NewBloomFilterPolicy(bits_per_key);
- wrapper->state_ = NULL;
+ wrapper->state_ = nullptr;
wrapper->destructor_ = &Wrapper::DoNothing;
return wrapper;
}
@@ -525,37 +492,29 @@ leveldb_readoptions_t* leveldb_readoptions_create() {
return new leveldb_readoptions_t;
}
-void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) {
- delete opt;
-}
+void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) { delete opt; }
-void leveldb_readoptions_set_verify_checksums(
- leveldb_readoptions_t* opt,
- unsigned char v) {
+void leveldb_readoptions_set_verify_checksums(leveldb_readoptions_t* opt,
+ uint8_t v) {
opt->rep.verify_checksums = v;
}
-void leveldb_readoptions_set_fill_cache(
- leveldb_readoptions_t* opt, unsigned char v) {
+void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t* opt, uint8_t v) {
opt->rep.fill_cache = v;
}
-void leveldb_readoptions_set_snapshot(
- leveldb_readoptions_t* opt,
- const leveldb_snapshot_t* snap) {
- opt->rep.snapshot = (snap ? snap->rep : NULL);
+void leveldb_readoptions_set_snapshot(leveldb_readoptions_t* opt,
+ const leveldb_snapshot_t* snap) {
+ opt->rep.snapshot = (snap ? snap->rep : nullptr);
}
leveldb_writeoptions_t* leveldb_writeoptions_create() {
return new leveldb_writeoptions_t;
}
-void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) {
- delete opt;
-}
+void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) { delete opt; }
-void leveldb_writeoptions_set_sync(
- leveldb_writeoptions_t* opt, unsigned char v) {
+void leveldb_writeoptions_set_sync(leveldb_writeoptions_t* opt, uint8_t v) {
opt->rep.sync = v;
}
@@ -582,16 +541,22 @@ void leveldb_env_destroy(leveldb_env_t* env) {
delete env;
}
-void leveldb_free(void* ptr) {
- free(ptr);
-}
+char* leveldb_env_get_test_directory(leveldb_env_t* env) {
+ std::string result;
+ if (!env->rep->GetTestDirectory(&result).ok()) {
+ return nullptr;
+ }
-int leveldb_major_version() {
- return kMajorVersion;
+ char* buffer = static_cast<char*>(malloc(result.size() + 1));
+ memcpy(buffer, result.data(), result.size());
+ buffer[result.size()] = '\0';
+ return buffer;
}
-int leveldb_minor_version() {
- return kMinorVersion;
-}
+void leveldb_free(void* ptr) { free(ptr); }
+
+int leveldb_major_version() { return kMajorVersion; }
+
+int leveldb_minor_version() { return kMinorVersion; }
} // end extern "C"
diff --git a/src/leveldb/db/c_test.c b/src/leveldb/db/c_test.c
index 7cd5ee0207..16c77eed6a 100644
--- a/src/leveldb/db/c_test.c
+++ b/src/leveldb/db/c_test.c
@@ -8,24 +8,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
const char* phase = "";
-static char dbname[200];
static void StartPhase(const char* name) {
fprintf(stderr, "=== Test %s\n", name);
phase = name;
}
-static const char* GetTempDir(void) {
- const char* ret = getenv("TEST_TMPDIR");
- if (ret == NULL || ret[0] == '\0')
- ret = "/tmp";
- return ret;
-}
-
#define CheckNoError(err) \
if ((err) != NULL) { \
fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \
@@ -130,7 +120,7 @@ static const char* CmpName(void* arg) {
}
// Custom filter policy
-static unsigned char fake_filter_result = 1;
+static uint8_t fake_filter_result = 1;
static void FilterDestroy(void* arg) { }
static const char* FilterName(void* arg) {
return "TestFilter";
@@ -145,10 +135,8 @@ static char* FilterCreate(
memcpy(result, "fake", 4);
return result;
}
-unsigned char FilterKeyMatch(
- void* arg,
- const char* key, size_t length,
- const char* filter, size_t filter_length) {
+uint8_t FilterKeyMatch(void* arg, const char* key, size_t length,
+ const char* filter, size_t filter_length) {
CheckCondition(filter_length == 4);
CheckCondition(memcmp(filter, "fake", 4) == 0);
return fake_filter_result;
@@ -162,21 +150,19 @@ int main(int argc, char** argv) {
leveldb_options_t* options;
leveldb_readoptions_t* roptions;
leveldb_writeoptions_t* woptions;
+ char* dbname;
char* err = NULL;
int run = -1;
CheckCondition(leveldb_major_version() >= 1);
CheckCondition(leveldb_minor_version() >= 1);
- snprintf(dbname, sizeof(dbname),
- "%s/leveldb_c_test-%d",
- GetTempDir(),
- ((int) geteuid()));
-
StartPhase("create_objects");
cmp = leveldb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);
env = leveldb_create_default_env();
cache = leveldb_cache_create_lru(100000);
+ dbname = leveldb_env_get_test_directory(env);
+ CheckCondition(dbname != NULL);
options = leveldb_options_create();
leveldb_options_set_comparator(options, cmp);
@@ -189,6 +175,7 @@ int main(int argc, char** argv) {
leveldb_options_set_max_open_files(options, 10);
leveldb_options_set_block_size(options, 1024);
leveldb_options_set_block_restart_interval(options, 8);
+ leveldb_options_set_max_file_size(options, 3 << 20);
leveldb_options_set_compression(options, leveldb_no_compression);
roptions = leveldb_readoptions_create();
@@ -239,12 +226,18 @@ int main(int argc, char** argv) {
leveldb_writebatch_clear(wb);
leveldb_writebatch_put(wb, "bar", 3, "b", 1);
leveldb_writebatch_put(wb, "box", 3, "c", 1);
- leveldb_writebatch_delete(wb, "bar", 3);
+
+ leveldb_writebatch_t* wb2 = leveldb_writebatch_create();
+ leveldb_writebatch_delete(wb2, "bar", 3);
+ leveldb_writebatch_append(wb, wb2);
+ leveldb_writebatch_destroy(wb2);
+
leveldb_write(db, woptions, wb, &err);
CheckNoError(err);
CheckGet(db, roptions, "foo", "hello");
CheckGet(db, roptions, "bar", NULL);
CheckGet(db, roptions, "box", "c");
+
int pos = 0;
leveldb_writebatch_iterate(wb, &pos, CheckPut, CheckDel);
CheckCondition(pos == 3);
@@ -381,6 +374,7 @@ int main(int argc, char** argv) {
leveldb_options_destroy(options);
leveldb_readoptions_destroy(roptions);
leveldb_writeoptions_destroy(woptions);
+ leveldb_free(dbname);
leveldb_cache_destroy(cache);
leveldb_comparator_destroy(cmp);
leveldb_env_destroy(env);
diff --git a/src/leveldb/db/corruption_test.cc b/src/leveldb/db/corruption_test.cc
index 37a484d25f..42f5237c65 100644
--- a/src/leveldb/db/corruption_test.cc
+++ b/src/leveldb/db/corruption_test.cc
@@ -2,20 +2,16 @@
// 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.
-#include "leveldb/db.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
#include <sys/types.h>
-#include "leveldb/cache.h"
-#include "leveldb/env.h"
-#include "leveldb/table.h"
-#include "leveldb/write_batch.h"
+
#include "db/db_impl.h"
#include "db/filename.h"
#include "db/log_format.h"
#include "db/version_set.h"
+#include "leveldb/cache.h"
+#include "leveldb/db.h"
+#include "leveldb/table.h"
+#include "leveldb/write_batch.h"
#include "util/logging.h"
#include "util/testharness.h"
#include "util/testutil.h"
@@ -26,44 +22,35 @@ static const int kValueSize = 1000;
class CorruptionTest {
public:
- test::ErrorEnv env_;
- std::string dbname_;
- Cache* tiny_cache_;
- Options options_;
- DB* db_;
-
- CorruptionTest() {
- tiny_cache_ = NewLRUCache(100);
+ CorruptionTest()
+ : db_(nullptr),
+ dbname_("/memenv/corruption_test"),
+ tiny_cache_(NewLRUCache(100)) {
options_.env = &env_;
options_.block_cache = tiny_cache_;
- dbname_ = test::TmpDir() + "/corruption_test";
DestroyDB(dbname_, options_);
- db_ = NULL;
options_.create_if_missing = true;
Reopen();
options_.create_if_missing = false;
}
~CorruptionTest() {
- delete db_;
- DestroyDB(dbname_, Options());
- delete tiny_cache_;
+ delete db_;
+ delete tiny_cache_;
}
Status TryReopen() {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
return DB::Open(options_, dbname_, &db_);
}
- void Reopen() {
- ASSERT_OK(TryReopen());
- }
+ void Reopen() { ASSERT_OK(TryReopen()); }
void RepairDB() {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
ASSERT_OK(::leveldb::RepairDB(dbname_, options_));
}
@@ -71,7 +58,7 @@ class CorruptionTest {
std::string key_space, value_space;
WriteBatch batch;
for (int i = 0; i < n; i++) {
- //if ((i % 100) == 0) fprintf(stderr, "@ %d of %d\n", i, n);
+ // if ((i % 100) == 0) fprintf(stderr, "@ %d of %d\n", i, n);
Slice key = Key(i, &key_space);
batch.Clear();
batch.Put(key, Value(i, &value_space));
@@ -100,8 +87,7 @@ class CorruptionTest {
// Ignore boundary keys.
continue;
}
- if (!ConsumeDecimalNumber(&in, &key) ||
- !in.empty() ||
+ if (!ConsumeDecimalNumber(&in, &key) || !in.empty() ||
key < next_expected) {
bad_keys++;
continue;
@@ -126,14 +112,13 @@ class CorruptionTest {
void Corrupt(FileType filetype, int offset, int bytes_to_corrupt) {
// Pick file to corrupt
std::vector<std::string> filenames;
- ASSERT_OK(env_.GetChildren(dbname_, &filenames));
+ ASSERT_OK(env_.target()->GetChildren(dbname_, &filenames));
uint64_t number;
FileType type;
std::string fname;
int picked_number = -1;
for (size_t i = 0; i < filenames.size(); i++) {
- if (ParseFileName(filenames[i], &number, &type) &&
- type == filetype &&
+ if (ParseFileName(filenames[i], &number, &type) && type == filetype &&
int(number) > picked_number) { // Pick latest file
fname = dbname_ + "/" + filenames[i];
picked_number = number;
@@ -141,35 +126,32 @@ class CorruptionTest {
}
ASSERT_TRUE(!fname.empty()) << filetype;
- struct stat sbuf;
- if (stat(fname.c_str(), &sbuf) != 0) {
- const char* msg = strerror(errno);
- ASSERT_TRUE(false) << fname << ": " << msg;
- }
+ uint64_t file_size;
+ ASSERT_OK(env_.target()->GetFileSize(fname, &file_size));
if (offset < 0) {
// Relative to end of file; make it absolute
- if (-offset > sbuf.st_size) {
+ if (-offset > file_size) {
offset = 0;
} else {
- offset = sbuf.st_size + offset;
+ offset = file_size + offset;
}
}
- if (offset > sbuf.st_size) {
- offset = sbuf.st_size;
+ if (offset > file_size) {
+ offset = file_size;
}
- if (offset + bytes_to_corrupt > sbuf.st_size) {
- bytes_to_corrupt = sbuf.st_size - offset;
+ if (offset + bytes_to_corrupt > file_size) {
+ bytes_to_corrupt = file_size - offset;
}
// Do it
std::string contents;
- Status s = ReadFileToString(Env::Default(), fname, &contents);
+ Status s = ReadFileToString(env_.target(), fname, &contents);
ASSERT_TRUE(s.ok()) << s.ToString();
for (int i = 0; i < bytes_to_corrupt; i++) {
contents[i + offset] ^= 0x80;
}
- s = WriteStringToFile(Env::Default(), contents, fname);
+ s = WriteStringToFile(env_.target(), contents, fname);
ASSERT_TRUE(s.ok()) << s.ToString();
}
@@ -197,12 +179,20 @@ class CorruptionTest {
Random r(k);
return test::RandomString(&r, kValueSize, storage);
}
+
+ test::ErrorEnv env_;
+ Options options_;
+ DB* db_;
+
+ private:
+ std::string dbname_;
+ Cache* tiny_cache_;
};
TEST(CorruptionTest, Recovery) {
Build(100);
Check(100, 100);
- Corrupt(kLogFile, 19, 1); // WriteBatch tag for first record
+ Corrupt(kLogFile, 19, 1); // WriteBatch tag for first record
Corrupt(kLogFile, log::kBlockSize + 1000, 1); // Somewhere in second block
Reopen();
@@ -237,8 +227,8 @@ TEST(CorruptionTest, TableFile) {
Build(100);
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
dbi->TEST_CompactMemTable();
- dbi->TEST_CompactRange(0, NULL, NULL);
- dbi->TEST_CompactRange(1, NULL, NULL);
+ dbi->TEST_CompactRange(0, nullptr, nullptr);
+ dbi->TEST_CompactRange(1, nullptr, nullptr);
Corrupt(kTableFile, 100, 1);
Check(90, 99);
@@ -251,8 +241,8 @@ TEST(CorruptionTest, TableFileRepair) {
Build(100);
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
dbi->TEST_CompactMemTable();
- dbi->TEST_CompactRange(0, NULL, NULL);
- dbi->TEST_CompactRange(1, NULL, NULL);
+ dbi->TEST_CompactRange(0, nullptr, nullptr);
+ dbi->TEST_CompactRange(1, nullptr, nullptr);
Corrupt(kTableFile, 100, 1);
RepairDB();
@@ -302,7 +292,7 @@ TEST(CorruptionTest, CorruptedDescriptor) {
ASSERT_OK(db_->Put(WriteOptions(), "foo", "hello"));
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
dbi->TEST_CompactMemTable();
- dbi->TEST_CompactRange(0, NULL, NULL);
+ dbi->TEST_CompactRange(0, nullptr, nullptr);
Corrupt(kDescriptorFile, 0, 1000);
Status s = TryReopen();
@@ -343,7 +333,7 @@ TEST(CorruptionTest, CompactionInputErrorParanoid) {
Corrupt(kTableFile, 100, 1);
env_.SleepForMicroseconds(100000);
}
- dbi->CompactRange(NULL, NULL);
+ dbi->CompactRange(nullptr, nullptr);
// Write must fail because of corrupted table
std::string tmp1, tmp2;
@@ -369,6 +359,4 @@ TEST(CorruptionTest, UnrelatedKeys) {
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/db_impl.cc b/src/leveldb/db/db_impl.cc
index 3bb58e560a..65e31724bc 100644
--- a/src/leveldb/db/db_impl.cc
+++ b/src/leveldb/db/db_impl.cc
@@ -4,12 +4,15 @@
#include "db/db_impl.h"
+#include <stdint.h>
+#include <stdio.h>
+
#include <algorithm>
+#include <atomic>
#include <set>
#include <string>
-#include <stdint.h>
-#include <stdio.h>
#include <vector>
+
#include "db/builder.h"
#include "db/db_iter.h"
#include "db/dbformat.h"
@@ -39,16 +42,33 @@ const int kNumNonTableCacheFiles = 10;
// Information kept for every waiting writer
struct DBImpl::Writer {
+ explicit Writer(port::Mutex* mu)
+ : batch(nullptr), sync(false), done(false), cv(mu) {}
+
Status status;
WriteBatch* batch;
bool sync;
bool done;
port::CondVar cv;
-
- explicit Writer(port::Mutex* mu) : cv(mu) { }
};
struct DBImpl::CompactionState {
+ // Files produced by compaction
+ struct Output {
+ uint64_t number;
+ uint64_t file_size;
+ InternalKey smallest, largest;
+ };
+
+ Output* current_output() { return &outputs[outputs.size() - 1]; }
+
+ explicit CompactionState(Compaction* c)
+ : compaction(c),
+ smallest_snapshot(0),
+ outfile(nullptr),
+ builder(nullptr),
+ total_bytes(0) {}
+
Compaction* const compaction;
// Sequence numbers < smallest_snapshot are not significant since we
@@ -57,12 +77,6 @@ struct DBImpl::CompactionState {
// we can drop all entries for the same key with sequence numbers < S.
SequenceNumber smallest_snapshot;
- // Files produced by compaction
- struct Output {
- uint64_t number;
- uint64_t file_size;
- InternalKey smallest, largest;
- };
std::vector<Output> outputs;
// State kept for output being generated
@@ -70,19 +84,10 @@ struct DBImpl::CompactionState {
TableBuilder* builder;
uint64_t total_bytes;
-
- Output* current_output() { return &outputs[outputs.size()-1]; }
-
- explicit CompactionState(Compaction* c)
- : compaction(c),
- outfile(NULL),
- builder(NULL),
- total_bytes(0) {
- }
};
// Fix user-supplied options to be reasonable
-template <class T,class V>
+template <class T, class V>
static void ClipToRange(T* ptr, V minvalue, V maxvalue) {
if (static_cast<V>(*ptr) > maxvalue) *ptr = maxvalue;
if (static_cast<V>(*ptr) < minvalue) *ptr = minvalue;
@@ -93,27 +98,32 @@ Options SanitizeOptions(const std::string& dbname,
const Options& src) {
Options result = src;
result.comparator = icmp;
- result.filter_policy = (src.filter_policy != NULL) ? ipolicy : NULL;
- ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000);
- ClipToRange(&result.write_buffer_size, 64<<10, 1<<30);
- ClipToRange(&result.max_file_size, 1<<20, 1<<30);
- ClipToRange(&result.block_size, 1<<10, 4<<20);
- if (result.info_log == NULL) {
+ result.filter_policy = (src.filter_policy != nullptr) ? ipolicy : nullptr;
+ ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000);
+ ClipToRange(&result.write_buffer_size, 64 << 10, 1 << 30);
+ ClipToRange(&result.max_file_size, 1 << 20, 1 << 30);
+ ClipToRange(&result.block_size, 1 << 10, 4 << 20);
+ if (result.info_log == nullptr) {
// Open a log file in the same directory as the db
src.env->CreateDir(dbname); // In case it does not exist
src.env->RenameFile(InfoLogFileName(dbname), OldInfoLogFileName(dbname));
Status s = src.env->NewLogger(InfoLogFileName(dbname), &result.info_log);
if (!s.ok()) {
// No place suitable for logging
- result.info_log = NULL;
+ result.info_log = nullptr;
}
}
- if (result.block_cache == NULL) {
+ if (result.block_cache == nullptr) {
result.block_cache = NewLRUCache(8 << 20);
}
return result;
}
+static int TableCacheSize(const Options& sanitized_options) {
+ // Reserve ten files or so for other uses and give the rest to TableCache.
+ return sanitized_options.max_open_files - kNumNonTableCacheFiles;
+}
+
DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
: env_(raw_options.env),
internal_comparator_(raw_options.comparator),
@@ -123,44 +133,39 @@ DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
owns_info_log_(options_.info_log != raw_options.info_log),
owns_cache_(options_.block_cache != raw_options.block_cache),
dbname_(dbname),
- db_lock_(NULL),
- shutting_down_(NULL),
- bg_cv_(&mutex_),
- mem_(NULL),
- imm_(NULL),
- logfile_(NULL),
+ table_cache_(new TableCache(dbname_, options_, TableCacheSize(options_))),
+ db_lock_(nullptr),
+ shutting_down_(false),
+ background_work_finished_signal_(&mutex_),
+ mem_(nullptr),
+ imm_(nullptr),
+ has_imm_(false),
+ logfile_(nullptr),
logfile_number_(0),
- log_(NULL),
+ log_(nullptr),
seed_(0),
tmp_batch_(new WriteBatch),
- bg_compaction_scheduled_(false),
- manual_compaction_(NULL) {
- has_imm_.Release_Store(NULL);
-
- // Reserve ten files or so for other uses and give the rest to TableCache.
- const int table_cache_size = options_.max_open_files - kNumNonTableCacheFiles;
- table_cache_ = new TableCache(dbname_, &options_, table_cache_size);
-
- versions_ = new VersionSet(dbname_, &options_, table_cache_,
- &internal_comparator_);
-}
+ background_compaction_scheduled_(false),
+ manual_compaction_(nullptr),
+ versions_(new VersionSet(dbname_, &options_, table_cache_,
+ &internal_comparator_)) {}
DBImpl::~DBImpl() {
- // Wait for background work to finish
+ // Wait for background work to finish.
mutex_.Lock();
- shutting_down_.Release_Store(this); // Any non-NULL value is ok
- while (bg_compaction_scheduled_) {
- bg_cv_.Wait();
+ shutting_down_.store(true, std::memory_order_release);
+ while (background_compaction_scheduled_) {
+ background_work_finished_signal_.Wait();
}
mutex_.Unlock();
- if (db_lock_ != NULL) {
+ if (db_lock_ != nullptr) {
env_->UnlockFile(db_lock_);
}
delete versions_;
- if (mem_ != NULL) mem_->Unref();
- if (imm_ != NULL) imm_->Unref();
+ if (mem_ != nullptr) mem_->Unref();
+ if (imm_ != nullptr) imm_->Unref();
delete tmp_batch_;
delete log_;
delete logfile_;
@@ -216,6 +221,8 @@ void DBImpl::MaybeIgnoreError(Status* s) const {
}
void DBImpl::DeleteObsoleteFiles() {
+ mutex_.AssertHeld();
+
if (!bg_error_.ok()) {
// After a background error, we don't know whether a new version may
// or may not have been committed, so we cannot safely garbage collect.
@@ -227,11 +234,12 @@ void DBImpl::DeleteObsoleteFiles() {
versions_->AddLiveFiles(&live);
std::vector<std::string> filenames;
- env_->GetChildren(dbname_, &filenames); // Ignoring errors on purpose
+ env_->GetChildren(dbname_, &filenames); // Ignoring errors on purpose
uint64_t number;
FileType type;
- for (size_t i = 0; i < filenames.size(); i++) {
- if (ParseFileName(filenames[i], &number, &type)) {
+ std::vector<std::string> files_to_delete;
+ for (std::string& filename : filenames) {
+ if (ParseFileName(filename, &number, &type)) {
bool keep = true;
switch (type) {
case kLogFile:
@@ -259,26 +267,34 @@ void DBImpl::DeleteObsoleteFiles() {
}
if (!keep) {
+ files_to_delete.push_back(std::move(filename));
if (type == kTableFile) {
table_cache_->Evict(number);
}
- Log(options_.info_log, "Delete type=%d #%lld\n",
- int(type),
+ Log(options_.info_log, "Delete type=%d #%lld\n", static_cast<int>(type),
static_cast<unsigned long long>(number));
- env_->DeleteFile(dbname_ + "/" + filenames[i]);
}
}
}
+
+ // While deleting all files unblock other threads. All files being deleted
+ // have unique names which will not collide with newly created files and
+ // are therefore safe to delete while allowing other threads to proceed.
+ mutex_.Unlock();
+ for (const std::string& filename : files_to_delete) {
+ env_->DeleteFile(dbname_ + "/" + filename);
+ }
+ mutex_.Lock();
}
-Status DBImpl::Recover(VersionEdit* edit, bool *save_manifest) {
+Status DBImpl::Recover(VersionEdit* edit, bool* save_manifest) {
mutex_.AssertHeld();
// Ignore error from CreateDir since the creation of the DB is
// committed only when the descriptor is created, and this directory
// may already exist from a previous failed creation attempt.
env_->CreateDir(dbname_);
- assert(db_lock_ == NULL);
+ assert(db_lock_ == nullptr);
Status s = env_->LockFile(LockFileName(dbname_), &db_lock_);
if (!s.ok()) {
return s;
@@ -296,8 +312,8 @@ Status DBImpl::Recover(VersionEdit* edit, bool *save_manifest) {
}
} else {
if (options_.error_if_exists) {
- return Status::InvalidArgument(
- dbname_, "exists (error_if_exists is true)");
+ return Status::InvalidArgument(dbname_,
+ "exists (error_if_exists is true)");
}
}
@@ -369,12 +385,12 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log,
Env* env;
Logger* info_log;
const char* fname;
- Status* status; // NULL if options_.paranoid_checks==false
- virtual void Corruption(size_t bytes, const Status& s) {
+ Status* status; // null if options_.paranoid_checks==false
+ void Corruption(size_t bytes, const Status& s) override {
Log(info_log, "%s%s: dropping %d bytes; %s",
- (this->status == NULL ? "(ignoring error) " : ""),
- fname, static_cast<int>(bytes), s.ToString().c_str());
- if (this->status != NULL && this->status->ok()) *this->status = s;
+ (this->status == nullptr ? "(ignoring error) " : ""), fname,
+ static_cast<int>(bytes), s.ToString().c_str());
+ if (this->status != nullptr && this->status->ok()) *this->status = s;
}
};
@@ -394,32 +410,30 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log,
reporter.env = env_;
reporter.info_log = options_.info_log;
reporter.fname = fname.c_str();
- reporter.status = (options_.paranoid_checks ? &status : NULL);
+ reporter.status = (options_.paranoid_checks ? &status : nullptr);
// We intentionally make log::Reader do checksumming even if
// paranoid_checks==false so that corruptions cause entire commits
// to be skipped instead of propagating bad information (like overly
// large sequence numbers).
- log::Reader reader(file, &reporter, true/*checksum*/,
- 0/*initial_offset*/);
+ log::Reader reader(file, &reporter, true /*checksum*/, 0 /*initial_offset*/);
Log(options_.info_log, "Recovering log #%llu",
- (unsigned long long) log_number);
+ (unsigned long long)log_number);
// Read all the records and add to a memtable
std::string scratch;
Slice record;
WriteBatch batch;
int compactions = 0;
- MemTable* mem = NULL;
- while (reader.ReadRecord(&record, &scratch) &&
- status.ok()) {
+ MemTable* mem = nullptr;
+ while (reader.ReadRecord(&record, &scratch) && status.ok()) {
if (record.size() < 12) {
- reporter.Corruption(
- record.size(), Status::Corruption("log record too small", fname));
+ reporter.Corruption(record.size(),
+ Status::Corruption("log record too small", fname));
continue;
}
WriteBatchInternal::SetContents(&batch, record);
- if (mem == NULL) {
+ if (mem == nullptr) {
mem = new MemTable(internal_comparator_);
mem->Ref();
}
@@ -428,9 +442,8 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log,
if (!status.ok()) {
break;
}
- const SequenceNumber last_seq =
- WriteBatchInternal::Sequence(&batch) +
- WriteBatchInternal::Count(&batch) - 1;
+ const SequenceNumber last_seq = WriteBatchInternal::Sequence(&batch) +
+ WriteBatchInternal::Count(&batch) - 1;
if (last_seq > *max_sequence) {
*max_sequence = last_seq;
}
@@ -438,9 +451,9 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log,
if (mem->ApproximateMemoryUsage() > options_.write_buffer_size) {
compactions++;
*save_manifest = true;
- status = WriteLevel0Table(mem, edit, NULL);
+ status = WriteLevel0Table(mem, edit, nullptr);
mem->Unref();
- mem = NULL;
+ mem = nullptr;
if (!status.ok()) {
// Reflect errors immediately so that conditions like full
// file-systems cause the DB::Open() to fail.
@@ -453,31 +466,31 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log,
// See if we should keep reusing the last log file.
if (status.ok() && options_.reuse_logs && last_log && compactions == 0) {
- assert(logfile_ == NULL);
- assert(log_ == NULL);
- assert(mem_ == NULL);
+ assert(logfile_ == nullptr);
+ assert(log_ == nullptr);
+ assert(mem_ == nullptr);
uint64_t lfile_size;
if (env_->GetFileSize(fname, &lfile_size).ok() &&
env_->NewAppendableFile(fname, &logfile_).ok()) {
Log(options_.info_log, "Reusing old log %s \n", fname.c_str());
log_ = new log::Writer(logfile_, lfile_size);
logfile_number_ = log_number;
- if (mem != NULL) {
+ if (mem != nullptr) {
mem_ = mem;
- mem = NULL;
+ mem = nullptr;
} else {
- // mem can be NULL if lognum exists but was empty.
+ // mem can be nullptr if lognum exists but was empty.
mem_ = new MemTable(internal_comparator_);
mem_->Ref();
}
}
}
- if (mem != NULL) {
+ if (mem != nullptr) {
// mem did not get reused; compact it.
if (status.ok()) {
*save_manifest = true;
- status = WriteLevel0Table(mem, edit, NULL);
+ status = WriteLevel0Table(mem, edit, nullptr);
}
mem->Unref();
}
@@ -494,7 +507,7 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
pending_outputs_.insert(meta.number);
Iterator* iter = mem->NewIterator();
Log(options_.info_log, "Level-0 table #%llu: started",
- (unsigned long long) meta.number);
+ (unsigned long long)meta.number);
Status s;
{
@@ -504,24 +517,22 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
}
Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s",
- (unsigned long long) meta.number,
- (unsigned long long) meta.file_size,
+ (unsigned long long)meta.number, (unsigned long long)meta.file_size,
s.ToString().c_str());
delete iter;
pending_outputs_.erase(meta.number);
-
// Note that if file_size is zero, the file has been deleted and
// should not be added to the manifest.
int level = 0;
if (s.ok() && meta.file_size > 0) {
const Slice min_user_key = meta.smallest.user_key();
const Slice max_user_key = meta.largest.user_key();
- if (base != NULL) {
+ if (base != nullptr) {
level = base->PickLevelForMemTableOutput(min_user_key, max_user_key);
}
- edit->AddFile(level, meta.number, meta.file_size,
- meta.smallest, meta.largest);
+ edit->AddFile(level, meta.number, meta.file_size, meta.smallest,
+ meta.largest);
}
CompactionStats stats;
@@ -533,7 +544,7 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
void DBImpl::CompactMemTable() {
mutex_.AssertHeld();
- assert(imm_ != NULL);
+ assert(imm_ != nullptr);
// Save the contents of the memtable as a new Table
VersionEdit edit;
@@ -542,7 +553,7 @@ void DBImpl::CompactMemTable() {
Status s = WriteLevel0Table(imm_, &edit, base);
base->Unref();
- if (s.ok() && shutting_down_.Acquire_Load()) {
+ if (s.ok() && shutting_down_.load(std::memory_order_acquire)) {
s = Status::IOError("Deleting DB during memtable compaction");
}
@@ -556,8 +567,8 @@ void DBImpl::CompactMemTable() {
if (s.ok()) {
// Commit to the new state
imm_->Unref();
- imm_ = NULL;
- has_imm_.Release_Store(NULL);
+ imm_ = nullptr;
+ has_imm_.store(false, std::memory_order_release);
DeleteObsoleteFiles();
} else {
RecordBackgroundError(s);
@@ -575,13 +586,14 @@ void DBImpl::CompactRange(const Slice* begin, const Slice* end) {
}
}
}
- TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap
+ TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap
for (int level = 0; level < max_level_with_files; level++) {
TEST_CompactRange(level, begin, end);
}
}
-void DBImpl::TEST_CompactRange(int level, const Slice* begin,const Slice* end) {
+void DBImpl::TEST_CompactRange(int level, const Slice* begin,
+ const Slice* end) {
assert(level >= 0);
assert(level + 1 < config::kNumLevels);
@@ -590,44 +602,45 @@ void DBImpl::TEST_CompactRange(int level, const Slice* begin,const Slice* end) {
ManualCompaction manual;
manual.level = level;
manual.done = false;
- if (begin == NULL) {
- manual.begin = NULL;
+ if (begin == nullptr) {
+ manual.begin = nullptr;
} else {
begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek);
manual.begin = &begin_storage;
}
- if (end == NULL) {
- manual.end = NULL;
+ if (end == nullptr) {
+ manual.end = nullptr;
} else {
end_storage = InternalKey(*end, 0, static_cast<ValueType>(0));
manual.end = &end_storage;
}
MutexLock l(&mutex_);
- while (!manual.done && !shutting_down_.Acquire_Load() && bg_error_.ok()) {
- if (manual_compaction_ == NULL) { // Idle
+ while (!manual.done && !shutting_down_.load(std::memory_order_acquire) &&
+ bg_error_.ok()) {
+ if (manual_compaction_ == nullptr) { // Idle
manual_compaction_ = &manual;
MaybeScheduleCompaction();
} else { // Running either my compaction or another compaction.
- bg_cv_.Wait();
+ background_work_finished_signal_.Wait();
}
}
if (manual_compaction_ == &manual) {
// Cancel my manual compaction since we aborted early for some reason.
- manual_compaction_ = NULL;
+ manual_compaction_ = nullptr;
}
}
Status DBImpl::TEST_CompactMemTable() {
- // NULL batch means just wait for earlier writes to be done
- Status s = Write(WriteOptions(), NULL);
+ // nullptr batch means just wait for earlier writes to be done
+ Status s = Write(WriteOptions(), nullptr);
if (s.ok()) {
// Wait until the compaction completes
MutexLock l(&mutex_);
- while (imm_ != NULL && bg_error_.ok()) {
- bg_cv_.Wait();
+ while (imm_ != nullptr && bg_error_.ok()) {
+ background_work_finished_signal_.Wait();
}
- if (imm_ != NULL) {
+ if (imm_ != nullptr) {
s = bg_error_;
}
}
@@ -638,24 +651,23 @@ void DBImpl::RecordBackgroundError(const Status& s) {
mutex_.AssertHeld();
if (bg_error_.ok()) {
bg_error_ = s;
- bg_cv_.SignalAll();
+ background_work_finished_signal_.SignalAll();
}
}
void DBImpl::MaybeScheduleCompaction() {
mutex_.AssertHeld();
- if (bg_compaction_scheduled_) {
+ if (background_compaction_scheduled_) {
// Already scheduled
- } else if (shutting_down_.Acquire_Load()) {
+ } else if (shutting_down_.load(std::memory_order_acquire)) {
// DB is being deleted; no more background compactions
} else if (!bg_error_.ok()) {
// Already got an error; no more changes
- } else if (imm_ == NULL &&
- manual_compaction_ == NULL &&
+ } else if (imm_ == nullptr && manual_compaction_ == nullptr &&
!versions_->NeedsCompaction()) {
// No work to be done
} else {
- bg_compaction_scheduled_ = true;
+ background_compaction_scheduled_ = true;
env_->Schedule(&DBImpl::BGWork, this);
}
}
@@ -666,8 +678,8 @@ void DBImpl::BGWork(void* db) {
void DBImpl::BackgroundCall() {
MutexLock l(&mutex_);
- assert(bg_compaction_scheduled_);
- if (shutting_down_.Acquire_Load()) {
+ assert(background_compaction_scheduled_);
+ if (shutting_down_.load(std::memory_order_acquire)) {
// No more background work when shutting down.
} else if (!bg_error_.ok()) {
// No more background work after a background error.
@@ -675,36 +687,35 @@ void DBImpl::BackgroundCall() {
BackgroundCompaction();
}
- bg_compaction_scheduled_ = false;
+ background_compaction_scheduled_ = false;
// Previous compaction may have produced too many files in a level,
// so reschedule another compaction if needed.
MaybeScheduleCompaction();
- bg_cv_.SignalAll();
+ background_work_finished_signal_.SignalAll();
}
void DBImpl::BackgroundCompaction() {
mutex_.AssertHeld();
- if (imm_ != NULL) {
+ if (imm_ != nullptr) {
CompactMemTable();
return;
}
Compaction* c;
- bool is_manual = (manual_compaction_ != NULL);
+ bool is_manual = (manual_compaction_ != nullptr);
InternalKey manual_end;
if (is_manual) {
ManualCompaction* m = manual_compaction_;
c = versions_->CompactRange(m->level, m->begin, m->end);
- m->done = (c == NULL);
- if (c != NULL) {
+ m->done = (c == nullptr);
+ if (c != nullptr) {
manual_end = c->input(0, c->num_input_files(0) - 1)->largest;
}
Log(options_.info_log,
"Manual compaction at level-%d from %s .. %s; will stop at %s\n",
- m->level,
- (m->begin ? m->begin->DebugString().c_str() : "(begin)"),
+ m->level, (m->begin ? m->begin->DebugString().c_str() : "(begin)"),
(m->end ? m->end->DebugString().c_str() : "(end)"),
(m->done ? "(end)" : manual_end.DebugString().c_str()));
} else {
@@ -712,26 +723,24 @@ void DBImpl::BackgroundCompaction() {
}
Status status;
- if (c == NULL) {
+ if (c == nullptr) {
// Nothing to do
} else if (!is_manual && c->IsTrivialMove()) {
// Move file to next level
assert(c->num_input_files(0) == 1);
FileMetaData* f = c->input(0, 0);
c->edit()->DeleteFile(c->level(), f->number);
- c->edit()->AddFile(c->level() + 1, f->number, f->file_size,
- f->smallest, f->largest);
+ c->edit()->AddFile(c->level() + 1, f->number, f->file_size, f->smallest,
+ f->largest);
status = versions_->LogAndApply(c->edit(), &mutex_);
if (!status.ok()) {
RecordBackgroundError(status);
}
VersionSet::LevelSummaryStorage tmp;
Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n",
- static_cast<unsigned long long>(f->number),
- c->level() + 1,
+ static_cast<unsigned long long>(f->number), c->level() + 1,
static_cast<unsigned long long>(f->file_size),
- status.ToString().c_str(),
- versions_->LevelSummary(&tmp));
+ status.ToString().c_str(), versions_->LevelSummary(&tmp));
} else {
CompactionState* compact = new CompactionState(c);
status = DoCompactionWork(compact);
@@ -746,11 +755,10 @@ void DBImpl::BackgroundCompaction() {
if (status.ok()) {
// Done
- } else if (shutting_down_.Acquire_Load()) {
+ } else if (shutting_down_.load(std::memory_order_acquire)) {
// Ignore compaction errors found during shutting down
} else {
- Log(options_.info_log,
- "Compaction error: %s", status.ToString().c_str());
+ Log(options_.info_log, "Compaction error: %s", status.ToString().c_str());
}
if (is_manual) {
@@ -764,18 +772,18 @@ void DBImpl::BackgroundCompaction() {
m->tmp_storage = manual_end;
m->begin = &m->tmp_storage;
}
- manual_compaction_ = NULL;
+ manual_compaction_ = nullptr;
}
}
void DBImpl::CleanupCompaction(CompactionState* compact) {
mutex_.AssertHeld();
- if (compact->builder != NULL) {
+ if (compact->builder != nullptr) {
// May happen if we get a shutdown call in the middle of compaction
compact->builder->Abandon();
delete compact->builder;
} else {
- assert(compact->outfile == NULL);
+ assert(compact->outfile == nullptr);
}
delete compact->outfile;
for (size_t i = 0; i < compact->outputs.size(); i++) {
@@ -786,8 +794,8 @@ void DBImpl::CleanupCompaction(CompactionState* compact) {
}
Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) {
- assert(compact != NULL);
- assert(compact->builder == NULL);
+ assert(compact != nullptr);
+ assert(compact->builder == nullptr);
uint64_t file_number;
{
mutex_.Lock();
@@ -812,9 +820,9 @@ Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) {
Status DBImpl::FinishCompactionOutputFile(CompactionState* compact,
Iterator* input) {
- assert(compact != NULL);
- assert(compact->outfile != NULL);
- assert(compact->builder != NULL);
+ assert(compact != nullptr);
+ assert(compact->outfile != nullptr);
+ assert(compact->builder != nullptr);
const uint64_t output_number = compact->current_output()->number;
assert(output_number != 0);
@@ -831,7 +839,7 @@ Status DBImpl::FinishCompactionOutputFile(CompactionState* compact,
compact->current_output()->file_size = current_bytes;
compact->total_bytes += current_bytes;
delete compact->builder;
- compact->builder = NULL;
+ compact->builder = nullptr;
// Finish and check for file errors
if (s.ok()) {
@@ -841,35 +849,29 @@ Status DBImpl::FinishCompactionOutputFile(CompactionState* compact,
s = compact->outfile->Close();
}
delete compact->outfile;
- compact->outfile = NULL;
+ compact->outfile = nullptr;
if (s.ok() && current_entries > 0) {
// Verify that the table is usable
- Iterator* iter = table_cache_->NewIterator(ReadOptions(),
- output_number,
- current_bytes);
+ Iterator* iter =
+ table_cache_->NewIterator(ReadOptions(), output_number, current_bytes);
s = iter->status();
delete iter;
if (s.ok()) {
- Log(options_.info_log,
- "Generated table #%llu@%d: %lld keys, %lld bytes",
- (unsigned long long) output_number,
- compact->compaction->level(),
- (unsigned long long) current_entries,
- (unsigned long long) current_bytes);
+ Log(options_.info_log, "Generated table #%llu@%d: %lld keys, %lld bytes",
+ (unsigned long long)output_number, compact->compaction->level(),
+ (unsigned long long)current_entries,
+ (unsigned long long)current_bytes);
}
}
return s;
}
-
Status DBImpl::InstallCompactionResults(CompactionState* compact) {
mutex_.AssertHeld();
- Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes",
- compact->compaction->num_input_files(0),
- compact->compaction->level(),
- compact->compaction->num_input_files(1),
- compact->compaction->level() + 1,
+ Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes",
+ compact->compaction->num_input_files(0), compact->compaction->level(),
+ compact->compaction->num_input_files(1), compact->compaction->level() + 1,
static_cast<long long>(compact->total_bytes));
// Add compaction outputs
@@ -877,9 +879,8 @@ Status DBImpl::InstallCompactionResults(CompactionState* compact) {
const int level = compact->compaction->level();
for (size_t i = 0; i < compact->outputs.size(); i++) {
const CompactionState::Output& out = compact->outputs[i];
- compact->compaction->edit()->AddFile(
- level + 1,
- out.number, out.file_size, out.smallest, out.largest);
+ compact->compaction->edit()->AddFile(level + 1, out.number, out.file_size,
+ out.smallest, out.largest);
}
return versions_->LogAndApply(compact->compaction->edit(), &mutex_);
}
@@ -888,39 +889,40 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
const uint64_t start_micros = env_->NowMicros();
int64_t imm_micros = 0; // Micros spent doing imm_ compactions
- Log(options_.info_log, "Compacting %d@%d + %d@%d files",
- compact->compaction->num_input_files(0),
- compact->compaction->level(),
+ Log(options_.info_log, "Compacting %d@%d + %d@%d files",
+ compact->compaction->num_input_files(0), compact->compaction->level(),
compact->compaction->num_input_files(1),
compact->compaction->level() + 1);
assert(versions_->NumLevelFiles(compact->compaction->level()) > 0);
- assert(compact->builder == NULL);
- assert(compact->outfile == NULL);
+ assert(compact->builder == nullptr);
+ assert(compact->outfile == nullptr);
if (snapshots_.empty()) {
compact->smallest_snapshot = versions_->LastSequence();
} else {
- compact->smallest_snapshot = snapshots_.oldest()->number_;
+ compact->smallest_snapshot = snapshots_.oldest()->sequence_number();
}
+ Iterator* input = versions_->MakeInputIterator(compact->compaction);
+
// Release mutex while we're actually doing the compaction work
mutex_.Unlock();
- Iterator* input = versions_->MakeInputIterator(compact->compaction);
input->SeekToFirst();
Status status;
ParsedInternalKey ikey;
std::string current_user_key;
bool has_current_user_key = false;
SequenceNumber last_sequence_for_key = kMaxSequenceNumber;
- for (; input->Valid() && !shutting_down_.Acquire_Load(); ) {
+ while (input->Valid() && !shutting_down_.load(std::memory_order_acquire)) {
// Prioritize immutable compaction work
- if (has_imm_.NoBarrier_Load() != NULL) {
+ if (has_imm_.load(std::memory_order_relaxed)) {
const uint64_t imm_start = env_->NowMicros();
mutex_.Lock();
- if (imm_ != NULL) {
+ if (imm_ != nullptr) {
CompactMemTable();
- bg_cv_.SignalAll(); // Wakeup MakeRoomForWrite() if necessary
+ // Wake up MakeRoomForWrite() if necessary.
+ background_work_finished_signal_.SignalAll();
}
mutex_.Unlock();
imm_micros += (env_->NowMicros() - imm_start);
@@ -928,7 +930,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
Slice key = input->key();
if (compact->compaction->ShouldStopBefore(key) &&
- compact->builder != NULL) {
+ compact->builder != nullptr) {
status = FinishCompactionOutputFile(compact, input);
if (!status.ok()) {
break;
@@ -944,8 +946,8 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
last_sequence_for_key = kMaxSequenceNumber;
} else {
if (!has_current_user_key ||
- user_comparator()->Compare(ikey.user_key,
- Slice(current_user_key)) != 0) {
+ user_comparator()->Compare(ikey.user_key, Slice(current_user_key)) !=
+ 0) {
// First occurrence of this user key
current_user_key.assign(ikey.user_key.data(), ikey.user_key.size());
has_current_user_key = true;
@@ -954,7 +956,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
if (last_sequence_for_key <= compact->smallest_snapshot) {
// Hidden by an newer entry for same user key
- drop = true; // (A)
+ drop = true; // (A)
} else if (ikey.type == kTypeDeletion &&
ikey.sequence <= compact->smallest_snapshot &&
compact->compaction->IsBaseLevelForKey(ikey.user_key)) {
@@ -982,7 +984,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
if (!drop) {
// Open output file if necessary
- if (compact->builder == NULL) {
+ if (compact->builder == nullptr) {
status = OpenCompactionOutputFile(compact);
if (!status.ok()) {
break;
@@ -1007,17 +1009,17 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
input->Next();
}
- if (status.ok() && shutting_down_.Acquire_Load()) {
+ if (status.ok() && shutting_down_.load(std::memory_order_acquire)) {
status = Status::IOError("Deleting DB during compaction");
}
- if (status.ok() && compact->builder != NULL) {
+ if (status.ok() && compact->builder != nullptr) {
status = FinishCompactionOutputFile(compact, input);
}
if (status.ok()) {
status = input->status();
}
delete input;
- input = NULL;
+ input = nullptr;
CompactionStats stats;
stats.micros = env_->NowMicros() - start_micros - imm_micros;
@@ -1040,34 +1042,37 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
RecordBackgroundError(status);
}
VersionSet::LevelSummaryStorage tmp;
- Log(options_.info_log,
- "compacted to: %s", versions_->LevelSummary(&tmp));
+ Log(options_.info_log, "compacted to: %s", versions_->LevelSummary(&tmp));
return status;
}
namespace {
+
struct IterState {
- port::Mutex* mu;
- Version* version;
- MemTable* mem;
- MemTable* imm;
+ port::Mutex* const mu;
+ Version* const version GUARDED_BY(mu);
+ MemTable* const mem GUARDED_BY(mu);
+ MemTable* const imm GUARDED_BY(mu);
+
+ IterState(port::Mutex* mutex, MemTable* mem, MemTable* imm, Version* version)
+ : mu(mutex), version(version), mem(mem), imm(imm) {}
};
static void CleanupIteratorState(void* arg1, void* arg2) {
IterState* state = reinterpret_cast<IterState*>(arg1);
state->mu->Lock();
state->mem->Unref();
- if (state->imm != NULL) state->imm->Unref();
+ if (state->imm != nullptr) state->imm->Unref();
state->version->Unref();
state->mu->Unlock();
delete state;
}
-} // namespace
+
+} // anonymous namespace
Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
SequenceNumber* latest_snapshot,
uint32_t* seed) {
- IterState* cleanup = new IterState;
mutex_.Lock();
*latest_snapshot = versions_->LastSequence();
@@ -1075,7 +1080,7 @@ Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
std::vector<Iterator*> list;
list.push_back(mem_->NewIterator());
mem_->Ref();
- if (imm_ != NULL) {
+ if (imm_ != nullptr) {
list.push_back(imm_->NewIterator());
imm_->Ref();
}
@@ -1084,11 +1089,8 @@ Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
NewMergingIterator(&internal_comparator_, &list[0], list.size());
versions_->current()->Ref();
- cleanup->mu = &mutex_;
- cleanup->mem = mem_;
- cleanup->imm = imm_;
- cleanup->version = versions_->current();
- internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, NULL);
+ IterState* cleanup = new IterState(&mutex_, mem_, imm_, versions_->current());
+ internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, nullptr);
*seed = ++seed_;
mutex_.Unlock();
@@ -1106,14 +1108,14 @@ int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() {
return versions_->MaxNextLevelOverlappingBytes();
}
-Status DBImpl::Get(const ReadOptions& options,
- const Slice& key,
+Status DBImpl::Get(const ReadOptions& options, const Slice& key,
std::string* value) {
Status s;
MutexLock l(&mutex_);
SequenceNumber snapshot;
- if (options.snapshot != NULL) {
- snapshot = reinterpret_cast<const SnapshotImpl*>(options.snapshot)->number_;
+ if (options.snapshot != nullptr) {
+ snapshot =
+ static_cast<const SnapshotImpl*>(options.snapshot)->sequence_number();
} else {
snapshot = versions_->LastSequence();
}
@@ -1122,7 +1124,7 @@ Status DBImpl::Get(const ReadOptions& options,
MemTable* imm = imm_;
Version* current = versions_->current();
mem->Ref();
- if (imm != NULL) imm->Ref();
+ if (imm != nullptr) imm->Ref();
current->Ref();
bool have_stat_update = false;
@@ -1135,7 +1137,7 @@ Status DBImpl::Get(const ReadOptions& options,
LookupKey lkey(key, snapshot);
if (mem->Get(lkey, value, &s)) {
// Done
- } else if (imm != NULL && imm->Get(lkey, value, &s)) {
+ } else if (imm != nullptr && imm->Get(lkey, value, &s)) {
// Done
} else {
s = current->Get(options, lkey, value, &stats);
@@ -1148,7 +1150,7 @@ Status DBImpl::Get(const ReadOptions& options,
MaybeScheduleCompaction();
}
mem->Unref();
- if (imm != NULL) imm->Unref();
+ if (imm != nullptr) imm->Unref();
current->Unref();
return s;
}
@@ -1157,12 +1159,12 @@ Iterator* DBImpl::NewIterator(const ReadOptions& options) {
SequenceNumber latest_snapshot;
uint32_t seed;
Iterator* iter = NewInternalIterator(options, &latest_snapshot, &seed);
- return NewDBIterator(
- this, user_comparator(), iter,
- (options.snapshot != NULL
- ? reinterpret_cast<const SnapshotImpl*>(options.snapshot)->number_
- : latest_snapshot),
- seed);
+ return NewDBIterator(this, user_comparator(), iter,
+ (options.snapshot != nullptr
+ ? static_cast<const SnapshotImpl*>(options.snapshot)
+ ->sequence_number()
+ : latest_snapshot),
+ seed);
}
void DBImpl::RecordReadSample(Slice key) {
@@ -1177,9 +1179,9 @@ const Snapshot* DBImpl::GetSnapshot() {
return snapshots_.New(versions_->LastSequence());
}
-void DBImpl::ReleaseSnapshot(const Snapshot* s) {
+void DBImpl::ReleaseSnapshot(const Snapshot* snapshot) {
MutexLock l(&mutex_);
- snapshots_.Delete(reinterpret_cast<const SnapshotImpl*>(s));
+ snapshots_.Delete(static_cast<const SnapshotImpl*>(snapshot));
}
// Convenience methods
@@ -1191,9 +1193,9 @@ Status DBImpl::Delete(const WriteOptions& options, const Slice& key) {
return DB::Delete(options, key);
}
-Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
+Status DBImpl::Write(const WriteOptions& options, WriteBatch* updates) {
Writer w(&mutex_);
- w.batch = my_batch;
+ w.batch = updates;
w.sync = options.sync;
w.done = false;
@@ -1207,13 +1209,13 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
}
// May temporarily unlock and wait.
- Status status = MakeRoomForWrite(my_batch == NULL);
+ Status status = MakeRoomForWrite(updates == nullptr);
uint64_t last_sequence = versions_->LastSequence();
Writer* last_writer = &w;
- if (status.ok() && my_batch != NULL) { // NULL batch is for compactions
- WriteBatch* updates = BuildBatchGroup(&last_writer);
- WriteBatchInternal::SetSequence(updates, last_sequence + 1);
- last_sequence += WriteBatchInternal::Count(updates);
+ if (status.ok() && updates != nullptr) { // nullptr batch is for compactions
+ WriteBatch* write_batch = BuildBatchGroup(&last_writer);
+ WriteBatchInternal::SetSequence(write_batch, last_sequence + 1);
+ last_sequence += WriteBatchInternal::Count(write_batch);
// Add to log and apply to memtable. We can release the lock
// during this phase since &w is currently responsible for logging
@@ -1221,7 +1223,7 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
// into mem_.
{
mutex_.Unlock();
- status = log_->AddRecord(WriteBatchInternal::Contents(updates));
+ status = log_->AddRecord(WriteBatchInternal::Contents(write_batch));
bool sync_error = false;
if (status.ok() && options.sync) {
status = logfile_->Sync();
@@ -1230,7 +1232,7 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
}
}
if (status.ok()) {
- status = WriteBatchInternal::InsertInto(updates, mem_);
+ status = WriteBatchInternal::InsertInto(write_batch, mem_);
}
mutex_.Lock();
if (sync_error) {
@@ -1240,7 +1242,7 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
RecordBackgroundError(status);
}
}
- if (updates == tmp_batch_) tmp_batch_->Clear();
+ if (write_batch == tmp_batch_) tmp_batch_->Clear();
versions_->SetLastSequence(last_sequence);
}
@@ -1265,12 +1267,13 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
}
// REQUIRES: Writer list must be non-empty
-// REQUIRES: First writer must have a non-NULL batch
+// REQUIRES: First writer must have a non-null batch
WriteBatch* DBImpl::BuildBatchGroup(Writer** last_writer) {
+ mutex_.AssertHeld();
assert(!writers_.empty());
Writer* first = writers_.front();
WriteBatch* result = first->batch;
- assert(result != NULL);
+ assert(result != nullptr);
size_t size = WriteBatchInternal::ByteSize(first->batch);
@@ -1278,8 +1281,8 @@ WriteBatch* DBImpl::BuildBatchGroup(Writer** last_writer) {
// original write is small, limit the growth so we do not slow
// down the small write too much.
size_t max_size = 1 << 20;
- if (size <= (128<<10)) {
- max_size = size + (128<<10);
+ if (size <= (128 << 10)) {
+ max_size = size + (128 << 10);
}
*last_writer = first;
@@ -1292,7 +1295,7 @@ WriteBatch* DBImpl::BuildBatchGroup(Writer** last_writer) {
break;
}
- if (w->batch != NULL) {
+ if (w->batch != nullptr) {
size += WriteBatchInternal::ByteSize(w->batch);
if (size > max_size) {
// Do not make batch too big
@@ -1325,9 +1328,8 @@ Status DBImpl::MakeRoomForWrite(bool force) {
// Yield previous error
s = bg_error_;
break;
- } else if (
- allow_delay &&
- versions_->NumLevelFiles(0) >= config::kL0_SlowdownWritesTrigger) {
+ } else if (allow_delay && versions_->NumLevelFiles(0) >=
+ config::kL0_SlowdownWritesTrigger) {
// We are getting close to hitting a hard limit on the number of
// L0 files. Rather than delaying a single write by several
// seconds when we hit the hard limit, start delaying each
@@ -1342,20 +1344,20 @@ Status DBImpl::MakeRoomForWrite(bool force) {
(mem_->ApproximateMemoryUsage() <= options_.write_buffer_size)) {
// There is room in current memtable
break;
- } else if (imm_ != NULL) {
+ } else if (imm_ != nullptr) {
// We have filled up the current memtable, but the previous
// one is still being compacted, so we wait.
Log(options_.info_log, "Current memtable full; waiting...\n");
- bg_cv_.Wait();
+ background_work_finished_signal_.Wait();
} else if (versions_->NumLevelFiles(0) >= config::kL0_StopWritesTrigger) {
// There are too many level-0 files.
Log(options_.info_log, "Too many L0 files; waiting...\n");
- bg_cv_.Wait();
+ background_work_finished_signal_.Wait();
} else {
// Attempt to switch to a new memtable and trigger compaction of old
assert(versions_->PrevLogNumber() == 0);
uint64_t new_log_number = versions_->NewFileNumber();
- WritableFile* lfile = NULL;
+ WritableFile* lfile = nullptr;
s = env_->NewWritableFile(LogFileName(dbname_, new_log_number), &lfile);
if (!s.ok()) {
// Avoid chewing through file number space in a tight loop.
@@ -1368,10 +1370,10 @@ Status DBImpl::MakeRoomForWrite(bool force) {
logfile_number_ = new_log_number;
log_ = new log::Writer(lfile);
imm_ = mem_;
- has_imm_.Release_Store(imm_);
+ has_imm_.store(true, std::memory_order_release);
mem_ = new MemTable(internal_comparator_);
mem_->Ref();
- force = false; // Do not force another compaction if have room
+ force = false; // Do not force another compaction if have room
MaybeScheduleCompaction();
}
}
@@ -1405,21 +1407,16 @@ bool DBImpl::GetProperty(const Slice& property, std::string* value) {
snprintf(buf, sizeof(buf),
" Compactions\n"
"Level Files Size(MB) Time(sec) Read(MB) Write(MB)\n"
- "--------------------------------------------------\n"
- );
+ "--------------------------------------------------\n");
value->append(buf);
for (int level = 0; level < config::kNumLevels; level++) {
int files = versions_->NumLevelFiles(level);
if (stats_[level].micros > 0 || files > 0) {
- snprintf(
- buf, sizeof(buf),
- "%3d %8d %8.0f %9.0f %8.0f %9.0f\n",
- level,
- files,
- versions_->NumLevelBytes(level) / 1048576.0,
- stats_[level].micros / 1e6,
- stats_[level].bytes_read / 1048576.0,
- stats_[level].bytes_written / 1048576.0);
+ snprintf(buf, sizeof(buf), "%3d %8d %8.0f %9.0f %8.0f %9.0f\n", level,
+ files, versions_->NumLevelBytes(level) / 1048576.0,
+ stats_[level].micros / 1e6,
+ stats_[level].bytes_read / 1048576.0,
+ stats_[level].bytes_written / 1048576.0);
value->append(buf);
}
}
@@ -1445,16 +1442,11 @@ bool DBImpl::GetProperty(const Slice& property, std::string* value) {
return false;
}
-void DBImpl::GetApproximateSizes(
- const Range* range, int n,
- uint64_t* sizes) {
+void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) {
// TODO(opt): better implementation
- Version* v;
- {
- MutexLock l(&mutex_);
- versions_->current()->Ref();
- v = versions_->current();
- }
+ MutexLock l(&mutex_);
+ Version* v = versions_->current();
+ v->Ref();
for (int i = 0; i < n; i++) {
// Convert user_key into a corresponding internal key.
@@ -1465,10 +1457,7 @@ void DBImpl::GetApproximateSizes(
sizes[i] = (limit >= start ? limit - start : 0);
}
- {
- MutexLock l(&mutex_);
- v->Unref();
- }
+ v->Unref();
}
// Default implementations of convenience methods that subclasses of DB
@@ -1485,11 +1474,10 @@ Status DB::Delete(const WriteOptions& opt, const Slice& key) {
return Write(opt, &batch);
}
-DB::~DB() { }
+DB::~DB() = default;
-Status DB::Open(const Options& options, const std::string& dbname,
- DB** dbptr) {
- *dbptr = NULL;
+Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) {
+ *dbptr = nullptr;
DBImpl* impl = new DBImpl(options, dbname);
impl->mutex_.Lock();
@@ -1497,7 +1485,7 @@ Status DB::Open(const Options& options, const std::string& dbname,
// Recover handles create_if_missing, error_if_exists
bool save_manifest = false;
Status s = impl->Recover(&edit, &save_manifest);
- if (s.ok() && impl->mem_ == NULL) {
+ if (s.ok() && impl->mem_ == nullptr) {
// Create new log and a corresponding memtable.
uint64_t new_log_number = impl->versions_->NewFileNumber();
WritableFile* lfile;
@@ -1523,7 +1511,7 @@ Status DB::Open(const Options& options, const std::string& dbname,
}
impl->mutex_.Unlock();
if (s.ok()) {
- assert(impl->mem_ != NULL);
+ assert(impl->mem_ != nullptr);
*dbptr = impl;
} else {
delete impl;
@@ -1531,21 +1519,20 @@ Status DB::Open(const Options& options, const std::string& dbname,
return s;
}
-Snapshot::~Snapshot() {
-}
+Snapshot::~Snapshot() = default;
Status DestroyDB(const std::string& dbname, const Options& options) {
Env* env = options.env;
std::vector<std::string> filenames;
- // Ignore error in case directory does not exist
- env->GetChildren(dbname, &filenames);
- if (filenames.empty()) {
+ Status result = env->GetChildren(dbname, &filenames);
+ if (!result.ok()) {
+ // Ignore error in case directory does not exist
return Status::OK();
}
FileLock* lock;
const std::string lockname = LockFileName(dbname);
- Status result = env->LockFile(lockname, &lock);
+ result = env->LockFile(lockname, &lock);
if (result.ok()) {
uint64_t number;
FileType type;
diff --git a/src/leveldb/db/db_impl.h b/src/leveldb/db/db_impl.h
index 8ff323e728..685735c733 100644
--- a/src/leveldb/db/db_impl.h
+++ b/src/leveldb/db/db_impl.h
@@ -5,8 +5,11 @@
#ifndef STORAGE_LEVELDB_DB_DB_IMPL_H_
#define STORAGE_LEVELDB_DB_DB_IMPL_H_
+#include <atomic>
#include <deque>
#include <set>
+#include <string>
+
#include "db/dbformat.h"
#include "db/log_writer.h"
#include "db/snapshot.h"
@@ -26,21 +29,25 @@ class VersionSet;
class DBImpl : public DB {
public:
DBImpl(const Options& options, const std::string& dbname);
- virtual ~DBImpl();
+
+ DBImpl(const DBImpl&) = delete;
+ DBImpl& operator=(const DBImpl&) = delete;
+
+ ~DBImpl() override;
// Implementations of the DB interface
- virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value);
- virtual Status Delete(const WriteOptions&, const Slice& key);
- virtual Status Write(const WriteOptions& options, WriteBatch* updates);
- virtual Status Get(const ReadOptions& options,
- const Slice& key,
- std::string* value);
- virtual Iterator* NewIterator(const ReadOptions&);
- virtual const Snapshot* GetSnapshot();
- virtual void ReleaseSnapshot(const Snapshot* snapshot);
- virtual bool GetProperty(const Slice& property, std::string* value);
- virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes);
- virtual void CompactRange(const Slice* begin, const Slice* end);
+ Status Put(const WriteOptions&, const Slice& key,
+ const Slice& value) override;
+ Status Delete(const WriteOptions&, const Slice& key) override;
+ Status Write(const WriteOptions& options, WriteBatch* updates) override;
+ Status Get(const ReadOptions& options, const Slice& key,
+ std::string* value) override;
+ Iterator* NewIterator(const ReadOptions&) override;
+ const Snapshot* GetSnapshot() override;
+ void ReleaseSnapshot(const Snapshot* snapshot) override;
+ bool GetProperty(const Slice& property, std::string* value) override;
+ void GetApproximateSizes(const Range* range, int n, uint64_t* sizes) override;
+ void CompactRange(const Slice* begin, const Slice* end) override;
// Extra methods (for testing) that are not in the public DB interface
@@ -69,6 +76,31 @@ class DBImpl : public DB {
struct CompactionState;
struct Writer;
+ // Information for a manual compaction
+ struct ManualCompaction {
+ int level;
+ bool done;
+ const InternalKey* begin; // null means beginning of key range
+ const InternalKey* end; // null means end of key range
+ InternalKey tmp_storage; // Used to keep track of compaction progress
+ };
+
+ // Per level compaction stats. stats_[level] stores the stats for
+ // compactions that produced data for the specified "level".
+ struct CompactionStats {
+ CompactionStats() : micros(0), bytes_read(0), bytes_written(0) {}
+
+ void Add(const CompactionStats& c) {
+ this->micros += c.micros;
+ this->bytes_read += c.bytes_read;
+ this->bytes_written += c.bytes_written;
+ }
+
+ int64_t micros;
+ int64_t bytes_read;
+ int64_t bytes_written;
+ };
+
Iterator* NewInternalIterator(const ReadOptions&,
SequenceNumber* latest_snapshot,
uint32_t* seed);
@@ -84,7 +116,7 @@ class DBImpl : public DB {
void MaybeIgnoreError(Status* s) const;
// Delete any unneeded files and stale in-memory entries.
- void DeleteObsoleteFiles();
+ void DeleteObsoleteFiles() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Compact the in-memory write buffer to disk. Switches to a new
// log-file/memtable and writes a new descriptor iff successful.
@@ -100,14 +132,15 @@ class DBImpl : public DB {
Status MakeRoomForWrite(bool force /* compact even if there is room? */)
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
- WriteBatch* BuildBatchGroup(Writer** last_writer);
+ WriteBatch* BuildBatchGroup(Writer** last_writer)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void RecordBackgroundError(const Status& s);
void MaybeScheduleCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
static void BGWork(void* db);
void BackgroundCall();
- void BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ void BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void CleanupCompaction(CompactionState* compact)
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Status DoCompactionWork(CompactionState* compact)
@@ -118,93 +151,66 @@ class DBImpl : public DB {
Status InstallCompactionResults(CompactionState* compact)
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ const Comparator* user_comparator() const {
+ return internal_comparator_.user_comparator();
+ }
+
// Constant after construction
Env* const env_;
const InternalKeyComparator internal_comparator_;
const InternalFilterPolicy internal_filter_policy_;
const Options options_; // options_.comparator == &internal_comparator_
- bool owns_info_log_;
- bool owns_cache_;
+ const bool owns_info_log_;
+ const bool owns_cache_;
const std::string dbname_;
// table_cache_ provides its own synchronization
- TableCache* table_cache_;
+ TableCache* const table_cache_;
- // Lock over the persistent DB state. Non-NULL iff successfully acquired.
+ // Lock over the persistent DB state. Non-null iff successfully acquired.
FileLock* db_lock_;
// State below is protected by mutex_
port::Mutex mutex_;
- port::AtomicPointer shutting_down_;
- port::CondVar bg_cv_; // Signalled when background work finishes
+ std::atomic<bool> shutting_down_;
+ port::CondVar background_work_finished_signal_ GUARDED_BY(mutex_);
MemTable* mem_;
- MemTable* imm_; // Memtable being compacted
- port::AtomicPointer has_imm_; // So bg thread can detect non-NULL imm_
+ MemTable* imm_ GUARDED_BY(mutex_); // Memtable being compacted
+ std::atomic<bool> has_imm_; // So bg thread can detect non-null imm_
WritableFile* logfile_;
- uint64_t logfile_number_;
+ uint64_t logfile_number_ GUARDED_BY(mutex_);
log::Writer* log_;
- uint32_t seed_; // For sampling.
+ uint32_t seed_ GUARDED_BY(mutex_); // For sampling.
// Queue of writers.
- std::deque<Writer*> writers_;
- WriteBatch* tmp_batch_;
+ std::deque<Writer*> writers_ GUARDED_BY(mutex_);
+ WriteBatch* tmp_batch_ GUARDED_BY(mutex_);
- SnapshotList snapshots_;
+ SnapshotList snapshots_ GUARDED_BY(mutex_);
// Set of table files to protect from deletion because they are
// part of ongoing compactions.
- std::set<uint64_t> pending_outputs_;
+ std::set<uint64_t> pending_outputs_ GUARDED_BY(mutex_);
// Has a background compaction been scheduled or is running?
- bool bg_compaction_scheduled_;
+ bool background_compaction_scheduled_ GUARDED_BY(mutex_);
- // Information for a manual compaction
- struct ManualCompaction {
- int level;
- bool done;
- const InternalKey* begin; // NULL means beginning of key range
- const InternalKey* end; // NULL means end of key range
- InternalKey tmp_storage; // Used to keep track of compaction progress
- };
- ManualCompaction* manual_compaction_;
+ ManualCompaction* manual_compaction_ GUARDED_BY(mutex_);
- VersionSet* versions_;
+ VersionSet* const versions_ GUARDED_BY(mutex_);
// Have we encountered a background error in paranoid mode?
- Status bg_error_;
-
- // Per level compaction stats. stats_[level] stores the stats for
- // compactions that produced data for the specified "level".
- struct CompactionStats {
- int64_t micros;
- int64_t bytes_read;
- int64_t bytes_written;
-
- CompactionStats() : micros(0), bytes_read(0), bytes_written(0) { }
+ Status bg_error_ GUARDED_BY(mutex_);
- void Add(const CompactionStats& c) {
- this->micros += c.micros;
- this->bytes_read += c.bytes_read;
- this->bytes_written += c.bytes_written;
- }
- };
- CompactionStats stats_[config::kNumLevels];
-
- // No copying allowed
- DBImpl(const DBImpl&);
- void operator=(const DBImpl&);
-
- const Comparator* user_comparator() const {
- return internal_comparator_.user_comparator();
- }
+ CompactionStats stats_[config::kNumLevels] GUARDED_BY(mutex_);
};
// Sanitize db options. The caller should delete result.info_log if
// it is not equal to src.info_log.
-extern Options SanitizeOptions(const std::string& db,
- const InternalKeyComparator* icmp,
- const InternalFilterPolicy* ipolicy,
- const Options& src);
+Options SanitizeOptions(const std::string& db,
+ const InternalKeyComparator* icmp,
+ const InternalFilterPolicy* ipolicy,
+ const Options& src);
} // namespace leveldb
diff --git a/src/leveldb/db/db_iter.cc b/src/leveldb/db/db_iter.cc
index 3b2035e9e3..98715a9502 100644
--- a/src/leveldb/db/db_iter.cc
+++ b/src/leveldb/db/db_iter.cc
@@ -4,9 +4,9 @@
#include "db/db_iter.h"
-#include "db/filename.h"
#include "db/db_impl.h"
#include "db/dbformat.h"
+#include "db/filename.h"
#include "leveldb/env.h"
#include "leveldb/iterator.h"
#include "port/port.h"
@@ -36,17 +36,14 @@ namespace {
// combines multiple entries for the same userkey found in the DB
// representation into a single entry while accounting for sequence
// numbers, deletion markers, overwrites, etc.
-class DBIter: public Iterator {
+class DBIter : public Iterator {
public:
// Which direction is the iterator currently moving?
// (1) When moving forward, the internal iterator is positioned at
// the exact entry that yields this->key(), this->value()
// (2) When moving backwards, the internal iterator is positioned
// just before all entries whose user key == this->key().
- enum Direction {
- kForward,
- kReverse
- };
+ enum Direction { kForward, kReverse };
DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s,
uint32_t seed)
@@ -57,21 +54,22 @@ class DBIter: public Iterator {
direction_(kForward),
valid_(false),
rnd_(seed),
- bytes_counter_(RandomPeriod()) {
- }
- virtual ~DBIter() {
- delete iter_;
- }
- virtual bool Valid() const { return valid_; }
- virtual Slice key() const {
+ bytes_until_read_sampling_(RandomCompactionPeriod()) {}
+
+ DBIter(const DBIter&) = delete;
+ DBIter& operator=(const DBIter&) = delete;
+
+ ~DBIter() override { delete iter_; }
+ bool Valid() const override { return valid_; }
+ Slice key() const override {
assert(valid_);
return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_;
}
- virtual Slice value() const {
+ Slice value() const override {
assert(valid_);
return (direction_ == kForward) ? iter_->value() : saved_value_;
}
- virtual Status status() const {
+ Status status() const override {
if (status_.ok()) {
return iter_->status();
} else {
@@ -79,11 +77,11 @@ class DBIter: public Iterator {
}
}
- virtual void Next();
- virtual void Prev();
- virtual void Seek(const Slice& target);
- virtual void SeekToFirst();
- virtual void SeekToLast();
+ void Next() override;
+ void Prev() override;
+ void Seek(const Slice& target) override;
+ void SeekToFirst() override;
+ void SeekToLast() override;
private:
void FindNextUserEntry(bool skipping, std::string* skip);
@@ -103,38 +101,35 @@ class DBIter: public Iterator {
}
}
- // Pick next gap with average value of config::kReadBytesPeriod.
- ssize_t RandomPeriod() {
- return rnd_.Uniform(2*config::kReadBytesPeriod);
+ // Picks the number of bytes that can be read until a compaction is scheduled.
+ size_t RandomCompactionPeriod() {
+ return rnd_.Uniform(2 * config::kReadBytesPeriod);
}
DBImpl* db_;
const Comparator* const user_comparator_;
Iterator* const iter_;
SequenceNumber const sequence_;
-
Status status_;
- std::string saved_key_; // == current key when direction_==kReverse
- std::string saved_value_; // == current raw value when direction_==kReverse
+ std::string saved_key_; // == current key when direction_==kReverse
+ std::string saved_value_; // == current raw value when direction_==kReverse
Direction direction_;
bool valid_;
-
Random rnd_;
- ssize_t bytes_counter_;
-
- // No copying allowed
- DBIter(const DBIter&);
- void operator=(const DBIter&);
+ size_t bytes_until_read_sampling_;
};
inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {
Slice k = iter_->key();
- ssize_t n = k.size() + iter_->value().size();
- bytes_counter_ -= n;
- while (bytes_counter_ < 0) {
- bytes_counter_ += RandomPeriod();
+
+ size_t bytes_read = k.size() + iter_->value().size();
+ while (bytes_until_read_sampling_ < bytes_read) {
+ bytes_until_read_sampling_ += RandomCompactionPeriod();
db_->RecordReadSample(k);
}
+ assert(bytes_until_read_sampling_ >= bytes_read);
+ bytes_until_read_sampling_ -= bytes_read;
+
if (!ParseInternalKey(k, ikey)) {
status_ = Status::Corruption("corrupted internal key in DBIter");
return false;
@@ -165,6 +160,15 @@ void DBIter::Next() {
} else {
// Store in saved_key_ the current key so we skip it below.
SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
+
+ // iter_ is pointing to current key. We can now safely move to the next to
+ // avoid checking current key.
+ iter_->Next();
+ if (!iter_->Valid()) {
+ valid_ = false;
+ saved_key_.clear();
+ return;
+ }
}
FindNextUserEntry(true, &saved_key_);
@@ -218,8 +222,8 @@ void DBIter::Prev() {
ClearSavedValue();
return;
}
- if (user_comparator_->Compare(ExtractUserKey(iter_->key()),
- saved_key_) < 0) {
+ if (user_comparator_->Compare(ExtractUserKey(iter_->key()), saved_key_) <
+ 0) {
break;
}
}
@@ -275,8 +279,8 @@ void DBIter::Seek(const Slice& target) {
direction_ = kForward;
ClearSavedValue();
saved_key_.clear();
- AppendInternalKey(
- &saved_key_, ParsedInternalKey(target, sequence_, kValueTypeForSeek));
+ AppendInternalKey(&saved_key_,
+ ParsedInternalKey(target, sequence_, kValueTypeForSeek));
iter_->Seek(saved_key_);
if (iter_->Valid()) {
FindNextUserEntry(false, &saved_key_ /* temporary storage */);
@@ -305,12 +309,9 @@ void DBIter::SeekToLast() {
} // anonymous namespace
-Iterator* NewDBIterator(
- DBImpl* db,
- const Comparator* user_key_comparator,
- Iterator* internal_iter,
- SequenceNumber sequence,
- uint32_t seed) {
+Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator,
+ Iterator* internal_iter, SequenceNumber sequence,
+ uint32_t seed) {
return new DBIter(db, user_key_comparator, internal_iter, sequence, seed);
}
diff --git a/src/leveldb/db/db_iter.h b/src/leveldb/db/db_iter.h
index 04927e937b..fd93e912a0 100644
--- a/src/leveldb/db/db_iter.h
+++ b/src/leveldb/db/db_iter.h
@@ -6,8 +6,9 @@
#define STORAGE_LEVELDB_DB_DB_ITER_H_
#include <stdint.h>
-#include "leveldb/db.h"
+
#include "db/dbformat.h"
+#include "leveldb/db.h"
namespace leveldb {
@@ -16,12 +17,9 @@ class DBImpl;
// Return a new iterator that converts internal keys (yielded by
// "*internal_iter") that were live at the specified "sequence" number
// into appropriate user keys.
-extern Iterator* NewDBIterator(
- DBImpl* db,
- const Comparator* user_key_comparator,
- Iterator* internal_iter,
- SequenceNumber sequence,
- uint32_t seed);
+Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator,
+ Iterator* internal_iter, SequenceNumber sequence,
+ uint32_t seed);
} // namespace leveldb
diff --git a/src/leveldb/db/db_test.cc b/src/leveldb/db/db_test.cc
index a0b08bc19c..beb1d3bdef 100644
--- a/src/leveldb/db/db_test.cc
+++ b/src/leveldb/db/db_test.cc
@@ -3,14 +3,20 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "leveldb/db.h"
-#include "leveldb/filter_policy.h"
+
+#include <atomic>
+#include <string>
+
#include "db/db_impl.h"
#include "db/filename.h"
#include "db/version_set.h"
#include "db/write_batch_internal.h"
#include "leveldb/cache.h"
#include "leveldb/env.h"
+#include "leveldb/filter_policy.h"
#include "leveldb/table.h"
+#include "port/port.h"
+#include "port/thread_annotations.h"
#include "util/hash.h"
#include "util/logging.h"
#include "util/mutexlock.h"
@@ -25,83 +31,116 @@ static std::string RandomString(Random* rnd, int len) {
return r;
}
+static std::string RandomKey(Random* rnd) {
+ int len =
+ (rnd->OneIn(3) ? 1 // Short sometimes to encourage collisions
+ : (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10)));
+ return test::RandomKey(rnd, len);
+}
+
namespace {
class AtomicCounter {
- private:
- port::Mutex mu_;
- int count_;
public:
- AtomicCounter() : count_(0) { }
- void Increment() {
- IncrementBy(1);
- }
- void IncrementBy(int count) {
+ AtomicCounter() : count_(0) {}
+ void Increment() { IncrementBy(1); }
+ void IncrementBy(int count) LOCKS_EXCLUDED(mu_) {
MutexLock l(&mu_);
count_ += count;
}
- int Read() {
+ int Read() LOCKS_EXCLUDED(mu_) {
MutexLock l(&mu_);
return count_;
}
- void Reset() {
+ void Reset() LOCKS_EXCLUDED(mu_) {
MutexLock l(&mu_);
count_ = 0;
}
+
+ private:
+ port::Mutex mu_;
+ int count_ GUARDED_BY(mu_);
};
void DelayMilliseconds(int millis) {
Env::Default()->SleepForMicroseconds(millis * 1000);
}
-}
+} // namespace
+
+// Test Env to override default Env behavior for testing.
+class TestEnv : public EnvWrapper {
+ public:
+ explicit TestEnv(Env* base) : EnvWrapper(base), ignore_dot_files_(false) {}
+
+ void SetIgnoreDotFiles(bool ignored) { ignore_dot_files_ = ignored; }
+
+ Status GetChildren(const std::string& dir,
+ std::vector<std::string>* result) override {
+ Status s = target()->GetChildren(dir, result);
+ if (!s.ok() || !ignore_dot_files_) {
+ return s;
+ }
+
+ std::vector<std::string>::iterator it = result->begin();
+ while (it != result->end()) {
+ if ((*it == ".") || (*it == "..")) {
+ it = result->erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ return s;
+ }
+
+ private:
+ bool ignore_dot_files_;
+};
-// Special Env used to delay background operations
+// Special Env used to delay background operations.
class SpecialEnv : public EnvWrapper {
public:
- // sstable/log Sync() calls are blocked while this pointer is non-NULL.
- port::AtomicPointer delay_data_sync_;
+ // sstable/log Sync() calls are blocked while this pointer is non-null.
+ std::atomic<bool> delay_data_sync_;
// sstable/log Sync() calls return an error.
- port::AtomicPointer data_sync_error_;
+ std::atomic<bool> data_sync_error_;
- // Simulate no-space errors while this pointer is non-NULL.
- port::AtomicPointer no_space_;
+ // Simulate no-space errors while this pointer is non-null.
+ std::atomic<bool> no_space_;
- // Simulate non-writable file system while this pointer is non-NULL
- port::AtomicPointer non_writable_;
+ // Simulate non-writable file system while this pointer is non-null.
+ std::atomic<bool> non_writable_;
- // Force sync of manifest files to fail while this pointer is non-NULL
- port::AtomicPointer manifest_sync_error_;
+ // Force sync of manifest files to fail while this pointer is non-null.
+ std::atomic<bool> manifest_sync_error_;
- // Force write to manifest files to fail while this pointer is non-NULL
- port::AtomicPointer manifest_write_error_;
+ // Force write to manifest files to fail while this pointer is non-null.
+ std::atomic<bool> manifest_write_error_;
bool count_random_reads_;
AtomicCounter random_read_counter_;
- explicit SpecialEnv(Env* base) : EnvWrapper(base) {
- delay_data_sync_.Release_Store(NULL);
- data_sync_error_.Release_Store(NULL);
- no_space_.Release_Store(NULL);
- non_writable_.Release_Store(NULL);
- count_random_reads_ = false;
- manifest_sync_error_.Release_Store(NULL);
- manifest_write_error_.Release_Store(NULL);
- }
+ explicit SpecialEnv(Env* base)
+ : EnvWrapper(base),
+ delay_data_sync_(false),
+ data_sync_error_(false),
+ no_space_(false),
+ non_writable_(false),
+ manifest_sync_error_(false),
+ manifest_write_error_(false),
+ count_random_reads_(false) {}
Status NewWritableFile(const std::string& f, WritableFile** r) {
class DataFile : public WritableFile {
private:
- SpecialEnv* env_;
- WritableFile* base_;
+ SpecialEnv* const env_;
+ WritableFile* const base_;
public:
- DataFile(SpecialEnv* env, WritableFile* base)
- : env_(env),
- base_(base) {
- }
+ DataFile(SpecialEnv* env, WritableFile* base) : env_(env), base_(base) {}
~DataFile() { delete base_; }
Status Append(const Slice& data) {
- if (env_->no_space_.Acquire_Load() != NULL) {
+ if (env_->no_space_.load(std::memory_order_acquire)) {
// Drop writes on the floor
return Status::OK();
} else {
@@ -111,24 +150,26 @@ class SpecialEnv : public EnvWrapper {
Status Close() { return base_->Close(); }
Status Flush() { return base_->Flush(); }
Status Sync() {
- if (env_->data_sync_error_.Acquire_Load() != NULL) {
+ if (env_->data_sync_error_.load(std::memory_order_acquire)) {
return Status::IOError("simulated data sync error");
}
- while (env_->delay_data_sync_.Acquire_Load() != NULL) {
+ while (env_->delay_data_sync_.load(std::memory_order_acquire)) {
DelayMilliseconds(100);
}
return base_->Sync();
}
+ std::string GetName() const override { return ""; }
};
class ManifestFile : public WritableFile {
private:
SpecialEnv* env_;
WritableFile* base_;
+
public:
- ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) { }
+ ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) {}
~ManifestFile() { delete base_; }
Status Append(const Slice& data) {
- if (env_->manifest_write_error_.Acquire_Load() != NULL) {
+ if (env_->manifest_write_error_.load(std::memory_order_acquire)) {
return Status::IOError("simulated writer error");
} else {
return base_->Append(data);
@@ -137,24 +178,25 @@ class SpecialEnv : public EnvWrapper {
Status Close() { return base_->Close(); }
Status Flush() { return base_->Flush(); }
Status Sync() {
- if (env_->manifest_sync_error_.Acquire_Load() != NULL) {
+ if (env_->manifest_sync_error_.load(std::memory_order_acquire)) {
return Status::IOError("simulated sync error");
} else {
return base_->Sync();
}
}
+ std::string GetName() const override { return ""; }
};
- if (non_writable_.Acquire_Load() != NULL) {
+ if (non_writable_.load(std::memory_order_acquire)) {
return Status::IOError("simulated write error");
}
Status s = target()->NewWritableFile(f, r);
if (s.ok()) {
- if (strstr(f.c_str(), ".ldb") != NULL ||
- strstr(f.c_str(), ".log") != NULL) {
+ if (strstr(f.c_str(), ".ldb") != nullptr ||
+ strstr(f.c_str(), ".log") != nullptr) {
*r = new DataFile(this, *r);
- } else if (strstr(f.c_str(), "MANIFEST") != NULL) {
+ } else if (strstr(f.c_str(), "MANIFEST") != nullptr) {
*r = new ManifestFile(this, *r);
}
}
@@ -166,16 +208,17 @@ class SpecialEnv : public EnvWrapper {
private:
RandomAccessFile* target_;
AtomicCounter* counter_;
+
public:
CountingFile(RandomAccessFile* target, AtomicCounter* counter)
- : target_(target), counter_(counter) {
- }
- virtual ~CountingFile() { delete target_; }
- virtual Status Read(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
+ : target_(target), counter_(counter) {}
+ ~CountingFile() override { delete target_; }
+ Status Read(uint64_t offset, size_t n, Slice* result,
+ char* scratch) const override {
counter_->Increment();
return target_->Read(offset, n, result, scratch);
}
+ std::string GetName() const override { return ""; }
};
Status s = target()->NewRandomAccessFile(f, r);
@@ -187,19 +230,6 @@ class SpecialEnv : public EnvWrapper {
};
class DBTest {
- private:
- const FilterPolicy* filter_policy_;
-
- // Sequence of option configurations to try
- enum OptionConfig {
- kDefault,
- kReuse,
- kFilter,
- kUncompressed,
- kEnd
- };
- int option_config_;
-
public:
std::string dbname_;
SpecialEnv* env_;
@@ -207,12 +237,11 @@ class DBTest {
Options last_options_;
- DBTest() : option_config_(kDefault),
- env_(new SpecialEnv(Env::Default())) {
+ DBTest() : env_(new SpecialEnv(Env::Default())), option_config_(kDefault) {
filter_policy_ = NewBloomFilterPolicy(10);
dbname_ = test::TmpDir() + "/db_test";
DestroyDB(dbname_, Options());
- db_ = NULL;
+ db_ = nullptr;
Reopen();
}
@@ -255,31 +284,27 @@ class DBTest {
return options;
}
- DBImpl* dbfull() {
- return reinterpret_cast<DBImpl*>(db_);
- }
+ DBImpl* dbfull() { return reinterpret_cast<DBImpl*>(db_); }
- void Reopen(Options* options = NULL) {
- ASSERT_OK(TryReopen(options));
- }
+ void Reopen(Options* options = nullptr) { ASSERT_OK(TryReopen(options)); }
void Close() {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
}
- void DestroyAndReopen(Options* options = NULL) {
+ void DestroyAndReopen(Options* options = nullptr) {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
DestroyDB(dbname_, Options());
ASSERT_OK(TryReopen(options));
}
Status TryReopen(Options* options) {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
Options opts;
- if (options != NULL) {
+ if (options != nullptr) {
opts = *options;
} else {
opts = CurrentOptions();
@@ -294,11 +319,9 @@ class DBTest {
return db_->Put(WriteOptions(), k, v);
}
- Status Delete(const std::string& k) {
- return db_->Delete(WriteOptions(), k);
- }
+ Status Delete(const std::string& k) { return db_->Delete(WriteOptions(), k); }
- std::string Get(const std::string& k, const Snapshot* snapshot = NULL) {
+ std::string Get(const std::string& k, const Snapshot* snapshot = nullptr) {
ReadOptions options;
options.snapshot = snapshot;
std::string result;
@@ -382,10 +405,9 @@ class DBTest {
int NumTableFilesAtLevel(int level) {
std::string property;
- ASSERT_TRUE(
- db_->GetProperty("leveldb.num-files-at-level" + NumberToString(level),
- &property));
- return atoi(property.c_str());
+ ASSERT_TRUE(db_->GetProperty(
+ "leveldb.num-files-at-level" + NumberToString(level), &property));
+ return std::stoi(property);
}
int TotalTableFiles() {
@@ -431,11 +453,12 @@ class DBTest {
}
// Do n memtable compactions, each of which produces an sstable
- // covering the range [small,large].
- void MakeTables(int n, const std::string& small, const std::string& large) {
+ // covering the range [small_key,large_key].
+ void MakeTables(int n, const std::string& small_key,
+ const std::string& large_key) {
for (int i = 0; i < n; i++) {
- Put(small, "begin");
- Put(large, "end");
+ Put(small_key, "begin");
+ Put(large_key, "end");
dbfull()->TEST_CompactMemTable();
}
}
@@ -448,9 +471,9 @@ class DBTest {
void DumpFileCounts(const char* label) {
fprintf(stderr, "---\n%s:\n", label);
- fprintf(stderr, "maxoverlap: %lld\n",
- static_cast<long long>(
- dbfull()->TEST_MaxNextLevelOverlappingBytes()));
+ fprintf(
+ stderr, "maxoverlap: %lld\n",
+ static_cast<long long>(dbfull()->TEST_MaxNextLevelOverlappingBytes()));
for (int level = 0; level < config::kNumLevels; level++) {
int num = NumTableFilesAtLevel(level);
if (num > 0) {
@@ -506,15 +529,42 @@ class DBTest {
}
return files_renamed;
}
+
+ private:
+ // Sequence of option configurations to try
+ enum OptionConfig { kDefault, kReuse, kFilter, kUncompressed, kEnd };
+
+ const FilterPolicy* filter_policy_;
+ int option_config_;
};
TEST(DBTest, Empty) {
do {
- ASSERT_TRUE(db_ != NULL);
+ ASSERT_TRUE(db_ != nullptr);
ASSERT_EQ("NOT_FOUND", Get("foo"));
} while (ChangeOptions());
}
+TEST(DBTest, EmptyKey) {
+ do {
+ ASSERT_OK(Put("", "v1"));
+ ASSERT_EQ("v1", Get(""));
+ ASSERT_OK(Put("", "v2"));
+ ASSERT_EQ("v2", Get(""));
+ } while (ChangeOptions());
+}
+
+TEST(DBTest, EmptyValue) {
+ do {
+ ASSERT_OK(Put("key", "v1"));
+ ASSERT_EQ("v1", Get("key"));
+ ASSERT_OK(Put("key", ""));
+ ASSERT_EQ("", Get("key"));
+ ASSERT_OK(Put("key", "v2"));
+ ASSERT_EQ("v2", Get("key"));
+ } while (ChangeOptions());
+}
+
TEST(DBTest, ReadWrite) {
do {
ASSERT_OK(Put("foo", "v1"));
@@ -547,11 +597,13 @@ TEST(DBTest, GetFromImmutableLayer) {
ASSERT_OK(Put("foo", "v1"));
ASSERT_EQ("v1", Get("foo"));
- env_->delay_data_sync_.Release_Store(env_); // Block sync calls
- Put("k1", std::string(100000, 'x')); // Fill memtable
- Put("k2", std::string(100000, 'y')); // Trigger compaction
+ // Block sync calls.
+ env_->delay_data_sync_.store(true, std::memory_order_release);
+ Put("k1", std::string(100000, 'x')); // Fill memtable.
+ Put("k2", std::string(100000, 'y')); // Trigger compaction.
ASSERT_EQ("v1", Get("foo"));
- env_->delay_data_sync_.Release_Store(NULL); // Release sync calls
+ // Release sync calls.
+ env_->delay_data_sync_.store(false, std::memory_order_release);
} while (ChangeOptions());
}
@@ -568,9 +620,9 @@ TEST(DBTest, GetMemUsage) {
ASSERT_OK(Put("foo", "v1"));
std::string val;
ASSERT_TRUE(db_->GetProperty("leveldb.approximate-memory-usage", &val));
- int mem_usage = atoi(val.c_str());
+ int mem_usage = std::stoi(val);
ASSERT_GT(mem_usage, 0);
- ASSERT_LT(mem_usage, 5*1024*1024);
+ ASSERT_LT(mem_usage, 5 * 1024 * 1024);
} while (ChangeOptions());
}
@@ -592,6 +644,55 @@ TEST(DBTest, GetSnapshot) {
} while (ChangeOptions());
}
+TEST(DBTest, GetIdenticalSnapshots) {
+ do {
+ // Try with both a short key and a long key
+ for (int i = 0; i < 2; i++) {
+ std::string key = (i == 0) ? std::string("foo") : std::string(200, 'x');
+ ASSERT_OK(Put(key, "v1"));
+ const Snapshot* s1 = db_->GetSnapshot();
+ const Snapshot* s2 = db_->GetSnapshot();
+ const Snapshot* s3 = db_->GetSnapshot();
+ ASSERT_OK(Put(key, "v2"));
+ ASSERT_EQ("v2", Get(key));
+ ASSERT_EQ("v1", Get(key, s1));
+ ASSERT_EQ("v1", Get(key, s2));
+ ASSERT_EQ("v1", Get(key, s3));
+ db_->ReleaseSnapshot(s1);
+ dbfull()->TEST_CompactMemTable();
+ ASSERT_EQ("v2", Get(key));
+ ASSERT_EQ("v1", Get(key, s2));
+ db_->ReleaseSnapshot(s2);
+ ASSERT_EQ("v1", Get(key, s3));
+ db_->ReleaseSnapshot(s3);
+ }
+ } while (ChangeOptions());
+}
+
+TEST(DBTest, IterateOverEmptySnapshot) {
+ do {
+ const Snapshot* snapshot = db_->GetSnapshot();
+ ReadOptions read_options;
+ read_options.snapshot = snapshot;
+ ASSERT_OK(Put("foo", "v1"));
+ ASSERT_OK(Put("foo", "v2"));
+
+ Iterator* iterator1 = db_->NewIterator(read_options);
+ iterator1->SeekToFirst();
+ ASSERT_TRUE(!iterator1->Valid());
+ delete iterator1;
+
+ dbfull()->TEST_CompactMemTable();
+
+ Iterator* iterator2 = db_->NewIterator(read_options);
+ iterator2->SeekToFirst();
+ ASSERT_TRUE(!iterator2->Valid());
+ delete iterator2;
+
+ db_->ReleaseSnapshot(snapshot);
+ } while (ChangeOptions());
+}
+
TEST(DBTest, GetLevel0Ordering) {
do {
// Check that we process level-0 files in correct order. The code
@@ -646,8 +747,7 @@ TEST(DBTest, GetEncountersEmptyLevel) {
// Step 1: First place sstables in levels 0 and 2
int compaction_count = 0;
- while (NumTableFilesAtLevel(0) == 0 ||
- NumTableFilesAtLevel(2) == 0) {
+ while (NumTableFilesAtLevel(0) == 0 || NumTableFilesAtLevel(2) == 0) {
ASSERT_LE(compaction_count, 100) << "could not fill levels 0 and 2";
compaction_count++;
Put("a", "begin");
@@ -656,7 +756,7 @@ TEST(DBTest, GetEncountersEmptyLevel) {
}
// Step 2: clear level 1 if necessary.
- dbfull()->TEST_CompactRange(1, NULL, NULL);
+ dbfull()->TEST_CompactRange(1, nullptr, nullptr);
ASSERT_EQ(NumTableFilesAtLevel(0), 1);
ASSERT_EQ(NumTableFilesAtLevel(1), 0);
ASSERT_EQ(NumTableFilesAtLevel(2), 1);
@@ -784,10 +884,10 @@ TEST(DBTest, IterMulti) {
ASSERT_EQ(IterStatus(iter), "b->vb");
// Make sure iter stays at snapshot
- ASSERT_OK(Put("a", "va2"));
+ ASSERT_OK(Put("a", "va2"));
ASSERT_OK(Put("a2", "va3"));
- ASSERT_OK(Put("b", "vb2"));
- ASSERT_OK(Put("c", "vc2"));
+ ASSERT_OK(Put("b", "vb2"));
+ ASSERT_OK(Put("c", "vc2"));
ASSERT_OK(Delete("b"));
iter->SeekToFirst();
ASSERT_EQ(IterStatus(iter), "a->va");
@@ -978,7 +1078,7 @@ TEST(DBTest, RecoverWithLargeLog) {
TEST(DBTest, CompactionsGenerateMultipleFiles) {
Options options = CurrentOptions();
- options.write_buffer_size = 100000000; // Large write buffer
+ options.write_buffer_size = 100000000; // Large write buffer
Reopen(&options);
Random rnd(301);
@@ -993,7 +1093,7 @@ TEST(DBTest, CompactionsGenerateMultipleFiles) {
// Reopening moves updates to level-0
Reopen(&options);
- dbfull()->TEST_CompactRange(0, NULL, NULL);
+ dbfull()->TEST_CompactRange(0, nullptr, nullptr);
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
ASSERT_GT(NumTableFilesAtLevel(1), 1);
@@ -1017,7 +1117,7 @@ TEST(DBTest, RepeatedWritesToSameKey) {
for (int i = 0; i < 5 * kMaxFiles; i++) {
Put("key", value);
ASSERT_LE(TotalTableFiles(), kMaxFiles);
- fprintf(stderr, "after %d: %d files\n", int(i+1), TotalTableFiles());
+ fprintf(stderr, "after %d: %d files\n", i + 1, TotalTableFiles());
}
}
@@ -1044,29 +1144,28 @@ TEST(DBTest, SparseMerge) {
}
Put("C", "vc");
dbfull()->TEST_CompactMemTable();
- dbfull()->TEST_CompactRange(0, NULL, NULL);
+ dbfull()->TEST_CompactRange(0, nullptr, nullptr);
// Make sparse update
- Put("A", "va2");
+ Put("A", "va2");
Put("B100", "bvalue2");
- Put("C", "vc2");
+ Put("C", "vc2");
dbfull()->TEST_CompactMemTable();
// Compactions should not cause us to create a situation where
// a file overlaps too much data at the next level.
- ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576);
- dbfull()->TEST_CompactRange(0, NULL, NULL);
- ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576);
- dbfull()->TEST_CompactRange(1, NULL, NULL);
- ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576);
+ ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20 * 1048576);
+ dbfull()->TEST_CompactRange(0, nullptr, nullptr);
+ ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20 * 1048576);
+ dbfull()->TEST_CompactRange(1, nullptr, nullptr);
+ ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20 * 1048576);
}
static bool Between(uint64_t val, uint64_t low, uint64_t high) {
bool result = (val >= low) && (val <= high);
if (!result) {
fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n",
- (unsigned long long)(val),
- (unsigned long long)(low),
+ (unsigned long long)(val), (unsigned long long)(low),
(unsigned long long)(high));
}
return result;
@@ -1075,7 +1174,7 @@ static bool Between(uint64_t val, uint64_t low, uint64_t high) {
TEST(DBTest, ApproximateSizes) {
do {
Options options = CurrentOptions();
- options.write_buffer_size = 100000000; // Large write buffer
+ options.write_buffer_size = 100000000; // Large write buffer
options.compression = kNoCompression;
DestroyAndReopen();
@@ -1110,12 +1209,13 @@ TEST(DBTest, ApproximateSizes) {
for (int compact_start = 0; compact_start < N; compact_start += 10) {
for (int i = 0; i < N; i += 10) {
- ASSERT_TRUE(Between(Size("", Key(i)), S1*i, S2*i));
- ASSERT_TRUE(Between(Size("", Key(i)+".suffix"), S1*(i+1), S2*(i+1)));
- ASSERT_TRUE(Between(Size(Key(i), Key(i+10)), S1*10, S2*10));
+ ASSERT_TRUE(Between(Size("", Key(i)), S1 * i, S2 * i));
+ ASSERT_TRUE(Between(Size("", Key(i) + ".suffix"), S1 * (i + 1),
+ S2 * (i + 1)));
+ ASSERT_TRUE(Between(Size(Key(i), Key(i + 10)), S1 * 10, S2 * 10));
}
- ASSERT_TRUE(Between(Size("", Key(50)), S1*50, S2*50));
- ASSERT_TRUE(Between(Size("", Key(50)+".suffix"), S1*50, S2*50));
+ ASSERT_TRUE(Between(Size("", Key(50)), S1 * 50, S2 * 50));
+ ASSERT_TRUE(Between(Size("", Key(50) + ".suffix"), S1 * 50, S2 * 50));
std::string cstart_str = Key(compact_start);
std::string cend_str = Key(compact_start + 9);
@@ -1168,7 +1268,7 @@ TEST(DBTest, ApproximateSizes_MixOfSmallAndLarge) {
ASSERT_TRUE(Between(Size(Key(3), Key(5)), 110000, 111000));
- dbfull()->TEST_CompactRange(0, NULL, NULL);
+ dbfull()->TEST_CompactRange(0, nullptr, nullptr);
}
} while (ChangeOptions());
}
@@ -1182,7 +1282,7 @@ TEST(DBTest, IteratorPinsRef) {
// Write to force compactions
Put("foo", "newvalue1");
for (int i = 0; i < 100; i++) {
- ASSERT_OK(Put(Key(i), Key(i) + std::string(100000, 'v'))); // 100K values
+ ASSERT_OK(Put(Key(i), Key(i) + std::string(100000, 'v'))); // 100K values
}
Put("foo", "newvalue2");
@@ -1234,7 +1334,7 @@ TEST(DBTest, HiddenValuesAreRemoved) {
Put("pastfoo", "v");
const Snapshot* snapshot = db_->GetSnapshot();
Put("foo", "tiny");
- Put("pastfoo2", "v2"); // Advance sequence number one more
+ Put("pastfoo2", "v2"); // Advance sequence number one more
ASSERT_OK(dbfull()->TEST_CompactMemTable());
ASSERT_GT(NumTableFilesAtLevel(0), 0);
@@ -1244,11 +1344,11 @@ TEST(DBTest, HiddenValuesAreRemoved) {
db_->ReleaseSnapshot(snapshot);
ASSERT_EQ(AllEntriesFor("foo"), "[ tiny, " + big + " ]");
Slice x("x");
- dbfull()->TEST_CompactRange(0, NULL, &x);
+ dbfull()->TEST_CompactRange(0, nullptr, &x);
ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]");
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
ASSERT_GE(NumTableFilesAtLevel(1), 1);
- dbfull()->TEST_CompactRange(1, NULL, &x);
+ dbfull()->TEST_CompactRange(1, nullptr, &x);
ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]");
ASSERT_TRUE(Between(Size("", "pastfoo"), 0, 1000));
@@ -1259,14 +1359,14 @@ TEST(DBTest, DeletionMarkers1) {
Put("foo", "v1");
ASSERT_OK(dbfull()->TEST_CompactMemTable());
const int last = config::kMaxMemCompactLevel;
- ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level
+ ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level
// Place a table at level last-1 to prevent merging with preceding mutation
Put("a", "begin");
Put("z", "end");
dbfull()->TEST_CompactMemTable();
ASSERT_EQ(NumTableFilesAtLevel(last), 1);
- ASSERT_EQ(NumTableFilesAtLevel(last-1), 1);
+ ASSERT_EQ(NumTableFilesAtLevel(last - 1), 1);
Delete("foo");
Put("foo", "v2");
@@ -1274,11 +1374,11 @@ TEST(DBTest, DeletionMarkers1) {
ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2
ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]");
Slice z("z");
- dbfull()->TEST_CompactRange(last-2, NULL, &z);
+ dbfull()->TEST_CompactRange(last - 2, nullptr, &z);
// DEL eliminated, but v1 remains because we aren't compacting that level
// (DEL can be eliminated because v2 hides v1).
ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]");
- dbfull()->TEST_CompactRange(last-1, NULL, NULL);
+ dbfull()->TEST_CompactRange(last - 1, nullptr, nullptr);
// Merging last-1 w/ last, so we are the base level for "foo", so
// DEL is removed. (as is v1).
ASSERT_EQ(AllEntriesFor("foo"), "[ v2 ]");
@@ -1288,23 +1388,23 @@ TEST(DBTest, DeletionMarkers2) {
Put("foo", "v1");
ASSERT_OK(dbfull()->TEST_CompactMemTable());
const int last = config::kMaxMemCompactLevel;
- ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level
+ ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level
// Place a table at level last-1 to prevent merging with preceding mutation
Put("a", "begin");
Put("z", "end");
dbfull()->TEST_CompactMemTable();
ASSERT_EQ(NumTableFilesAtLevel(last), 1);
- ASSERT_EQ(NumTableFilesAtLevel(last-1), 1);
+ ASSERT_EQ(NumTableFilesAtLevel(last - 1), 1);
Delete("foo");
ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2
ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
- dbfull()->TEST_CompactRange(last-2, NULL, NULL);
+ dbfull()->TEST_CompactRange(last - 2, nullptr, nullptr);
// DEL kept: "last" file overlaps
ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
- dbfull()->TEST_CompactRange(last-1, NULL, NULL);
+ dbfull()->TEST_CompactRange(last - 1, nullptr, nullptr);
// Merging last-1 w/ last, so we are the base level for "foo", so
// DEL is removed. (as is v1).
ASSERT_EQ(AllEntriesFor("foo"), "[ ]");
@@ -1314,7 +1414,8 @@ TEST(DBTest, OverlapInLevel0) {
do {
ASSERT_EQ(config::kMaxMemCompactLevel, 2) << "Fix test to match config";
- // Fill levels 1 and 2 to disable the pushing of new memtables to levels > 0.
+ // Fill levels 1 and 2 to disable the pushing of new memtables to levels >
+ // 0.
ASSERT_OK(Put("100", "v100"));
ASSERT_OK(Put("999", "v999"));
dbfull()->TEST_CompactMemTable();
@@ -1337,8 +1438,8 @@ TEST(DBTest, OverlapInLevel0) {
ASSERT_EQ("2,1,1", FilesPerLevel());
// Compact away the placeholder files we created initially
- dbfull()->TEST_CompactRange(1, NULL, NULL);
- dbfull()->TEST_CompactRange(2, NULL, NULL);
+ dbfull()->TEST_CompactRange(1, nullptr, nullptr);
+ dbfull()->TEST_CompactRange(2, nullptr, nullptr);
ASSERT_EQ("2", FilesPerLevel());
// Do a memtable compaction. Before bug-fix, the compaction would
@@ -1370,21 +1471,21 @@ TEST(DBTest, L0_CompactionBug_Issue44_a) {
TEST(DBTest, L0_CompactionBug_Issue44_b) {
Reopen();
- Put("","");
+ Put("", "");
Reopen();
Delete("e");
- Put("","");
+ Put("", "");
Reopen();
Put("c", "cv");
Reopen();
- Put("","");
+ Put("", "");
Reopen();
- Put("","");
+ Put("", "");
DelayMilliseconds(1000); // Wait for compaction to finish
Reopen();
- Put("d","dv");
+ Put("d", "dv");
Reopen();
- Put("","");
+ Put("", "");
Reopen();
Delete("d");
Delete("b");
@@ -1394,17 +1495,26 @@ TEST(DBTest, L0_CompactionBug_Issue44_b) {
ASSERT_EQ("(->)(c->cv)", Contents());
}
+TEST(DBTest, Fflush_Issue474) {
+ static const int kNum = 100000;
+ Random rnd(test::RandomSeed());
+ for (int i = 0; i < kNum; i++) {
+ fflush(nullptr);
+ ASSERT_OK(Put(RandomKey(&rnd), RandomString(&rnd, 100)));
+ }
+}
+
TEST(DBTest, ComparatorCheck) {
class NewComparator : public Comparator {
public:
- virtual const char* Name() const { return "leveldb.NewComparator"; }
- virtual int Compare(const Slice& a, const Slice& b) const {
+ const char* Name() const override { return "leveldb.NewComparator"; }
+ int Compare(const Slice& a, const Slice& b) const override {
return BytewiseComparator()->Compare(a, b);
}
- virtual void FindShortestSeparator(std::string* s, const Slice& l) const {
+ void FindShortestSeparator(std::string* s, const Slice& l) const override {
BytewiseComparator()->FindShortestSeparator(s, l);
}
- virtual void FindShortSuccessor(std::string* key) const {
+ void FindShortSuccessor(std::string* key) const override {
BytewiseComparator()->FindShortSuccessor(key);
}
};
@@ -1420,21 +1530,22 @@ TEST(DBTest, ComparatorCheck) {
TEST(DBTest, CustomComparator) {
class NumberComparator : public Comparator {
public:
- virtual const char* Name() const { return "test.NumberComparator"; }
- virtual int Compare(const Slice& a, const Slice& b) const {
+ const char* Name() const override { return "test.NumberComparator"; }
+ int Compare(const Slice& a, const Slice& b) const override {
return ToNumber(a) - ToNumber(b);
}
- virtual void FindShortestSeparator(std::string* s, const Slice& l) const {
- ToNumber(*s); // Check format
- ToNumber(l); // Check format
+ void FindShortestSeparator(std::string* s, const Slice& l) const override {
+ ToNumber(*s); // Check format
+ ToNumber(l); // Check format
}
- virtual void FindShortSuccessor(std::string* key) const {
- ToNumber(*key); // Check format
+ void FindShortSuccessor(std::string* key) const override {
+ ToNumber(*key); // Check format
}
+
private:
static int ToNumber(const Slice& x) {
// Check that there are no extra characters.
- ASSERT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size()-1] == ']')
+ ASSERT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size() - 1] == ']')
<< EscapeString(x);
int val;
char ignored;
@@ -1447,7 +1558,7 @@ TEST(DBTest, CustomComparator) {
Options new_options = CurrentOptions();
new_options.create_if_missing = true;
new_options.comparator = &cmp;
- new_options.filter_policy = NULL; // Cannot use bloom filters
+ new_options.filter_policy = nullptr; // Cannot use bloom filters
new_options.write_buffer_size = 1000; // Compact more often
DestroyAndReopen(&new_options);
ASSERT_OK(Put("[10]", "ten"));
@@ -1465,7 +1576,7 @@ TEST(DBTest, CustomComparator) {
for (int run = 0; run < 2; run++) {
for (int i = 0; i < 1000; i++) {
char buf[100];
- snprintf(buf, sizeof(buf), "[%d]", i*10);
+ snprintf(buf, sizeof(buf), "[%d]", i * 10);
ASSERT_OK(Put(buf, buf));
}
Compact("[0]", "[1000000]");
@@ -1502,7 +1613,7 @@ TEST(DBTest, ManualCompaction) {
// Compact all
MakeTables(1, "a", "z");
ASSERT_EQ("0,1,2", FilesPerLevel());
- db_->CompactRange(NULL, NULL);
+ db_->CompactRange(nullptr, nullptr);
ASSERT_EQ("0,0,1", FilesPerLevel());
}
@@ -1511,42 +1622,94 @@ TEST(DBTest, DBOpen_Options) {
DestroyDB(dbname, Options());
// Does not exist, and create_if_missing == false: error
- DB* db = NULL;
+ DB* db = nullptr;
Options opts;
opts.create_if_missing = false;
Status s = DB::Open(opts, dbname, &db);
- ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != NULL);
- ASSERT_TRUE(db == NULL);
+ ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != nullptr);
+ ASSERT_TRUE(db == nullptr);
// Does not exist, and create_if_missing == true: OK
opts.create_if_missing = true;
s = DB::Open(opts, dbname, &db);
ASSERT_OK(s);
- ASSERT_TRUE(db != NULL);
+ ASSERT_TRUE(db != nullptr);
delete db;
- db = NULL;
+ db = nullptr;
// Does exist, and error_if_exists == true: error
opts.create_if_missing = false;
opts.error_if_exists = true;
s = DB::Open(opts, dbname, &db);
- ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != NULL);
- ASSERT_TRUE(db == NULL);
+ ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != nullptr);
+ ASSERT_TRUE(db == nullptr);
// Does exist, and error_if_exists == false: OK
opts.create_if_missing = true;
opts.error_if_exists = false;
s = DB::Open(opts, dbname, &db);
ASSERT_OK(s);
- ASSERT_TRUE(db != NULL);
+ ASSERT_TRUE(db != nullptr);
+
+ delete db;
+ db = nullptr;
+}
+
+TEST(DBTest, DestroyEmptyDir) {
+ std::string dbname = test::TmpDir() + "/db_empty_dir";
+ TestEnv env(Env::Default());
+ env.DeleteDir(dbname);
+ ASSERT_TRUE(!env.FileExists(dbname));
+
+ Options opts;
+ opts.env = &env;
+
+ ASSERT_OK(env.CreateDir(dbname));
+ ASSERT_TRUE(env.FileExists(dbname));
+ std::vector<std::string> children;
+ ASSERT_OK(env.GetChildren(dbname, &children));
+ // The stock Env's do not filter out '.' and '..' special files.
+ ASSERT_EQ(2, children.size());
+ ASSERT_OK(DestroyDB(dbname, opts));
+ ASSERT_TRUE(!env.FileExists(dbname));
+
+ // Should also be destroyed if Env is filtering out dot files.
+ env.SetIgnoreDotFiles(true);
+ ASSERT_OK(env.CreateDir(dbname));
+ ASSERT_TRUE(env.FileExists(dbname));
+ ASSERT_OK(env.GetChildren(dbname, &children));
+ ASSERT_EQ(0, children.size());
+ ASSERT_OK(DestroyDB(dbname, opts));
+ ASSERT_TRUE(!env.FileExists(dbname));
+}
+
+TEST(DBTest, DestroyOpenDB) {
+ std::string dbname = test::TmpDir() + "/open_db_dir";
+ env_->DeleteDir(dbname);
+ ASSERT_TRUE(!env_->FileExists(dbname));
+
+ Options opts;
+ opts.create_if_missing = true;
+ DB* db = nullptr;
+ ASSERT_OK(DB::Open(opts, dbname, &db));
+ ASSERT_TRUE(db != nullptr);
+
+ // Must fail to destroy an open db.
+ ASSERT_TRUE(env_->FileExists(dbname));
+ ASSERT_TRUE(!DestroyDB(dbname, Options()).ok());
+ ASSERT_TRUE(env_->FileExists(dbname));
delete db;
- db = NULL;
+ db = nullptr;
+
+ // Should succeed destroying a closed db.
+ ASSERT_OK(DestroyDB(dbname, Options()));
+ ASSERT_TRUE(!env_->FileExists(dbname));
}
TEST(DBTest, Locking) {
- DB* db2 = NULL;
+ DB* db2 = nullptr;
Status s = DB::Open(CurrentOptions(), dbname_, &db2);
ASSERT_TRUE(!s.ok()) << "Locking did not prevent re-opening db";
}
@@ -1561,13 +1724,14 @@ TEST(DBTest, NoSpace) {
ASSERT_EQ("v1", Get("foo"));
Compact("a", "z");
const int num_files = CountFiles();
- env_->no_space_.Release_Store(env_); // Force out-of-space errors
+ // Force out-of-space errors.
+ env_->no_space_.store(true, std::memory_order_release);
for (int i = 0; i < 10; i++) {
- for (int level = 0; level < config::kNumLevels-1; level++) {
- dbfull()->TEST_CompactRange(level, NULL, NULL);
+ for (int level = 0; level < config::kNumLevels - 1; level++) {
+ dbfull()->TEST_CompactRange(level, nullptr, nullptr);
}
}
- env_->no_space_.Release_Store(NULL);
+ env_->no_space_.store(false, std::memory_order_release);
ASSERT_LT(CountFiles(), num_files + 3);
}
@@ -1577,7 +1741,8 @@ TEST(DBTest, NonWritableFileSystem) {
options.env = env_;
Reopen(&options);
ASSERT_OK(Put("foo", "v1"));
- env_->non_writable_.Release_Store(env_); // Force errors for new files
+ // Force errors for new files.
+ env_->non_writable_.store(true, std::memory_order_release);
std::string big(100000, 'x');
int errors = 0;
for (int i = 0; i < 20; i++) {
@@ -1588,7 +1753,7 @@ TEST(DBTest, NonWritableFileSystem) {
}
}
ASSERT_GT(errors, 0);
- env_->non_writable_.Release_Store(NULL);
+ env_->non_writable_.store(false, std::memory_order_release);
}
TEST(DBTest, WriteSyncError) {
@@ -1598,7 +1763,7 @@ TEST(DBTest, WriteSyncError) {
Options options = CurrentOptions();
options.env = env_;
Reopen(&options);
- env_->data_sync_error_.Release_Store(env_);
+ env_->data_sync_error_.store(true, std::memory_order_release);
// (b) Normal write should succeed
WriteOptions w;
@@ -1612,7 +1777,7 @@ TEST(DBTest, WriteSyncError) {
ASSERT_EQ("NOT_FOUND", Get("k2"));
// (d) make sync behave normally
- env_->data_sync_error_.Release_Store(NULL);
+ env_->data_sync_error_.store(false, std::memory_order_release);
// (e) Do a non-sync write; should fail
w.sync = false;
@@ -1632,9 +1797,8 @@ TEST(DBTest, ManifestWriteError) {
// We iterate twice. In the second iteration, everything is the
// same except the log record never makes it to the MANIFEST file.
for (int iter = 0; iter < 2; iter++) {
- port::AtomicPointer* error_type = (iter == 0)
- ? &env_->manifest_sync_error_
- : &env_->manifest_write_error_;
+ std::atomic<bool>* error_type = (iter == 0) ? &env_->manifest_sync_error_
+ : &env_->manifest_write_error_;
// Insert foo=>bar mapping
Options options = CurrentOptions();
@@ -1649,15 +1813,15 @@ TEST(DBTest, ManifestWriteError) {
dbfull()->TEST_CompactMemTable();
ASSERT_EQ("bar", Get("foo"));
const int last = config::kMaxMemCompactLevel;
- ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo=>bar is now in last level
+ ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo=>bar is now in last level
// Merging compaction (will fail)
- error_type->Release_Store(env_);
- dbfull()->TEST_CompactRange(last, NULL, NULL); // Should fail
+ error_type->store(true, std::memory_order_release);
+ dbfull()->TEST_CompactRange(last, nullptr, nullptr); // Should fail
ASSERT_EQ("bar", Get("foo"));
// Recovery: should not lose data
- error_type->Release_Store(NULL);
+ error_type->store(false, std::memory_order_release);
Reopen(&options);
ASSERT_EQ("bar", Get("foo"));
}
@@ -1677,8 +1841,7 @@ TEST(DBTest, MissingSSTFile) {
options.paranoid_checks = true;
Status s = TryReopen(&options);
ASSERT_TRUE(!s.ok());
- ASSERT_TRUE(s.ToString().find("issing") != std::string::npos)
- << s.ToString();
+ ASSERT_TRUE(s.ToString().find("issing") != std::string::npos) << s.ToString();
}
TEST(DBTest, StillReadSST) {
@@ -1728,7 +1891,7 @@ TEST(DBTest, BloomFilter) {
dbfull()->TEST_CompactMemTable();
// Prevent auto compactions triggered by seeks
- env_->delay_data_sync_.Release_Store(env_);
+ env_->delay_data_sync_.store(true, std::memory_order_release);
// Lookup present keys. Should rarely read from small sstable.
env_->random_read_counter_.Reset();
@@ -1738,7 +1901,7 @@ TEST(DBTest, BloomFilter) {
int reads = env_->random_read_counter_.Read();
fprintf(stderr, "%d present => %d reads\n", N, reads);
ASSERT_GE(reads, N);
- ASSERT_LE(reads, N + 2*N/100);
+ ASSERT_LE(reads, N + 2 * N / 100);
// Lookup present keys. Should rarely read from either sstable.
env_->random_read_counter_.Reset();
@@ -1747,9 +1910,9 @@ TEST(DBTest, BloomFilter) {
}
reads = env_->random_read_counter_.Read();
fprintf(stderr, "%d missing => %d reads\n", N, reads);
- ASSERT_LE(reads, 3*N/100);
+ ASSERT_LE(reads, 3 * N / 100);
- env_->delay_data_sync_.Release_Store(NULL);
+ env_->delay_data_sync_.store(false, std::memory_order_release);
Close();
delete options.block_cache;
delete options.filter_policy;
@@ -1764,9 +1927,9 @@ static const int kNumKeys = 1000;
struct MTState {
DBTest* test;
- port::AtomicPointer stop;
- port::AtomicPointer counter[kNumThreads];
- port::AtomicPointer thread_done[kNumThreads];
+ std::atomic<bool> stop;
+ std::atomic<int> counter[kNumThreads];
+ std::atomic<bool> thread_done[kNumThreads];
};
struct MTThread {
@@ -1778,13 +1941,13 @@ static void MTThreadBody(void* arg) {
MTThread* t = reinterpret_cast<MTThread*>(arg);
int id = t->id;
DB* db = t->state->test->db_;
- uintptr_t counter = 0;
+ int counter = 0;
fprintf(stderr, "... starting thread %d\n", id);
Random rnd(1000 + id);
std::string value;
char valbuf[1500];
- while (t->state->stop.Acquire_Load() == NULL) {
- t->state->counter[id].Release_Store(reinterpret_cast<void*>(counter));
+ while (!t->state->stop.load(std::memory_order_acquire)) {
+ t->state->counter[id].store(counter, std::memory_order_release);
int key = rnd.Uniform(kNumKeys);
char keybuf[20];
@@ -1793,8 +1956,8 @@ static void MTThreadBody(void* arg) {
if (rnd.OneIn(2)) {
// Write values of the form <key, my id, counter>.
// We add some padding for force compactions.
- snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d",
- key, id, static_cast<int>(counter));
+ snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d", key, id,
+ static_cast<int>(counter));
ASSERT_OK(db->Put(WriteOptions(), Slice(keybuf), Slice(valbuf)));
} else {
// Read a value and verify that it matches the pattern written above.
@@ -1809,14 +1972,13 @@ static void MTThreadBody(void* arg) {
ASSERT_EQ(k, key);
ASSERT_GE(w, 0);
ASSERT_LT(w, kNumThreads);
- ASSERT_LE(static_cast<uintptr_t>(c), reinterpret_cast<uintptr_t>(
- t->state->counter[w].Acquire_Load()));
+ ASSERT_LE(c, t->state->counter[w].load(std::memory_order_acquire));
}
}
counter++;
}
- t->state->thread_done[id].Release_Store(t);
- fprintf(stderr, "... stopping thread %d after %d ops\n", id, int(counter));
+ t->state->thread_done[id].store(true, std::memory_order_release);
+ fprintf(stderr, "... stopping thread %d after %d ops\n", id, counter);
}
} // namespace
@@ -1826,10 +1988,10 @@ TEST(DBTest, MultiThreaded) {
// Initialize state
MTState mt;
mt.test = this;
- mt.stop.Release_Store(0);
+ mt.stop.store(false, std::memory_order_release);
for (int id = 0; id < kNumThreads; id++) {
- mt.counter[id].Release_Store(0);
- mt.thread_done[id].Release_Store(0);
+ mt.counter[id].store(false, std::memory_order_release);
+ mt.thread_done[id].store(false, std::memory_order_release);
}
// Start threads
@@ -1844,9 +2006,9 @@ TEST(DBTest, MultiThreaded) {
DelayMilliseconds(kTestSeconds * 1000);
// Stop the threads and wait for them to finish
- mt.stop.Release_Store(&mt);
+ mt.stop.store(true, std::memory_order_release);
for (int id = 0; id < kNumThreads; id++) {
- while (mt.thread_done[id].Acquire_Load() == NULL) {
+ while (!mt.thread_done[id].load(std::memory_order_acquire)) {
DelayMilliseconds(100);
}
}
@@ -1857,28 +2019,28 @@ namespace {
typedef std::map<std::string, std::string> KVMap;
}
-class ModelDB: public DB {
+class ModelDB : public DB {
public:
class ModelSnapshot : public Snapshot {
public:
KVMap map_;
};
- explicit ModelDB(const Options& options): options_(options) { }
- ~ModelDB() { }
- virtual Status Put(const WriteOptions& o, const Slice& k, const Slice& v) {
+ explicit ModelDB(const Options& options) : options_(options) {}
+ ~ModelDB() override = default;
+ Status Put(const WriteOptions& o, const Slice& k, const Slice& v) override {
return DB::Put(o, k, v);
}
- virtual Status Delete(const WriteOptions& o, const Slice& key) {
+ Status Delete(const WriteOptions& o, const Slice& key) override {
return DB::Delete(o, key);
}
- virtual Status Get(const ReadOptions& options,
- const Slice& key, std::string* value) {
- assert(false); // Not implemented
+ Status Get(const ReadOptions& options, const Slice& key,
+ std::string* value) override {
+ assert(false); // Not implemented
return Status::NotFound(key);
}
- virtual Iterator* NewIterator(const ReadOptions& options) {
- if (options.snapshot == NULL) {
+ Iterator* NewIterator(const ReadOptions& options) override {
+ if (options.snapshot == nullptr) {
KVMap* saved = new KVMap;
*saved = map_;
return new ModelIter(saved, true);
@@ -1888,68 +2050,65 @@ class ModelDB: public DB {
return new ModelIter(snapshot_state, false);
}
}
- virtual const Snapshot* GetSnapshot() {
+ const Snapshot* GetSnapshot() override {
ModelSnapshot* snapshot = new ModelSnapshot;
snapshot->map_ = map_;
return snapshot;
}
- virtual void ReleaseSnapshot(const Snapshot* snapshot) {
+ void ReleaseSnapshot(const Snapshot* snapshot) override {
delete reinterpret_cast<const ModelSnapshot*>(snapshot);
}
- virtual Status Write(const WriteOptions& options, WriteBatch* batch) {
+ Status Write(const WriteOptions& options, WriteBatch* batch) override {
class Handler : public WriteBatch::Handler {
public:
KVMap* map_;
- virtual void Put(const Slice& key, const Slice& value) {
+ void Put(const Slice& key, const Slice& value) override {
(*map_)[key.ToString()] = value.ToString();
}
- virtual void Delete(const Slice& key) {
- map_->erase(key.ToString());
- }
+ void Delete(const Slice& key) override { map_->erase(key.ToString()); }
};
Handler handler;
handler.map_ = &map_;
return batch->Iterate(&handler);
}
- virtual bool GetProperty(const Slice& property, std::string* value) {
+ bool GetProperty(const Slice& property, std::string* value) override {
return false;
}
- virtual void GetApproximateSizes(const Range* r, int n, uint64_t* sizes) {
+ void GetApproximateSizes(const Range* r, int n, uint64_t* sizes) override {
for (int i = 0; i < n; i++) {
sizes[i] = 0;
}
}
- virtual void CompactRange(const Slice* start, const Slice* end) {
- }
+ void CompactRange(const Slice* start, const Slice* end) override {}
private:
- class ModelIter: public Iterator {
+ class ModelIter : public Iterator {
public:
ModelIter(const KVMap* map, bool owned)
- : map_(map), owned_(owned), iter_(map_->end()) {
- }
- ~ModelIter() {
+ : map_(map), owned_(owned), iter_(map_->end()) {}
+ ~ModelIter() override {
if (owned_) delete map_;
}
- virtual bool Valid() const { return iter_ != map_->end(); }
- virtual void SeekToFirst() { iter_ = map_->begin(); }
- virtual void SeekToLast() {
+ bool Valid() const override { return iter_ != map_->end(); }
+ void SeekToFirst() override { iter_ = map_->begin(); }
+ void SeekToLast() override {
if (map_->empty()) {
iter_ = map_->end();
} else {
iter_ = map_->find(map_->rbegin()->first);
}
}
- virtual void Seek(const Slice& k) {
+ void Seek(const Slice& k) override {
iter_ = map_->lower_bound(k.ToString());
}
- virtual void Next() { ++iter_; }
- virtual void Prev() { --iter_; }
- virtual Slice key() const { return iter_->first; }
- virtual Slice value() const { return iter_->second; }
- virtual Status status() const { return Status::OK(); }
+ void Next() override { ++iter_; }
+ void Prev() override { --iter_; }
+ Slice key() const override { return iter_->first; }
+ Slice value() const override { return iter_->second; }
+ Status status() const override { return Status::OK(); }
+
private:
const KVMap* const map_;
const bool owned_; // Do we own map_
@@ -1959,16 +2118,7 @@ class ModelDB: public DB {
KVMap map_;
};
-static std::string RandomKey(Random* rnd) {
- int len = (rnd->OneIn(3)
- ? 1 // Short sometimes to encourage collisions
- : (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10)));
- return test::RandomKey(rnd, len);
-}
-
-static bool CompareIterators(int step,
- DB* model,
- DB* db,
+static bool CompareIterators(int step, DB* model, DB* db,
const Snapshot* model_snap,
const Snapshot* db_snap) {
ReadOptions options;
@@ -1979,12 +2129,10 @@ static bool CompareIterators(int step,
bool ok = true;
int count = 0;
for (miter->SeekToFirst(), dbiter->SeekToFirst();
- ok && miter->Valid() && dbiter->Valid();
- miter->Next(), dbiter->Next()) {
+ ok && miter->Valid() && dbiter->Valid(); miter->Next(), dbiter->Next()) {
count++;
if (miter->key().compare(dbiter->key()) != 0) {
- fprintf(stderr, "step %d: Key mismatch: '%s' vs. '%s'\n",
- step,
+ fprintf(stderr, "step %d: Key mismatch: '%s' vs. '%s'\n", step,
EscapeString(miter->key()).c_str(),
EscapeString(dbiter->key()).c_str());
ok = false;
@@ -1993,8 +2141,7 @@ static bool CompareIterators(int step,
if (miter->value().compare(dbiter->value()) != 0) {
fprintf(stderr, "step %d: Value mismatch for key '%s': '%s' vs. '%s'\n",
- step,
- EscapeString(miter->key()).c_str(),
+ step, EscapeString(miter->key()).c_str(),
EscapeString(miter->value()).c_str(),
EscapeString(miter->value()).c_str());
ok = false;
@@ -2019,8 +2166,8 @@ TEST(DBTest, Randomized) {
do {
ModelDB model(CurrentOptions());
const int N = 10000;
- const Snapshot* model_snap = NULL;
- const Snapshot* db_snap = NULL;
+ const Snapshot* model_snap = nullptr;
+ const Snapshot* db_snap = nullptr;
std::string k, v;
for (int step = 0; step < N; step++) {
if (step % 100 == 0) {
@@ -2028,22 +2175,19 @@ TEST(DBTest, Randomized) {
}
// TODO(sanjay): Test Get() works
int p = rnd.Uniform(100);
- if (p < 45) { // Put
+ if (p < 45) { // Put
k = RandomKey(&rnd);
- v = RandomString(&rnd,
- rnd.OneIn(20)
- ? 100 + rnd.Uniform(100)
- : rnd.Uniform(8));
+ v = RandomString(
+ &rnd, rnd.OneIn(20) ? 100 + rnd.Uniform(100) : rnd.Uniform(8));
ASSERT_OK(model.Put(WriteOptions(), k, v));
ASSERT_OK(db_->Put(WriteOptions(), k, v));
- } else if (p < 90) { // Delete
+ } else if (p < 90) { // Delete
k = RandomKey(&rnd);
ASSERT_OK(model.Delete(WriteOptions(), k));
ASSERT_OK(db_->Delete(WriteOptions(), k));
-
- } else { // Multi-element batch
+ } else { // Multi-element batch
WriteBatch b;
const int num = rnd.Uniform(8);
for (int i = 0; i < num; i++) {
@@ -2065,23 +2209,23 @@ TEST(DBTest, Randomized) {
}
if ((step % 100) == 0) {
- ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL));
+ ASSERT_TRUE(CompareIterators(step, &model, db_, nullptr, nullptr));
ASSERT_TRUE(CompareIterators(step, &model, db_, model_snap, db_snap));
// Save a snapshot from each DB this time that we'll use next
// time we compare things, to make sure the current state is
// preserved with the snapshot
- if (model_snap != NULL) model.ReleaseSnapshot(model_snap);
- if (db_snap != NULL) db_->ReleaseSnapshot(db_snap);
+ if (model_snap != nullptr) model.ReleaseSnapshot(model_snap);
+ if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap);
Reopen();
- ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL));
+ ASSERT_TRUE(CompareIterators(step, &model, db_, nullptr, nullptr));
model_snap = model.GetSnapshot();
db_snap = db_->GetSnapshot();
}
}
- if (model_snap != NULL) model.ReleaseSnapshot(model_snap);
- if (db_snap != NULL) db_->ReleaseSnapshot(db_snap);
+ if (model_snap != nullptr) model.ReleaseSnapshot(model_snap);
+ if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap);
} while (ChangeOptions());
}
@@ -2095,15 +2239,15 @@ void BM_LogAndApply(int iters, int num_base_files) {
std::string dbname = test::TmpDir() + "/leveldb_test_benchmark";
DestroyDB(dbname, Options());
- DB* db = NULL;
+ DB* db = nullptr;
Options opts;
opts.create_if_missing = true;
Status s = DB::Open(opts, dbname, &db);
ASSERT_OK(s);
- ASSERT_TRUE(db != NULL);
+ ASSERT_TRUE(db != nullptr);
delete db;
- db = NULL;
+ db = nullptr;
Env* env = Env::Default();
@@ -2112,14 +2256,14 @@ void BM_LogAndApply(int iters, int num_base_files) {
InternalKeyComparator cmp(BytewiseComparator());
Options options;
- VersionSet vset(dbname, &options, NULL, &cmp);
+ VersionSet vset(dbname, &options, nullptr, &cmp);
bool save_manifest;
ASSERT_OK(vset.Recover(&save_manifest));
VersionEdit vbase;
uint64_t fnum = 1;
for (int i = 0; i < num_base_files; i++) {
- InternalKey start(MakeKey(2*fnum), 1, kTypeValue);
- InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion);
+ InternalKey start(MakeKey(2 * fnum), 1, kTypeValue);
+ InternalKey limit(MakeKey(2 * fnum + 1), 1, kTypeDeletion);
vbase.AddFile(2, fnum++, 1 /* file size */, start, limit);
}
ASSERT_OK(vset.LogAndApply(&vbase, &mu));
@@ -2129,8 +2273,8 @@ void BM_LogAndApply(int iters, int num_base_files) {
for (int i = 0; i < iters; i++) {
VersionEdit vedit;
vedit.DeleteFile(2, fnum);
- InternalKey start(MakeKey(2*fnum), 1, kTypeValue);
- InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion);
+ InternalKey start(MakeKey(2 * fnum), 1, kTypeValue);
+ InternalKey limit(MakeKey(2 * fnum + 1), 1, kTypeDeletion);
vedit.AddFile(2, fnum++, 1 /* file size */, start, limit);
vset.LogAndApply(&vedit, &mu);
}
@@ -2139,8 +2283,8 @@ void BM_LogAndApply(int iters, int num_base_files) {
char buf[16];
snprintf(buf, sizeof(buf), "%d", num_base_files);
fprintf(stderr,
- "BM_LogAndApply/%-6s %8d iters : %9u us (%7.0f us / iter)\n",
- buf, iters, us, ((float)us) / iters);
+ "BM_LogAndApply/%-6s %8d iters : %9u us (%7.0f us / iter)\n", buf,
+ iters, us, ((float)us) / iters);
}
} // namespace leveldb
diff --git a/src/leveldb/db/dbformat.cc b/src/leveldb/db/dbformat.cc
index 20a7ca4462..459eddf5b1 100644
--- a/src/leveldb/db/dbformat.cc
+++ b/src/leveldb/db/dbformat.cc
@@ -2,8 +2,12 @@
// 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.
-#include <stdio.h>
#include "db/dbformat.h"
+
+#include <stdio.h>
+
+#include <sstream>
+
#include "port/port.h"
#include "util/coding.h"
@@ -21,26 +25,20 @@ void AppendInternalKey(std::string* result, const ParsedInternalKey& key) {
}
std::string ParsedInternalKey::DebugString() const {
- char buf[50];
- snprintf(buf, sizeof(buf), "' @ %llu : %d",
- (unsigned long long) sequence,
- int(type));
- std::string result = "'";
- result += EscapeString(user_key.ToString());
- result += buf;
- return result;
+ std::ostringstream ss;
+ ss << '\'' << EscapeString(user_key.ToString()) << "' @ " << sequence << " : "
+ << static_cast<int>(type);
+ return ss.str();
}
std::string InternalKey::DebugString() const {
- std::string result;
ParsedInternalKey parsed;
if (ParseInternalKey(rep_, &parsed)) {
- result = parsed.DebugString();
- } else {
- result = "(bad)";
- result.append(EscapeString(rep_));
+ return parsed.DebugString();
}
- return result;
+ std::ostringstream ss;
+ ss << "(bad)" << EscapeString(rep_);
+ return ss.str();
}
const char* InternalKeyComparator::Name() const {
@@ -65,9 +63,8 @@ int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const {
return r;
}
-void InternalKeyComparator::FindShortestSeparator(
- std::string* start,
- const Slice& limit) const {
+void InternalKeyComparator::FindShortestSeparator(std::string* start,
+ const Slice& limit) const {
// Attempt to shorten the user portion of the key
Slice user_start = ExtractUserKey(*start);
Slice user_limit = ExtractUserKey(limit);
@@ -77,7 +74,8 @@ void InternalKeyComparator::FindShortestSeparator(
user_comparator_->Compare(user_start, tmp) < 0) {
// User key has become shorter physically, but larger logically.
// Tack on the earliest possible number to the shortened user key.
- PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek));
+ PutFixed64(&tmp,
+ PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek));
assert(this->Compare(*start, tmp) < 0);
assert(this->Compare(tmp, limit) < 0);
start->swap(tmp);
@@ -92,15 +90,14 @@ void InternalKeyComparator::FindShortSuccessor(std::string* key) const {
user_comparator_->Compare(user_key, tmp) < 0) {
// User key has become shorter physically, but larger logically.
// Tack on the earliest possible number to the shortened user key.
- PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek));
+ PutFixed64(&tmp,
+ PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek));
assert(this->Compare(*key, tmp) < 0);
key->swap(tmp);
}
}
-const char* InternalFilterPolicy::Name() const {
- return user_policy_->Name();
-}
+const char* InternalFilterPolicy::Name() const { return user_policy_->Name(); }
void InternalFilterPolicy::CreateFilter(const Slice* keys, int n,
std::string* dst) const {
diff --git a/src/leveldb/db/dbformat.h b/src/leveldb/db/dbformat.h
index ea897b13c0..a1c30ed88c 100644
--- a/src/leveldb/db/dbformat.h
+++ b/src/leveldb/db/dbformat.h
@@ -5,7 +5,10 @@
#ifndef STORAGE_LEVELDB_DB_DBFORMAT_H_
#define STORAGE_LEVELDB_DB_DBFORMAT_H_
-#include <stdio.h>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+
#include "leveldb/comparator.h"
#include "leveldb/db.h"
#include "leveldb/filter_policy.h"
@@ -48,10 +51,7 @@ class InternalKey;
// Value types encoded as the last component of internal keys.
// DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk
// data structures.
-enum ValueType {
- kTypeDeletion = 0x0,
- kTypeValue = 0x1
-};
+enum ValueType { kTypeDeletion = 0x0, kTypeValue = 0x1 };
// kValueTypeForSeek defines the ValueType that should be passed when
// constructing a ParsedInternalKey object for seeking to a particular
// sequence number (since we sort sequence numbers in decreasing order
@@ -64,17 +64,16 @@ typedef uint64_t SequenceNumber;
// We leave eight bits empty at the bottom so a type and sequence#
// can be packed together into 64-bits.
-static const SequenceNumber kMaxSequenceNumber =
- ((0x1ull << 56) - 1);
+static const SequenceNumber kMaxSequenceNumber = ((0x1ull << 56) - 1);
struct ParsedInternalKey {
Slice user_key;
SequenceNumber sequence;
ValueType type;
- ParsedInternalKey() { } // Intentionally left uninitialized (for speed)
+ ParsedInternalKey() {} // Intentionally left uninitialized (for speed)
ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t)
- : user_key(u), sequence(seq), type(t) { }
+ : user_key(u), sequence(seq), type(t) {}
std::string DebugString() const;
};
@@ -84,15 +83,13 @@ inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) {
}
// Append the serialization of "key" to *result.
-extern void AppendInternalKey(std::string* result,
- const ParsedInternalKey& key);
+void AppendInternalKey(std::string* result, const ParsedInternalKey& key);
// Attempt to parse an internal key from "internal_key". On success,
// stores the parsed data in "*result", and returns true.
//
// On error, returns false, leaves "*result" in an undefined state.
-extern bool ParseInternalKey(const Slice& internal_key,
- ParsedInternalKey* result);
+bool ParseInternalKey(const Slice& internal_key, ParsedInternalKey* result);
// Returns the user key portion of an internal key.
inline Slice ExtractUserKey(const Slice& internal_key) {
@@ -100,27 +97,19 @@ inline Slice ExtractUserKey(const Slice& internal_key) {
return Slice(internal_key.data(), internal_key.size() - 8);
}
-inline ValueType ExtractValueType(const Slice& internal_key) {
- assert(internal_key.size() >= 8);
- const size_t n = internal_key.size();
- uint64_t num = DecodeFixed64(internal_key.data() + n - 8);
- unsigned char c = num & 0xff;
- return static_cast<ValueType>(c);
-}
-
// A comparator for internal keys that uses a specified comparator for
// the user key portion and breaks ties by decreasing sequence number.
class InternalKeyComparator : public Comparator {
private:
const Comparator* user_comparator_;
+
public:
- explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) { }
- virtual const char* Name() const;
- virtual int Compare(const Slice& a, const Slice& b) const;
- virtual void FindShortestSeparator(
- std::string* start,
- const Slice& limit) const;
- virtual void FindShortSuccessor(std::string* key) const;
+ explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) {}
+ const char* Name() const override;
+ int Compare(const Slice& a, const Slice& b) const override;
+ void FindShortestSeparator(std::string* start,
+ const Slice& limit) const override;
+ void FindShortSuccessor(std::string* key) const override;
const Comparator* user_comparator() const { return user_comparator_; }
@@ -131,11 +120,12 @@ class InternalKeyComparator : public Comparator {
class InternalFilterPolicy : public FilterPolicy {
private:
const FilterPolicy* const user_policy_;
+
public:
- explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) { }
- virtual const char* Name() const;
- virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const;
- virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const;
+ explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) {}
+ const char* Name() const override;
+ void CreateFilter(const Slice* keys, int n, std::string* dst) const override;
+ bool KeyMayMatch(const Slice& key, const Slice& filter) const override;
};
// Modules in this directory should keep internal keys wrapped inside
@@ -144,13 +134,18 @@ class InternalFilterPolicy : public FilterPolicy {
class InternalKey {
private:
std::string rep_;
+
public:
- InternalKey() { } // Leave rep_ as empty to indicate it is invalid
+ InternalKey() {} // Leave rep_ as empty to indicate it is invalid
InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) {
AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t));
}
- void DecodeFrom(const Slice& s) { rep_.assign(s.data(), s.size()); }
+ bool DecodeFrom(const Slice& s) {
+ rep_.assign(s.data(), s.size());
+ return !rep_.empty();
+ }
+
Slice Encode() const {
assert(!rep_.empty());
return rep_;
@@ -168,8 +163,8 @@ class InternalKey {
std::string DebugString() const;
};
-inline int InternalKeyComparator::Compare(
- const InternalKey& a, const InternalKey& b) const {
+inline int InternalKeyComparator::Compare(const InternalKey& a,
+ const InternalKey& b) const {
return Compare(a.Encode(), b.Encode());
}
@@ -178,11 +173,11 @@ inline bool ParseInternalKey(const Slice& internal_key,
const size_t n = internal_key.size();
if (n < 8) return false;
uint64_t num = DecodeFixed64(internal_key.data() + n - 8);
- unsigned char c = num & 0xff;
+ uint8_t c = num & 0xff;
result->sequence = num >> 8;
result->type = static_cast<ValueType>(c);
result->user_key = Slice(internal_key.data(), n - 8);
- return (c <= static_cast<unsigned char>(kTypeValue));
+ return (c <= static_cast<uint8_t>(kTypeValue));
}
// A helper class useful for DBImpl::Get()
@@ -192,6 +187,9 @@ class LookupKey {
// the specified sequence number.
LookupKey(const Slice& user_key, SequenceNumber sequence);
+ LookupKey(const LookupKey&) = delete;
+ LookupKey& operator=(const LookupKey&) = delete;
+
~LookupKey();
// Return a key suitable for lookup in a MemTable.
@@ -214,11 +212,7 @@ class LookupKey {
const char* start_;
const char* kstart_;
const char* end_;
- char space_[200]; // Avoid allocation for short keys
-
- // No copying allowed
- LookupKey(const LookupKey&);
- void operator=(const LookupKey&);
+ char space_[200]; // Avoid allocation for short keys
};
inline LookupKey::~LookupKey() {
diff --git a/src/leveldb/db/dbformat_test.cc b/src/leveldb/db/dbformat_test.cc
index 5d82f5d313..1209369c31 100644
--- a/src/leveldb/db/dbformat_test.cc
+++ b/src/leveldb/db/dbformat_test.cc
@@ -8,8 +8,7 @@
namespace leveldb {
-static std::string IKey(const std::string& user_key,
- uint64_t seq,
+static std::string IKey(const std::string& user_key, uint64_t seq,
ValueType vt) {
std::string encoded;
AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt));
@@ -28,9 +27,7 @@ static std::string ShortSuccessor(const std::string& s) {
return result;
}
-static void TestKey(const std::string& key,
- uint64_t seq,
- ValueType vt) {
+static void TestKey(const std::string& key, uint64_t seq, ValueType vt) {
std::string encoded = IKey(key, seq, vt);
Slice in(encoded);
@@ -44,16 +41,22 @@ static void TestKey(const std::string& key,
ASSERT_TRUE(!ParseInternalKey(Slice("bar"), &decoded));
}
-class FormatTest { };
+class FormatTest {};
TEST(FormatTest, InternalKey_EncodeDecode) {
- const char* keys[] = { "", "k", "hello", "longggggggggggggggggggggg" };
- const uint64_t seq[] = {
- 1, 2, 3,
- (1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1,
- (1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1,
- (1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1
- };
+ const char* keys[] = {"", "k", "hello", "longggggggggggggggggggggg"};
+ const uint64_t seq[] = {1,
+ 2,
+ 3,
+ (1ull << 8) - 1,
+ 1ull << 8,
+ (1ull << 8) + 1,
+ (1ull << 16) - 1,
+ 1ull << 16,
+ (1ull << 16) + 1,
+ (1ull << 32) - 1,
+ 1ull << 32,
+ (1ull << 32) + 1};
for (int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) {
for (int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) {
TestKey(keys[k], seq[s], kTypeValue);
@@ -62,40 +65,44 @@ TEST(FormatTest, InternalKey_EncodeDecode) {
}
}
+TEST(FormatTest, InternalKey_DecodeFromEmpty) {
+ InternalKey internal_key;
+
+ ASSERT_TRUE(!internal_key.DecodeFrom(""));
+}
+
TEST(FormatTest, InternalKeyShortSeparator) {
// When user keys are same
ASSERT_EQ(IKey("foo", 100, kTypeValue),
- Shorten(IKey("foo", 100, kTypeValue),
- IKey("foo", 99, kTypeValue)));
- ASSERT_EQ(IKey("foo", 100, kTypeValue),
- Shorten(IKey("foo", 100, kTypeValue),
- IKey("foo", 101, kTypeValue)));
- ASSERT_EQ(IKey("foo", 100, kTypeValue),
- Shorten(IKey("foo", 100, kTypeValue),
- IKey("foo", 100, kTypeValue)));
- ASSERT_EQ(IKey("foo", 100, kTypeValue),
- Shorten(IKey("foo", 100, kTypeValue),
- IKey("foo", 100, kTypeDeletion)));
+ Shorten(IKey("foo", 100, kTypeValue), IKey("foo", 99, kTypeValue)));
+ ASSERT_EQ(
+ IKey("foo", 100, kTypeValue),
+ Shorten(IKey("foo", 100, kTypeValue), IKey("foo", 101, kTypeValue)));
+ ASSERT_EQ(
+ IKey("foo", 100, kTypeValue),
+ Shorten(IKey("foo", 100, kTypeValue), IKey("foo", 100, kTypeValue)));
+ ASSERT_EQ(
+ IKey("foo", 100, kTypeValue),
+ Shorten(IKey("foo", 100, kTypeValue), IKey("foo", 100, kTypeDeletion)));
// When user keys are misordered
ASSERT_EQ(IKey("foo", 100, kTypeValue),
- Shorten(IKey("foo", 100, kTypeValue),
- IKey("bar", 99, kTypeValue)));
+ Shorten(IKey("foo", 100, kTypeValue), IKey("bar", 99, kTypeValue)));
// When user keys are different, but correctly ordered
- ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
- Shorten(IKey("foo", 100, kTypeValue),
- IKey("hello", 200, kTypeValue)));
+ ASSERT_EQ(
+ IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
+ Shorten(IKey("foo", 100, kTypeValue), IKey("hello", 200, kTypeValue)));
// When start user key is prefix of limit user key
- ASSERT_EQ(IKey("foo", 100, kTypeValue),
- Shorten(IKey("foo", 100, kTypeValue),
- IKey("foobar", 200, kTypeValue)));
+ ASSERT_EQ(
+ IKey("foo", 100, kTypeValue),
+ Shorten(IKey("foo", 100, kTypeValue), IKey("foobar", 200, kTypeValue)));
// When limit user key is prefix of start user key
- ASSERT_EQ(IKey("foobar", 100, kTypeValue),
- Shorten(IKey("foobar", 100, kTypeValue),
- IKey("foo", 200, kTypeValue)));
+ ASSERT_EQ(
+ IKey("foobar", 100, kTypeValue),
+ Shorten(IKey("foobar", 100, kTypeValue), IKey("foo", 200, kTypeValue)));
}
TEST(FormatTest, InternalKeyShortestSuccessor) {
@@ -105,8 +112,20 @@ TEST(FormatTest, InternalKeyShortestSuccessor) {
ShortSuccessor(IKey("\xff\xff", 100, kTypeValue)));
}
-} // namespace leveldb
+TEST(FormatTest, ParsedInternalKeyDebugString) {
+ ParsedInternalKey key("The \"key\" in 'single quotes'", 42, kTypeValue);
+
+ ASSERT_EQ("'The \"key\" in 'single quotes'' @ 42 : 1", key.DebugString());
+}
+
+TEST(FormatTest, InternalKeyDebugString) {
+ InternalKey key("The \"key\" in 'single quotes'", 42, kTypeValue);
+ ASSERT_EQ("'The \"key\" in 'single quotes'' @ 42 : 1", key.DebugString());
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
+ InternalKey invalid_key;
+ ASSERT_EQ("(bad)", invalid_key.DebugString());
}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/dumpfile.cc b/src/leveldb/db/dumpfile.cc
index 61c47c2ff9..77d59003cf 100644
--- a/src/leveldb/db/dumpfile.cc
+++ b/src/leveldb/db/dumpfile.cc
@@ -2,7 +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.
+#include "leveldb/dumpfile.h"
+
#include <stdio.h>
+
#include "db/dbformat.h"
#include "db/filename.h"
#include "db/log_reader.h"
@@ -35,8 +38,7 @@ bool GuessType(const std::string& fname, FileType* type) {
// Notified when log reader encounters corruption.
class CorruptionReporter : public log::Reader::Reporter {
public:
- WritableFile* dst_;
- virtual void Corruption(size_t bytes, const Status& status) {
+ void Corruption(size_t bytes, const Status& status) override {
std::string r = "corruption: ";
AppendNumberTo(&r, bytes);
r += " bytes; ";
@@ -44,6 +46,8 @@ class CorruptionReporter : public log::Reader::Reporter {
r.push_back('\n');
dst_->Append(r);
}
+
+ WritableFile* dst_;
};
// Print contents of a log file. (*func)() is called on every record.
@@ -70,8 +74,7 @@ Status PrintLogContents(Env* env, const std::string& fname,
// Called on every item found in a WriteBatch.
class WriteBatchItemPrinter : public WriteBatch::Handler {
public:
- WritableFile* dst_;
- virtual void Put(const Slice& key, const Slice& value) {
+ void Put(const Slice& key, const Slice& value) override {
std::string r = " put '";
AppendEscapedStringTo(&r, key);
r += "' '";
@@ -79,14 +82,15 @@ class WriteBatchItemPrinter : public WriteBatch::Handler {
r += "'\n";
dst_->Append(r);
}
- virtual void Delete(const Slice& key) {
+ void Delete(const Slice& key) override {
std::string r = " del '";
AppendEscapedStringTo(&r, key);
r += "'\n";
dst_->Append(r);
}
-};
+ WritableFile* dst_;
+};
// Called on every log record (each one of which is a WriteBatch)
// found in a kLogFile.
@@ -142,8 +146,8 @@ Status DumpDescriptor(Env* env, const std::string& fname, WritableFile* dst) {
Status DumpTable(Env* env, const std::string& fname, WritableFile* dst) {
uint64_t file_size;
- RandomAccessFile* file = NULL;
- Table* table = NULL;
+ RandomAccessFile* file = nullptr;
+ Table* table = nullptr;
Status s = env->GetFileSize(fname, &file_size);
if (s.ok()) {
s = env->NewRandomAccessFile(fname, &file);
@@ -213,9 +217,12 @@ Status DumpFile(Env* env, const std::string& fname, WritableFile* dst) {
return Status::InvalidArgument(fname + ": unknown file type");
}
switch (ftype) {
- case kLogFile: return DumpLog(env, fname, dst);
- case kDescriptorFile: return DumpDescriptor(env, fname, dst);
- case kTableFile: return DumpTable(env, fname, dst);
+ case kLogFile:
+ return DumpLog(env, fname, dst);
+ case kDescriptorFile:
+ return DumpDescriptor(env, fname, dst);
+ case kTableFile:
+ return DumpTable(env, fname, dst);
default:
break;
}
diff --git a/src/leveldb/db/fault_injection_test.cc b/src/leveldb/db/fault_injection_test.cc
index 875dfe81ee..bf705cb60f 100644
--- a/src/leveldb/db/fault_injection_test.cc
+++ b/src/leveldb/db/fault_injection_test.cc
@@ -6,18 +6,20 @@
// the last "sync". It then checks for data loss errors by purposely dropping
// file data (or entire files) not protected by a "sync".
-#include "leveldb/db.h"
-
#include <map>
#include <set>
+
#include "db/db_impl.h"
#include "db/filename.h"
#include "db/log_format.h"
#include "db/version_set.h"
#include "leveldb/cache.h"
+#include "leveldb/db.h"
#include "leveldb/env.h"
#include "leveldb/table.h"
#include "leveldb/write_batch.h"
+#include "port/port.h"
+#include "port/thread_annotations.h"
#include "util/logging.h"
#include "util/mutexlock.h"
#include "util/testharness.h"
@@ -34,7 +36,7 @@ class FaultInjectionTestEnv;
namespace {
// Assume a filename, and not a directory name like "/foo/bar/"
-static std::string GetDirName(const std::string filename) {
+static std::string GetDirName(const std::string& filename) {
size_t found = filename.find_last_of("/\\");
if (found == std::string::npos) {
return "";
@@ -54,8 +56,7 @@ Status Truncate(const std::string& filename, uint64_t length) {
SequentialFile* orig_file;
Status s = env->NewSequentialFile(filename, &orig_file);
- if (!s.ok())
- return s;
+ if (!s.ok()) return s;
char* scratch = new char[length];
leveldb::Slice result;
@@ -83,15 +84,15 @@ Status Truncate(const std::string& filename, uint64_t length) {
struct FileState {
std::string filename_;
- ssize_t pos_;
- ssize_t pos_at_last_sync_;
- ssize_t pos_at_last_flush_;
+ int64_t pos_;
+ int64_t pos_at_last_sync_;
+ int64_t pos_at_last_flush_;
FileState(const std::string& filename)
: filename_(filename),
pos_(-1),
pos_at_last_sync_(-1),
- pos_at_last_flush_(-1) { }
+ pos_at_last_flush_(-1) {}
FileState() : pos_(-1), pos_at_last_sync_(-1), pos_at_last_flush_(-1) {}
@@ -106,14 +107,14 @@ struct FileState {
// is written to or sync'ed.
class TestWritableFile : public WritableFile {
public:
- TestWritableFile(const FileState& state,
- WritableFile* f,
+ TestWritableFile(const FileState& state, WritableFile* f,
FaultInjectionTestEnv* env);
- virtual ~TestWritableFile();
- virtual Status Append(const Slice& data);
- virtual Status Close();
- virtual Status Flush();
- virtual Status Sync();
+ ~TestWritableFile() override;
+ Status Append(const Slice& data) override;
+ Status Close() override;
+ Status Flush() override;
+ Status Sync() override;
+ std::string GetName() const override { return ""; }
private:
FileState state_;
@@ -126,14 +127,15 @@ class TestWritableFile : public WritableFile {
class FaultInjectionTestEnv : public EnvWrapper {
public:
- FaultInjectionTestEnv() : EnvWrapper(Env::Default()), filesystem_active_(true) {}
- virtual ~FaultInjectionTestEnv() { }
- virtual Status NewWritableFile(const std::string& fname,
- WritableFile** result);
- virtual Status NewAppendableFile(const std::string& fname,
- WritableFile** result);
- virtual Status DeleteFile(const std::string& f);
- virtual Status RenameFile(const std::string& s, const std::string& t);
+ FaultInjectionTestEnv()
+ : EnvWrapper(Env::Default()), filesystem_active_(true) {}
+ ~FaultInjectionTestEnv() override = default;
+ Status NewWritableFile(const std::string& fname,
+ WritableFile** result) override;
+ Status NewAppendableFile(const std::string& fname,
+ WritableFile** result) override;
+ Status DeleteFile(const std::string& f) override;
+ Status RenameFile(const std::string& s, const std::string& t) override;
void WritableFileClosed(const FileState& state);
Status DropUnsyncedFileData();
@@ -146,24 +148,26 @@ class FaultInjectionTestEnv : public EnvWrapper {
// system reset. Setting to inactive will freeze our saved filesystem state so
// that it will stop being recorded. It can then be reset back to the state at
// the time of the reset.
- bool IsFilesystemActive() const { return filesystem_active_; }
- void SetFilesystemActive(bool active) { filesystem_active_ = active; }
+ bool IsFilesystemActive() LOCKS_EXCLUDED(mutex_) {
+ MutexLock l(&mutex_);
+ return filesystem_active_;
+ }
+ void SetFilesystemActive(bool active) LOCKS_EXCLUDED(mutex_) {
+ MutexLock l(&mutex_);
+ filesystem_active_ = active;
+ }
private:
port::Mutex mutex_;
- std::map<std::string, FileState> db_file_state_;
- std::set<std::string> new_files_since_last_dir_sync_;
- bool filesystem_active_; // Record flushes, syncs, writes
+ std::map<std::string, FileState> db_file_state_ GUARDED_BY(mutex_);
+ std::set<std::string> new_files_since_last_dir_sync_ GUARDED_BY(mutex_);
+ bool filesystem_active_ GUARDED_BY(mutex_); // Record flushes, syncs, writes
};
-TestWritableFile::TestWritableFile(const FileState& state,
- WritableFile* f,
+TestWritableFile::TestWritableFile(const FileState& state, WritableFile* f,
FaultInjectionTestEnv* env)
- : state_(state),
- target_(f),
- writable_file_opened_(true),
- env_(env) {
- assert(f != NULL);
+ : state_(state), target_(f), writable_file_opened_(true), env_(env) {
+ assert(f != nullptr);
}
TestWritableFile::~TestWritableFile() {
@@ -265,10 +269,11 @@ Status FaultInjectionTestEnv::NewAppendableFile(const std::string& fname,
Status FaultInjectionTestEnv::DropUnsyncedFileData() {
Status s;
MutexLock l(&mutex_);
- for (std::map<std::string, FileState>::const_iterator it =
- db_file_state_.begin();
- s.ok() && it != db_file_state_.end(); ++it) {
- const FileState& state = it->second;
+ for (const auto& kvp : db_file_state_) {
+ if (!s.ok()) {
+ break;
+ }
+ const FileState& state = kvp.second;
if (!state.IsFullySynced()) {
s = state.DropUnsyncedData();
}
@@ -328,7 +333,6 @@ void FaultInjectionTestEnv::ResetState() {
// Since we are not destroying the database, the existing files
// should keep their recorded synced/flushed state. Therefore
// we do not reset db_file_state_ and new_files_since_last_dir_sync_.
- MutexLock l(&mutex_);
SetFilesystemActive(true);
}
@@ -338,12 +342,14 @@ Status FaultInjectionTestEnv::DeleteFilesCreatedAfterLastDirSync() {
std::set<std::string> new_files(new_files_since_last_dir_sync_.begin(),
new_files_since_last_dir_sync_.end());
mutex_.Unlock();
- Status s;
- std::set<std::string>::const_iterator it;
- for (it = new_files.begin(); s.ok() && it != new_files.end(); ++it) {
- s = DeleteFile(*it);
+ Status status;
+ for (const auto& new_file : new_files) {
+ Status delete_status = DeleteFile(new_file);
+ if (!delete_status.ok() && status.ok()) {
+ status = std::move(delete_status);
+ }
}
- return s;
+ return status;
}
void FaultInjectionTestEnv::WritableFileClosed(const FileState& state) {
@@ -352,7 +358,7 @@ void FaultInjectionTestEnv::WritableFileClosed(const FileState& state) {
}
Status FileState::DropUnsyncedData() const {
- ssize_t sync_pos = pos_at_last_sync_ == -1 ? 0 : pos_at_last_sync_;
+ int64_t sync_pos = pos_at_last_sync_ == -1 ? 0 : pos_at_last_sync_;
return Truncate(filename_, sync_pos);
}
@@ -370,7 +376,7 @@ class FaultInjectionTest {
FaultInjectionTest()
: env_(new FaultInjectionTestEnv),
tiny_cache_(NewLRUCache(100)),
- db_(NULL) {
+ db_(nullptr) {
dbname_ = test::TmpDir() + "/fault_test";
DestroyDB(dbname_, Options()); // Destroy any db from earlier run
options_.reuse_logs = true;
@@ -387,9 +393,7 @@ class FaultInjectionTest {
delete env_;
}
- void ReuseLogs(bool reuse) {
- options_.reuse_logs = reuse;
- }
+ void ReuseLogs(bool reuse) { options_.reuse_logs = reuse; }
void Build(int start_idx, int num_vals) {
std::string key_space, value_space;
@@ -449,19 +453,18 @@ class FaultInjectionTest {
Status OpenDB() {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
env_->ResetState();
return DB::Open(options_, dbname_, &db_);
}
void CloseDB() {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
}
void DeleteAllData() {
Iterator* iter = db_->NewIterator(ReadOptions());
- WriteOptions options;
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
ASSERT_OK(db_->Delete(WriteOptions(), iter->key()));
}
@@ -485,23 +488,22 @@ class FaultInjectionTest {
void PartialCompactTestPreFault(int num_pre_sync, int num_post_sync) {
DeleteAllData();
Build(0, num_pre_sync);
- db_->CompactRange(NULL, NULL);
+ db_->CompactRange(nullptr, nullptr);
Build(num_pre_sync, num_post_sync);
}
void PartialCompactTestReopenWithFault(ResetMethod reset_method,
- int num_pre_sync,
- int num_post_sync) {
+ int num_pre_sync, int num_post_sync) {
env_->SetFilesystemActive(false);
CloseDB();
ResetDBState(reset_method);
ASSERT_OK(OpenDB());
ASSERT_OK(Verify(0, num_pre_sync, FaultInjectionTest::VAL_EXPECT_NO_ERROR));
- ASSERT_OK(Verify(num_pre_sync, num_post_sync, FaultInjectionTest::VAL_EXPECT_ERROR));
+ ASSERT_OK(Verify(num_pre_sync, num_post_sync,
+ FaultInjectionTest::VAL_EXPECT_ERROR));
}
- void NoWriteTestPreFault() {
- }
+ void NoWriteTestPreFault() {}
void NoWriteTestReopenWithFault(ResetMethod reset_method) {
CloseDB();
@@ -517,8 +519,7 @@ class FaultInjectionTest {
int num_post_sync = rnd.Uniform(kMaxNumValues);
PartialCompactTestPreFault(num_pre_sync, num_post_sync);
- PartialCompactTestReopenWithFault(RESET_DROP_UNSYNCED_DATA,
- num_pre_sync,
+ PartialCompactTestReopenWithFault(RESET_DROP_UNSYNCED_DATA, num_pre_sync,
num_post_sync);
NoWriteTestPreFault();
@@ -528,8 +529,7 @@ class FaultInjectionTest {
// No new files created so we expect all values since no files will be
// dropped.
PartialCompactTestReopenWithFault(RESET_DELETE_UNSYNCED_FILES,
- num_pre_sync + num_post_sync,
- 0);
+ num_pre_sync + num_post_sync, 0);
NoWriteTestPreFault();
NoWriteTestReopenWithFault(RESET_DELETE_UNSYNCED_FILES);
@@ -549,6 +549,4 @@ TEST(FaultInjectionTest, FaultTestWithLogReuse) {
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/filename.cc b/src/leveldb/db/filename.cc
index da32946d99..85de45c507 100644
--- a/src/leveldb/db/filename.cc
+++ b/src/leveldb/db/filename.cc
@@ -2,9 +2,11 @@
// 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.
+#include "db/filename.h"
+
#include <ctype.h>
#include <stdio.h>
-#include "db/filename.h"
+
#include "db/dbformat.h"
#include "leveldb/env.h"
#include "util/logging.h"
@@ -12,31 +14,30 @@
namespace leveldb {
// A utility routine: write "data" to the named file and Sync() it.
-extern Status WriteStringToFileSync(Env* env, const Slice& data,
- const std::string& fname);
+Status WriteStringToFileSync(Env* env, const Slice& data,
+ const std::string& fname);
-static std::string MakeFileName(const std::string& name, uint64_t number,
+static std::string MakeFileName(const std::string& dbname, uint64_t number,
const char* suffix) {
char buf[100];
snprintf(buf, sizeof(buf), "/%06llu.%s",
- static_cast<unsigned long long>(number),
- suffix);
- return name + buf;
+ static_cast<unsigned long long>(number), suffix);
+ return dbname + buf;
}
-std::string LogFileName(const std::string& name, uint64_t number) {
+std::string LogFileName(const std::string& dbname, uint64_t number) {
assert(number > 0);
- return MakeFileName(name, number, "log");
+ return MakeFileName(dbname, number, "log");
}
-std::string TableFileName(const std::string& name, uint64_t number) {
+std::string TableFileName(const std::string& dbname, uint64_t number) {
assert(number > 0);
- return MakeFileName(name, number, "ldb");
+ return MakeFileName(dbname, number, "ldb");
}
-std::string SSTTableFileName(const std::string& name, uint64_t number) {
+std::string SSTTableFileName(const std::string& dbname, uint64_t number) {
assert(number > 0);
- return MakeFileName(name, number, "sst");
+ return MakeFileName(dbname, number, "sst");
}
std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
@@ -51,9 +52,7 @@ std::string CurrentFileName(const std::string& dbname) {
return dbname + "/CURRENT";
}
-std::string LockFileName(const std::string& dbname) {
- return dbname + "/LOCK";
-}
+std::string LockFileName(const std::string& dbname) { return dbname + "/LOCK"; }
std::string TempFileName(const std::string& dbname, uint64_t number) {
assert(number > 0);
@@ -69,7 +68,6 @@ std::string OldInfoLogFileName(const std::string& dbname) {
return dbname + "/LOG.old";
}
-
// Owned filenames have the form:
// dbname/CURRENT
// dbname/LOCK
@@ -77,10 +75,9 @@ std::string OldInfoLogFileName(const std::string& dbname) {
// dbname/LOG.old
// dbname/MANIFEST-[0-9]+
// dbname/[0-9]+.(log|sst|ldb)
-bool ParseFileName(const std::string& fname,
- uint64_t* number,
+bool ParseFileName(const std::string& filename, uint64_t* number,
FileType* type) {
- Slice rest(fname);
+ Slice rest(filename);
if (rest == "CURRENT") {
*number = 0;
*type = kCurrentFile;
diff --git a/src/leveldb/db/filename.h b/src/leveldb/db/filename.h
index 87a752605d..524e813c06 100644
--- a/src/leveldb/db/filename.h
+++ b/src/leveldb/db/filename.h
@@ -8,7 +8,9 @@
#define STORAGE_LEVELDB_DB_FILENAME_H_
#include <stdint.h>
+
#include <string>
+
#include "leveldb/slice.h"
#include "leveldb/status.h"
#include "port/port.h"
@@ -30,55 +32,52 @@ enum FileType {
// Return the name of the log file with the specified number
// in the db named by "dbname". The result will be prefixed with
// "dbname".
-extern std::string LogFileName(const std::string& dbname, uint64_t number);
+std::string LogFileName(const std::string& dbname, uint64_t number);
// Return the name of the sstable with the specified number
// in the db named by "dbname". The result will be prefixed with
// "dbname".
-extern std::string TableFileName(const std::string& dbname, uint64_t number);
+std::string TableFileName(const std::string& dbname, uint64_t number);
// Return the legacy file name for an sstable with the specified number
// in the db named by "dbname". The result will be prefixed with
// "dbname".
-extern std::string SSTTableFileName(const std::string& dbname, uint64_t number);
+std::string SSTTableFileName(const std::string& dbname, uint64_t number);
// Return the name of the descriptor file for the db named by
// "dbname" and the specified incarnation number. The result will be
// prefixed with "dbname".
-extern std::string DescriptorFileName(const std::string& dbname,
- uint64_t number);
+std::string DescriptorFileName(const std::string& dbname, uint64_t number);
// Return the name of the current file. This file contains the name
// of the current manifest file. The result will be prefixed with
// "dbname".
-extern std::string CurrentFileName(const std::string& dbname);
+std::string CurrentFileName(const std::string& dbname);
// Return the name of the lock file for the db named by
// "dbname". The result will be prefixed with "dbname".
-extern std::string LockFileName(const std::string& dbname);
+std::string LockFileName(const std::string& dbname);
// Return the name of a temporary file owned by the db named "dbname".
// The result will be prefixed with "dbname".
-extern std::string TempFileName(const std::string& dbname, uint64_t number);
+std::string TempFileName(const std::string& dbname, uint64_t number);
// Return the name of the info log file for "dbname".
-extern std::string InfoLogFileName(const std::string& dbname);
+std::string InfoLogFileName(const std::string& dbname);
// Return the name of the old info log file for "dbname".
-extern std::string OldInfoLogFileName(const std::string& dbname);
+std::string OldInfoLogFileName(const std::string& dbname);
// If filename is a leveldb file, store the type of the file in *type.
// The number encoded in the filename is stored in *number. If the
// filename was successfully parsed, returns true. Else return false.
-extern bool ParseFileName(const std::string& filename,
- uint64_t* number,
- FileType* type);
+bool ParseFileName(const std::string& filename, uint64_t* number,
+ FileType* type);
// Make the CURRENT file point to the descriptor file with the
// specified number.
-extern Status SetCurrentFile(Env* env, const std::string& dbname,
- uint64_t descriptor_number);
-
+Status SetCurrentFile(Env* env, const std::string& dbname,
+ uint64_t descriptor_number);
} // namespace leveldb
diff --git a/src/leveldb/db/filename_test.cc b/src/leveldb/db/filename_test.cc
index a32556deaf..952f32008e 100644
--- a/src/leveldb/db/filename_test.cc
+++ b/src/leveldb/db/filename_test.cc
@@ -11,7 +11,7 @@
namespace leveldb {
-class FileNameTest { };
+class FileNameTest {};
TEST(FileNameTest, Parse) {
Slice db;
@@ -24,17 +24,17 @@ TEST(FileNameTest, Parse) {
uint64_t number;
FileType type;
} cases[] = {
- { "100.log", 100, kLogFile },
- { "0.log", 0, kLogFile },
- { "0.sst", 0, kTableFile },
- { "0.ldb", 0, kTableFile },
- { "CURRENT", 0, kCurrentFile },
- { "LOCK", 0, kDBLockFile },
- { "MANIFEST-2", 2, kDescriptorFile },
- { "MANIFEST-7", 7, kDescriptorFile },
- { "LOG", 0, kInfoLogFile },
- { "LOG.old", 0, kInfoLogFile },
- { "18446744073709551615.log", 18446744073709551615ull, kLogFile },
+ {"100.log", 100, kLogFile},
+ {"0.log", 0, kLogFile},
+ {"0.sst", 0, kTableFile},
+ {"0.ldb", 0, kTableFile},
+ {"CURRENT", 0, kCurrentFile},
+ {"LOCK", 0, kDBLockFile},
+ {"MANIFEST-2", 2, kDescriptorFile},
+ {"MANIFEST-7", 7, kDescriptorFile},
+ {"LOG", 0, kInfoLogFile},
+ {"LOG.old", 0, kInfoLogFile},
+ {"18446744073709551615.log", 18446744073709551615ull, kLogFile},
};
for (int i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
std::string f = cases[i].fname;
@@ -44,30 +44,28 @@ TEST(FileNameTest, Parse) {
}
// Errors
- static const char* errors[] = {
- "",
- "foo",
- "foo-dx-100.log",
- ".log",
- "",
- "manifest",
- "CURREN",
- "CURRENTX",
- "MANIFES",
- "MANIFEST",
- "MANIFEST-",
- "XMANIFEST-3",
- "MANIFEST-3x",
- "LOC",
- "LOCKx",
- "LO",
- "LOGx",
- "18446744073709551616.log",
- "184467440737095516150.log",
- "100",
- "100.",
- "100.lop"
- };
+ static const char* errors[] = {"",
+ "foo",
+ "foo-dx-100.log",
+ ".log",
+ "",
+ "manifest",
+ "CURREN",
+ "CURRENTX",
+ "MANIFES",
+ "MANIFEST",
+ "MANIFEST-",
+ "XMANIFEST-3",
+ "MANIFEST-3x",
+ "LOC",
+ "LOCKx",
+ "LO",
+ "LOGx",
+ "18446744073709551616.log",
+ "184467440737095516150.log",
+ "100",
+ "100.",
+ "100.lop"};
for (int i = 0; i < sizeof(errors) / sizeof(errors[0]); i++) {
std::string f = errors[i];
ASSERT_TRUE(!ParseFileName(f, &number, &type)) << f;
@@ -114,10 +112,20 @@ TEST(FileNameTest, Construction) {
ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type));
ASSERT_EQ(999, number);
ASSERT_EQ(kTempFile, type);
+
+ fname = InfoLogFileName("foo");
+ ASSERT_EQ("foo/", std::string(fname.data(), 4));
+ ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type));
+ ASSERT_EQ(0, number);
+ ASSERT_EQ(kInfoLogFile, type);
+
+ fname = OldInfoLogFileName("foo");
+ ASSERT_EQ("foo/", std::string(fname.data(), 4));
+ ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type));
+ ASSERT_EQ(0, number);
+ ASSERT_EQ(kInfoLogFile, type);
}
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/leveldbutil.cc b/src/leveldb/db/leveldbutil.cc
index d06d64d640..9ed9667d37 100644
--- a/src/leveldb/db/leveldbutil.cc
+++ b/src/leveldb/db/leveldbutil.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include <stdio.h>
+
#include "leveldb/dumpfile.h"
#include "leveldb/env.h"
#include "leveldb/status.h"
@@ -12,14 +13,14 @@ namespace {
class StdoutPrinter : public WritableFile {
public:
- virtual Status Append(const Slice& data) {
+ Status Append(const Slice& data) override {
fwrite(data.data(), 1, data.size(), stdout);
return Status::OK();
}
- virtual Status Close() { return Status::OK(); }
- virtual Status Flush() { return Status::OK(); }
- virtual Status Sync() { return Status::OK(); }
- virtual std::string GetName() const { return "[stdout]"; }
+ Status Close() override { return Status::OK(); }
+ Status Flush() override { return Status::OK(); }
+ Status Sync() override { return Status::OK(); }
+ std::string GetName() const override { return "[stdout]"; }
};
bool HandleDumpCommand(Env* env, char** files, int num) {
@@ -39,11 +40,9 @@ bool HandleDumpCommand(Env* env, char** files, int num) {
} // namespace leveldb
static void Usage() {
- fprintf(
- stderr,
- "Usage: leveldbutil command...\n"
- " dump files... -- dump contents of specified files\n"
- );
+ fprintf(stderr,
+ "Usage: leveldbutil command...\n"
+ " dump files... -- dump contents of specified files\n");
}
int main(int argc, char** argv) {
@@ -55,7 +54,7 @@ int main(int argc, char** argv) {
} else {
std::string command = argv[1];
if (command == "dump") {
- ok = leveldb::HandleDumpCommand(env, argv+2, argc-2);
+ ok = leveldb::HandleDumpCommand(env, argv + 2, argc - 2);
} else {
Usage();
ok = false;
diff --git a/src/leveldb/db/log_reader.cc b/src/leveldb/db/log_reader.cc
index 8b6ad136d7..1ccfb7b34a 100644
--- a/src/leveldb/db/log_reader.cc
+++ b/src/leveldb/db/log_reader.cc
@@ -5,6 +5,7 @@
#include "db/log_reader.h"
#include <stdio.h>
+
#include "leveldb/env.h"
#include "util/coding.h"
#include "util/crc32c.h"
@@ -12,8 +13,7 @@
namespace leveldb {
namespace log {
-Reader::Reporter::~Reporter() {
-}
+Reader::Reporter::~Reporter() = default;
Reader::Reader(SequentialFile* file, Reporter* reporter, bool checksum,
uint64_t initial_offset)
@@ -26,20 +26,16 @@ Reader::Reader(SequentialFile* file, Reporter* reporter, bool checksum,
last_record_offset_(0),
end_of_buffer_offset_(0),
initial_offset_(initial_offset),
- resyncing_(initial_offset > 0) {
-}
+ resyncing_(initial_offset > 0) {}
-Reader::~Reader() {
- delete[] backing_store_;
-}
+Reader::~Reader() { delete[] backing_store_; }
bool Reader::SkipToInitialBlock() {
- size_t offset_in_block = initial_offset_ % kBlockSize;
+ const size_t offset_in_block = initial_offset_ % kBlockSize;
uint64_t block_start_location = initial_offset_ - offset_in_block;
// Don't search a block if we'd be in the trailer
if (offset_in_block > kBlockSize - 6) {
- offset_in_block = 0;
block_start_location += kBlockSize;
}
@@ -99,9 +95,7 @@ bool Reader::ReadRecord(Slice* record, std::string* scratch) {
// it could emit an empty kFirstType record at the tail end
// of a block followed by a kFullType or kFirstType record
// at the beginning of the next block.
- if (scratch->empty()) {
- in_fragmented_record = false;
- } else {
+ if (!scratch->empty()) {
ReportCorruption(scratch->size(), "partial record without end(1)");
}
}
@@ -117,9 +111,7 @@ bool Reader::ReadRecord(Slice* record, std::string* scratch) {
// it could emit an empty kFirstType record at the tail end
// of a block followed by a kFullType or kFirstType record
// at the beginning of the next block.
- if (scratch->empty()) {
- in_fragmented_record = false;
- } else {
+ if (!scratch->empty()) {
ReportCorruption(scratch->size(), "partial record without end(2)");
}
}
@@ -181,16 +173,14 @@ bool Reader::ReadRecord(Slice* record, std::string* scratch) {
return false;
}
-uint64_t Reader::LastRecordOffset() {
- return last_record_offset_;
-}
+uint64_t Reader::LastRecordOffset() { return last_record_offset_; }
void Reader::ReportCorruption(uint64_t bytes, const char* reason) {
ReportDrop(bytes, Status::Corruption(reason, file_->GetName()));
}
void Reader::ReportDrop(uint64_t bytes, const Status& reason) {
- if (reporter_ != NULL &&
+ if (reporter_ != nullptr &&
end_of_buffer_offset_ - buffer_.size() - bytes >= initial_offset_) {
reporter_->Corruption(static_cast<size_t>(bytes), reason);
}
diff --git a/src/leveldb/db/log_reader.h b/src/leveldb/db/log_reader.h
index 8389d61f8f..001da8948a 100644
--- a/src/leveldb/db/log_reader.h
+++ b/src/leveldb/db/log_reader.h
@@ -32,7 +32,7 @@ class Reader {
// Create a reader that will return log records from "*file".
// "*file" must remain live while this Reader is in use.
//
- // If "reporter" is non-NULL, it is notified whenever some data is
+ // If "reporter" is non-null, it is notified whenever some data is
// dropped due to a detected corruption. "*reporter" must remain
// live while this Reader is in use.
//
@@ -43,6 +43,9 @@ class Reader {
Reader(SequentialFile* file, Reporter* reporter, bool checksum,
uint64_t initial_offset);
+ Reader(const Reader&) = delete;
+ Reader& operator=(const Reader&) = delete;
+
~Reader();
// Read the next record into *record. Returns true if read
@@ -58,26 +61,6 @@ class Reader {
uint64_t LastRecordOffset();
private:
- SequentialFile* const file_;
- Reporter* const reporter_;
- bool const checksum_;
- char* const backing_store_;
- Slice buffer_;
- bool eof_; // Last Read() indicated EOF by returning < kBlockSize
-
- // Offset of the last record returned by ReadRecord.
- uint64_t last_record_offset_;
- // Offset of the first location past the end of buffer_.
- uint64_t end_of_buffer_offset_;
-
- // Offset at which to start looking for the first record to return
- uint64_t const initial_offset_;
-
- // True if we are resynchronizing after a seek (initial_offset_ > 0). In
- // particular, a run of kMiddleType and kLastType records can be silently
- // skipped in this mode
- bool resyncing_;
-
// Extend record types with the following special values
enum {
kEof = kMaxRecordType + 1,
@@ -102,9 +85,25 @@ class Reader {
void ReportCorruption(uint64_t bytes, const char* reason);
void ReportDrop(uint64_t bytes, const Status& reason);
- // No copying allowed
- Reader(const Reader&);
- void operator=(const Reader&);
+ SequentialFile* const file_;
+ Reporter* const reporter_;
+ bool const checksum_;
+ char* const backing_store_;
+ Slice buffer_;
+ bool eof_; // Last Read() indicated EOF by returning < kBlockSize
+
+ // Offset of the last record returned by ReadRecord.
+ uint64_t last_record_offset_;
+ // Offset of the first location past the end of buffer_.
+ uint64_t end_of_buffer_offset_;
+
+ // Offset at which to start looking for the first record to return
+ uint64_t const initial_offset_;
+
+ // True if we are resynchronizing after a seek (initial_offset_ > 0). In
+ // particular, a run of kMiddleType and kLastType records can be silently
+ // skipped in this mode
+ bool resyncing_;
};
} // namespace log
diff --git a/src/leveldb/db/log_test.cc b/src/leveldb/db/log_test.cc
index 48a5928657..41fc043068 100644
--- a/src/leveldb/db/log_test.cc
+++ b/src/leveldb/db/log_test.cc
@@ -37,87 +37,12 @@ static std::string RandomSkewedString(int i, Random* rnd) {
}
class LogTest {
- private:
- class StringDest : public WritableFile {
- public:
- std::string contents_;
-
- virtual Status Close() { return Status::OK(); }
- virtual Status Flush() { return Status::OK(); }
- virtual Status Sync() { return Status::OK(); }
- virtual Status Append(const Slice& slice) {
- contents_.append(slice.data(), slice.size());
- return Status::OK();
- }
- };
-
- class StringSource : public SequentialFile {
- public:
- Slice contents_;
- bool force_error_;
- bool returned_partial_;
- StringSource() : force_error_(false), returned_partial_(false) { }
-
- virtual Status Read(size_t n, Slice* result, char* scratch) {
- ASSERT_TRUE(!returned_partial_) << "must not Read() after eof/error";
-
- if (force_error_) {
- force_error_ = false;
- returned_partial_ = true;
- return Status::Corruption("read error");
- }
-
- if (contents_.size() < n) {
- n = contents_.size();
- returned_partial_ = true;
- }
- *result = Slice(contents_.data(), n);
- contents_.remove_prefix(n);
- return Status::OK();
- }
-
- virtual Status Skip(uint64_t n) {
- if (n > contents_.size()) {
- contents_.clear();
- return Status::NotFound("in-memory file skipped past end");
- }
-
- contents_.remove_prefix(n);
-
- return Status::OK();
- }
- };
-
- class ReportCollector : public Reader::Reporter {
- public:
- size_t dropped_bytes_;
- std::string message_;
-
- ReportCollector() : dropped_bytes_(0) { }
- virtual void Corruption(size_t bytes, const Status& status) {
- dropped_bytes_ += bytes;
- message_.append(status.ToString());
- }
- };
-
- StringDest dest_;
- StringSource source_;
- ReportCollector report_;
- bool reading_;
- Writer* writer_;
- Reader* reader_;
-
- // Record metadata for testing initial offset functionality
- static size_t initial_offset_record_sizes_[];
- static uint64_t initial_offset_last_record_offsets_[];
- static int num_initial_offset_records_;
-
public:
- LogTest() : reading_(false),
- writer_(new Writer(&dest_)),
- reader_(new Reader(&source_, &report_, true/*checksum*/,
- 0/*initial_offset*/)) {
- }
+ LogTest()
+ : reading_(false),
+ writer_(new Writer(&dest_)),
+ reader_(new Reader(&source_, &report_, true /*checksum*/,
+ 0 /*initial_offset*/)) {}
~LogTest() {
delete writer_;
@@ -134,9 +59,7 @@ class LogTest {
writer_->AddRecord(Slice(msg));
}
- size_t WrittenBytes() const {
- return dest_.contents_.size();
- }
+ size_t WrittenBytes() const { return dest_.contents_.size(); }
std::string Read() {
if (!reading_) {
@@ -166,22 +89,16 @@ class LogTest {
void FixChecksum(int header_offset, int len) {
// Compute crc of type/len/data
- uint32_t crc = crc32c::Value(&dest_.contents_[header_offset+6], 1 + len);
+ uint32_t crc = crc32c::Value(&dest_.contents_[header_offset + 6], 1 + len);
crc = crc32c::Mask(crc);
EncodeFixed32(&dest_.contents_[header_offset], crc);
}
- void ForceError() {
- source_.force_error_ = true;
- }
+ void ForceError() { source_.force_error_ = true; }
- size_t DroppedBytes() const {
- return report_.dropped_bytes_;
- }
+ size_t DroppedBytes() const { return report_.dropped_bytes_; }
- std::string ReportMessage() const {
- return report_.message_;
- }
+ std::string ReportMessage() const { return report_.message_; }
// Returns OK iff recorded error message contains "msg"
std::string MatchError(const std::string& msg) const {
@@ -202,14 +119,14 @@ class LogTest {
void StartReadingAt(uint64_t initial_offset) {
delete reader_;
- reader_ = new Reader(&source_, &report_, true/*checksum*/, initial_offset);
+ reader_ = new Reader(&source_, &report_, true /*checksum*/, initial_offset);
}
void CheckOffsetPastEndReturnsNoRecords(uint64_t offset_past_end) {
WriteInitialOffsetLog();
reading_ = true;
source_.contents_ = Slice(dest_.contents_);
- Reader* offset_reader = new Reader(&source_, &report_, true/*checksum*/,
+ Reader* offset_reader = new Reader(&source_, &report_, true /*checksum*/,
WrittenBytes() + offset_past_end);
Slice record;
std::string scratch;
@@ -222,8 +139,8 @@ class LogTest {
WriteInitialOffsetLog();
reading_ = true;
source_.contents_ = Slice(dest_.contents_);
- Reader* offset_reader = new Reader(&source_, &report_, true/*checksum*/,
- initial_offset);
+ Reader* offset_reader =
+ new Reader(&source_, &report_, true /*checksum*/, initial_offset);
// Read all records from expected_record_offset through the last one.
ASSERT_LT(expected_record_offset, num_initial_offset_records_);
@@ -240,36 +157,110 @@ class LogTest {
}
delete offset_reader;
}
+
+ private:
+ class StringDest : public WritableFile {
+ public:
+ Status Close() override { return Status::OK(); }
+ Status Flush() override { return Status::OK(); }
+ Status Sync() override { return Status::OK(); }
+ Status Append(const Slice& slice) override {
+ contents_.append(slice.data(), slice.size());
+ return Status::OK();
+ }
+ std::string GetName() const override { return ""; }
+
+ std::string contents_;
+ };
+
+ class StringSource : public SequentialFile {
+ public:
+ StringSource() : force_error_(false), returned_partial_(false) {}
+
+ Status Read(size_t n, Slice* result, char* scratch) override {
+ ASSERT_TRUE(!returned_partial_) << "must not Read() after eof/error";
+
+ if (force_error_) {
+ force_error_ = false;
+ returned_partial_ = true;
+ return Status::Corruption("read error");
+ }
+
+ if (contents_.size() < n) {
+ n = contents_.size();
+ returned_partial_ = true;
+ }
+ *result = Slice(contents_.data(), n);
+ contents_.remove_prefix(n);
+ return Status::OK();
+ }
+
+ Status Skip(uint64_t n) override {
+ if (n > contents_.size()) {
+ contents_.clear();
+ return Status::NotFound("in-memory file skipped past end");
+ }
+
+ contents_.remove_prefix(n);
+
+ return Status::OK();
+ }
+ std::string GetName() const { return ""; }
+
+ Slice contents_;
+ bool force_error_;
+ bool returned_partial_;
+ };
+
+ class ReportCollector : public Reader::Reporter {
+ public:
+ ReportCollector() : dropped_bytes_(0) {}
+ void Corruption(size_t bytes, const Status& status) override {
+ dropped_bytes_ += bytes;
+ message_.append(status.ToString());
+ }
+
+ size_t dropped_bytes_;
+ std::string message_;
+ };
+
+ // Record metadata for testing initial offset functionality
+ static size_t initial_offset_record_sizes_[];
+ static uint64_t initial_offset_last_record_offsets_[];
+ static int num_initial_offset_records_;
+
+ StringDest dest_;
+ StringSource source_;
+ ReportCollector report_;
+ bool reading_;
+ Writer* writer_;
+ Reader* reader_;
+};
+
+size_t LogTest::initial_offset_record_sizes_[] = {
+ 10000, // Two sizable records in first block
+ 10000,
+ 2 * log::kBlockSize - 1000, // Span three blocks
+ 1,
+ 13716, // Consume all but two bytes of block 3.
+ log::kBlockSize - kHeaderSize, // Consume the entirety of block 4.
};
-size_t LogTest::initial_offset_record_sizes_[] =
- {10000, // Two sizable records in first block
- 10000,
- 2 * log::kBlockSize - 1000, // Span three blocks
- 1,
- 13716, // Consume all but two bytes of block 3.
- log::kBlockSize - kHeaderSize, // Consume the entirety of block 4.
- };
-
-uint64_t LogTest::initial_offset_last_record_offsets_[] =
- {0,
- kHeaderSize + 10000,
- 2 * (kHeaderSize + 10000),
- 2 * (kHeaderSize + 10000) +
- (2 * log::kBlockSize - 1000) + 3 * kHeaderSize,
- 2 * (kHeaderSize + 10000) +
- (2 * log::kBlockSize - 1000) + 3 * kHeaderSize
- + kHeaderSize + 1,
- 3 * log::kBlockSize,
- };
+uint64_t LogTest::initial_offset_last_record_offsets_[] = {
+ 0,
+ kHeaderSize + 10000,
+ 2 * (kHeaderSize + 10000),
+ 2 * (kHeaderSize + 10000) + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize,
+ 2 * (kHeaderSize + 10000) + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize +
+ kHeaderSize + 1,
+ 3 * log::kBlockSize,
+};
// LogTest::initial_offset_last_record_offsets_ must be defined before this.
int LogTest::num_initial_offset_records_ =
- sizeof(LogTest::initial_offset_last_record_offsets_)/sizeof(uint64_t);
+ sizeof(LogTest::initial_offset_last_record_offsets_) / sizeof(uint64_t);
-TEST(LogTest, Empty) {
- ASSERT_EQ("EOF", Read());
-}
+TEST(LogTest, Empty) { ASSERT_EQ("EOF", Read()); }
TEST(LogTest, ReadWrite) {
Write("foo");
@@ -306,7 +297,7 @@ TEST(LogTest, Fragmentation) {
TEST(LogTest, MarginalTrailer) {
// Make a trailer that is exactly the same length as an empty record.
- const int n = kBlockSize - 2*kHeaderSize;
+ const int n = kBlockSize - 2 * kHeaderSize;
Write(BigString("foo", n));
ASSERT_EQ(kBlockSize - kHeaderSize, WrittenBytes());
Write("");
@@ -319,7 +310,7 @@ TEST(LogTest, MarginalTrailer) {
TEST(LogTest, MarginalTrailer2) {
// Make a trailer that is exactly the same length as an empty record.
- const int n = kBlockSize - 2*kHeaderSize;
+ const int n = kBlockSize - 2 * kHeaderSize;
Write(BigString("foo", n));
ASSERT_EQ(kBlockSize - kHeaderSize, WrittenBytes());
Write("bar");
@@ -331,7 +322,7 @@ TEST(LogTest, MarginalTrailer2) {
}
TEST(LogTest, ShortTrailer) {
- const int n = kBlockSize - 2*kHeaderSize + 4;
+ const int n = kBlockSize - 2 * kHeaderSize + 4;
Write(BigString("foo", n));
ASSERT_EQ(kBlockSize - kHeaderSize + 4, WrittenBytes());
Write("");
@@ -343,7 +334,7 @@ TEST(LogTest, ShortTrailer) {
}
TEST(LogTest, AlignedEof) {
- const int n = kBlockSize - 2*kHeaderSize + 4;
+ const int n = kBlockSize - 2 * kHeaderSize + 4;
Write(BigString("foo", n));
ASSERT_EQ(kBlockSize - kHeaderSize + 4, WrittenBytes());
ASSERT_EQ(BigString("foo", n), Read());
@@ -394,7 +385,7 @@ TEST(LogTest, BadRecordType) {
TEST(LogTest, TruncatedTrailingRecordIsIgnored) {
Write("foo");
- ShrinkSize(4); // Drop all payload as well as a header byte
+ ShrinkSize(4); // Drop all payload as well as a header byte
ASSERT_EQ("EOF", Read());
// Truncated last record is ignored, not treated as an error.
ASSERT_EQ(0, DroppedBytes());
@@ -492,7 +483,7 @@ TEST(LogTest, SkipIntoMultiRecord) {
// If initial_offset points to a record after first(R1) but before first(R2)
// incomplete fragment errors are not actual errors, and must be suppressed
// until a new first or full record is encountered.
- Write(BigString("foo", 3*kBlockSize));
+ Write(BigString("foo", 3 * kBlockSize));
Write("correct");
StartReadingAt(kBlockSize);
@@ -514,44 +505,30 @@ TEST(LogTest, ErrorJoinsRecords) {
Write("correct");
// Wipe the middle block
- for (int offset = kBlockSize; offset < 2*kBlockSize; offset++) {
+ for (int offset = kBlockSize; offset < 2 * kBlockSize; offset++) {
SetByte(offset, 'x');
}
ASSERT_EQ("correct", Read());
ASSERT_EQ("EOF", Read());
const size_t dropped = DroppedBytes();
- ASSERT_LE(dropped, 2*kBlockSize + 100);
- ASSERT_GE(dropped, 2*kBlockSize);
+ ASSERT_LE(dropped, 2 * kBlockSize + 100);
+ ASSERT_GE(dropped, 2 * kBlockSize);
}
-TEST(LogTest, ReadStart) {
- CheckInitialOffsetRecord(0, 0);
-}
+TEST(LogTest, ReadStart) { CheckInitialOffsetRecord(0, 0); }
-TEST(LogTest, ReadSecondOneOff) {
- CheckInitialOffsetRecord(1, 1);
-}
+TEST(LogTest, ReadSecondOneOff) { CheckInitialOffsetRecord(1, 1); }
-TEST(LogTest, ReadSecondTenThousand) {
- CheckInitialOffsetRecord(10000, 1);
-}
+TEST(LogTest, ReadSecondTenThousand) { CheckInitialOffsetRecord(10000, 1); }
-TEST(LogTest, ReadSecondStart) {
- CheckInitialOffsetRecord(10007, 1);
-}
+TEST(LogTest, ReadSecondStart) { CheckInitialOffsetRecord(10007, 1); }
-TEST(LogTest, ReadThirdOneOff) {
- CheckInitialOffsetRecord(10008, 2);
-}
+TEST(LogTest, ReadThirdOneOff) { CheckInitialOffsetRecord(10008, 2); }
-TEST(LogTest, ReadThirdStart) {
- CheckInitialOffsetRecord(20014, 2);
-}
+TEST(LogTest, ReadThirdStart) { CheckInitialOffsetRecord(20014, 2); }
-TEST(LogTest, ReadFourthOneOff) {
- CheckInitialOffsetRecord(20015, 3);
-}
+TEST(LogTest, ReadFourthOneOff) { CheckInitialOffsetRecord(20015, 3); }
TEST(LogTest, ReadFourthFirstBlockTrailer) {
CheckInitialOffsetRecord(log::kBlockSize - 4, 3);
@@ -575,17 +552,11 @@ TEST(LogTest, ReadInitialOffsetIntoBlockPadding) {
CheckInitialOffsetRecord(3 * log::kBlockSize - 3, 5);
}
-TEST(LogTest, ReadEnd) {
- CheckOffsetPastEndReturnsNoRecords(0);
-}
+TEST(LogTest, ReadEnd) { CheckOffsetPastEndReturnsNoRecords(0); }
-TEST(LogTest, ReadPastEnd) {
- CheckOffsetPastEndReturnsNoRecords(5);
-}
+TEST(LogTest, ReadPastEnd) { CheckOffsetPastEndReturnsNoRecords(5); }
} // namespace log
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/log_writer.cc b/src/leveldb/db/log_writer.cc
index 74a03270da..bfb16fb486 100644
--- a/src/leveldb/db/log_writer.cc
+++ b/src/leveldb/db/log_writer.cc
@@ -5,6 +5,7 @@
#include "db/log_writer.h"
#include <stdint.h>
+
#include "leveldb/env.h"
#include "util/coding.h"
#include "util/crc32c.h"
@@ -19,9 +20,7 @@ static void InitTypeCrc(uint32_t* type_crc) {
}
}
-Writer::Writer(WritableFile* dest)
- : dest_(dest),
- block_offset_(0) {
+Writer::Writer(WritableFile* dest) : dest_(dest), block_offset_(0) {
InitTypeCrc(type_crc_);
}
@@ -30,8 +29,7 @@ Writer::Writer(WritableFile* dest, uint64_t dest_length)
InitTypeCrc(type_crc_);
}
-Writer::~Writer() {
-}
+Writer::~Writer() = default;
Status Writer::AddRecord(const Slice& slice) {
const char* ptr = slice.data();
@@ -49,7 +47,7 @@ Status Writer::AddRecord(const Slice& slice) {
// Switch to a new block
if (leftover > 0) {
// Fill the trailer (literal below relies on kHeaderSize being 7)
- assert(kHeaderSize == 7);
+ static_assert(kHeaderSize == 7, "");
dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover));
}
block_offset_ = 0;
@@ -81,30 +79,31 @@ Status Writer::AddRecord(const Slice& slice) {
return s;
}
-Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, size_t n) {
- assert(n <= 0xffff); // Must fit in two bytes
- assert(block_offset_ + kHeaderSize + n <= kBlockSize);
+Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr,
+ size_t length) {
+ assert(length <= 0xffff); // Must fit in two bytes
+ assert(block_offset_ + kHeaderSize + length <= kBlockSize);
// Format the header
char buf[kHeaderSize];
- buf[4] = static_cast<char>(n & 0xff);
- buf[5] = static_cast<char>(n >> 8);
+ buf[4] = static_cast<char>(length & 0xff);
+ buf[5] = static_cast<char>(length >> 8);
buf[6] = static_cast<char>(t);
// Compute the crc of the record type and the payload.
- uint32_t crc = crc32c::Extend(type_crc_[t], ptr, n);
- crc = crc32c::Mask(crc); // Adjust for storage
+ uint32_t crc = crc32c::Extend(type_crc_[t], ptr, length);
+ crc = crc32c::Mask(crc); // Adjust for storage
EncodeFixed32(buf, crc);
// Write the header and the payload
Status s = dest_->Append(Slice(buf, kHeaderSize));
if (s.ok()) {
- s = dest_->Append(Slice(ptr, n));
+ s = dest_->Append(Slice(ptr, length));
if (s.ok()) {
s = dest_->Flush();
}
}
- block_offset_ += kHeaderSize + n;
+ block_offset_ += kHeaderSize + length;
return s;
}
diff --git a/src/leveldb/db/log_writer.h b/src/leveldb/db/log_writer.h
index 9e7cc4705b..c0a21147ee 100644
--- a/src/leveldb/db/log_writer.h
+++ b/src/leveldb/db/log_writer.h
@@ -6,6 +6,7 @@
#define STORAGE_LEVELDB_DB_LOG_WRITER_H_
#include <stdint.h>
+
#include "db/log_format.h"
#include "leveldb/slice.h"
#include "leveldb/status.h"
@@ -28,24 +29,23 @@ class Writer {
// "*dest" must remain live while this Writer is in use.
Writer(WritableFile* dest, uint64_t dest_length);
+ Writer(const Writer&) = delete;
+ Writer& operator=(const Writer&) = delete;
+
~Writer();
Status AddRecord(const Slice& slice);
private:
+ Status EmitPhysicalRecord(RecordType type, const char* ptr, size_t length);
+
WritableFile* dest_;
- int block_offset_; // Current offset in block
+ int block_offset_; // Current offset in block
// crc32c values for all supported record types. These are
// pre-computed to reduce the overhead of computing the crc of the
// record type stored in the header.
uint32_t type_crc_[kMaxRecordType + 1];
-
- Status EmitPhysicalRecord(RecordType type, const char* ptr, size_t length);
-
- // No copying allowed
- Writer(const Writer&);
- void operator=(const Writer&);
};
} // namespace log
diff --git a/src/leveldb/db/memtable.cc b/src/leveldb/db/memtable.cc
index 287afdbdcb..00931d4671 100644
--- a/src/leveldb/db/memtable.cc
+++ b/src/leveldb/db/memtable.cc
@@ -18,20 +18,15 @@ static Slice GetLengthPrefixedSlice(const char* data) {
return Slice(p, len);
}
-MemTable::MemTable(const InternalKeyComparator& cmp)
- : comparator_(cmp),
- refs_(0),
- table_(comparator_, &arena_) {
-}
+MemTable::MemTable(const InternalKeyComparator& comparator)
+ : comparator_(comparator), refs_(0), table_(comparator_, &arena_) {}
-MemTable::~MemTable() {
- assert(refs_ == 0);
-}
+MemTable::~MemTable() { assert(refs_ == 0); }
size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); }
-int MemTable::KeyComparator::operator()(const char* aptr, const char* bptr)
- const {
+int MemTable::KeyComparator::operator()(const char* aptr,
+ const char* bptr) const {
// Internal keys are encoded as length-prefixed strings.
Slice a = GetLengthPrefixedSlice(aptr);
Slice b = GetLengthPrefixedSlice(bptr);
@@ -48,39 +43,37 @@ static const char* EncodeKey(std::string* scratch, const Slice& target) {
return scratch->data();
}
-class MemTableIterator: public Iterator {
+class MemTableIterator : public Iterator {
public:
- explicit MemTableIterator(MemTable::Table* table) : iter_(table) { }
-
- virtual bool Valid() const { return iter_.Valid(); }
- virtual void Seek(const Slice& k) { iter_.Seek(EncodeKey(&tmp_, k)); }
- virtual void SeekToFirst() { iter_.SeekToFirst(); }
- virtual void SeekToLast() { iter_.SeekToLast(); }
- virtual void Next() { iter_.Next(); }
- virtual void Prev() { iter_.Prev(); }
- virtual Slice key() const { return GetLengthPrefixedSlice(iter_.key()); }
- virtual Slice value() const {
+ explicit MemTableIterator(MemTable::Table* table) : iter_(table) {}
+
+ MemTableIterator(const MemTableIterator&) = delete;
+ MemTableIterator& operator=(const MemTableIterator&) = delete;
+
+ ~MemTableIterator() override = default;
+
+ bool Valid() const override { return iter_.Valid(); }
+ void Seek(const Slice& k) override { iter_.Seek(EncodeKey(&tmp_, k)); }
+ void SeekToFirst() override { iter_.SeekToFirst(); }
+ void SeekToLast() override { iter_.SeekToLast(); }
+ void Next() override { iter_.Next(); }
+ void Prev() override { iter_.Prev(); }
+ Slice key() const override { return GetLengthPrefixedSlice(iter_.key()); }
+ Slice value() const override {
Slice key_slice = GetLengthPrefixedSlice(iter_.key());
return GetLengthPrefixedSlice(key_slice.data() + key_slice.size());
}
- virtual Status status() const { return Status::OK(); }
+ Status status() const override { return Status::OK(); }
private:
MemTable::Table::Iterator iter_;
- std::string tmp_; // For passing to EncodeKey
-
- // No copying allowed
- MemTableIterator(const MemTableIterator&);
- void operator=(const MemTableIterator&);
+ std::string tmp_; // For passing to EncodeKey
};
-Iterator* MemTable::NewIterator() {
- return new MemTableIterator(&table_);
-}
+Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); }
-void MemTable::Add(SequenceNumber s, ValueType type,
- const Slice& key,
+void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key,
const Slice& value) {
// Format of an entry is concatenation of:
// key_size : varint32 of internal_key.size()
@@ -90,9 +83,9 @@ void MemTable::Add(SequenceNumber s, ValueType type,
size_t key_size = key.size();
size_t val_size = value.size();
size_t internal_key_size = key_size + 8;
- const size_t encoded_len =
- VarintLength(internal_key_size) + internal_key_size +
- VarintLength(val_size) + val_size;
+ const size_t encoded_len = VarintLength(internal_key_size) +
+ internal_key_size + VarintLength(val_size) +
+ val_size;
char* buf = arena_.Allocate(encoded_len);
char* p = EncodeVarint32(buf, internal_key_size);
memcpy(p, key.data(), key_size);
@@ -121,10 +114,9 @@ bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
// all entries with overly large sequence numbers.
const char* entry = iter.key();
uint32_t key_length;
- const char* key_ptr = GetVarint32Ptr(entry, entry+5, &key_length);
+ const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length);
if (comparator_.comparator.user_comparator()->Compare(
- Slice(key_ptr, key_length - 8),
- key.user_key()) == 0) {
+ Slice(key_ptr, key_length - 8), key.user_key()) == 0) {
// Correct user key
const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
switch (static_cast<ValueType>(tag & 0xff)) {
diff --git a/src/leveldb/db/memtable.h b/src/leveldb/db/memtable.h
index 9f41567cde..9d986b1070 100644
--- a/src/leveldb/db/memtable.h
+++ b/src/leveldb/db/memtable.h
@@ -6,15 +6,15 @@
#define STORAGE_LEVELDB_DB_MEMTABLE_H_
#include <string>
-#include "leveldb/db.h"
+
#include "db/dbformat.h"
#include "db/skiplist.h"
+#include "leveldb/db.h"
#include "util/arena.h"
namespace leveldb {
class InternalKeyComparator;
-class Mutex;
class MemTableIterator;
class MemTable {
@@ -23,6 +23,9 @@ class MemTable {
// is zero and the caller must call Ref() at least once.
explicit MemTable(const InternalKeyComparator& comparator);
+ MemTable(const MemTable&) = delete;
+ MemTable& operator=(const MemTable&) = delete;
+
// Increase reference count.
void Ref() { ++refs_; }
@@ -50,8 +53,7 @@ class MemTable {
// Add an entry into memtable that maps key to value at the
// specified sequence number and with the specified type.
// Typically value will be empty if type==kTypeDeletion.
- void Add(SequenceNumber seq, ValueType type,
- const Slice& key,
+ void Add(SequenceNumber seq, ValueType type, const Slice& key,
const Slice& value);
// If memtable contains a value for key, store it in *value and return true.
@@ -61,26 +63,23 @@ class MemTable {
bool Get(const LookupKey& key, std::string* value, Status* s);
private:
- ~MemTable(); // Private since only Unref() should be used to delete it
+ friend class MemTableIterator;
+ friend class MemTableBackwardIterator;
struct KeyComparator {
const InternalKeyComparator comparator;
- explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { }
+ explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) {}
int operator()(const char* a, const char* b) const;
};
- friend class MemTableIterator;
- friend class MemTableBackwardIterator;
typedef SkipList<const char*, KeyComparator> Table;
+ ~MemTable(); // Private since only Unref() should be used to delete it
+
KeyComparator comparator_;
int refs_;
Arena arena_;
Table table_;
-
- // No copying allowed
- MemTable(const MemTable&);
- void operator=(const MemTable&);
};
} // namespace leveldb
diff --git a/src/leveldb/db/recovery_test.cc b/src/leveldb/db/recovery_test.cc
index 9596f4288a..547a9591ea 100644
--- a/src/leveldb/db/recovery_test.cc
+++ b/src/leveldb/db/recovery_test.cc
@@ -17,7 +17,7 @@ namespace leveldb {
class RecoveryTest {
public:
- RecoveryTest() : env_(Env::Default()), db_(NULL) {
+ RecoveryTest() : env_(Env::Default()), db_(nullptr) {
dbname_ = test::TmpDir() + "/recovery_test";
DestroyDB(dbname_, Options());
Open();
@@ -44,22 +44,26 @@ class RecoveryTest {
void Close() {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
}
- void Open(Options* options = NULL) {
+ Status OpenWithStatus(Options* options = nullptr) {
Close();
Options opts;
- if (options != NULL) {
+ if (options != nullptr) {
opts = *options;
} else {
opts.reuse_logs = true; // TODO(sanjay): test both ways
opts.create_if_missing = true;
}
- if (opts.env == NULL) {
+ if (opts.env == nullptr) {
opts.env = env_;
}
- ASSERT_OK(DB::Open(opts, dbname_, &db_));
+ return DB::Open(opts, dbname_, &db_);
+ }
+
+ void Open(Options* options = nullptr) {
+ ASSERT_OK(OpenWithStatus(options));
ASSERT_EQ(1, NumLogs());
}
@@ -67,7 +71,7 @@ class RecoveryTest {
return db_->Put(WriteOptions(), k, v);
}
- std::string Get(const std::string& k, const Snapshot* snapshot = NULL) {
+ std::string Get(const std::string& k, const Snapshot* snapshot = nullptr) {
std::string result;
Status s = db_->Get(ReadOptions(), k, &result);
if (s.IsNotFound()) {
@@ -82,17 +86,18 @@ class RecoveryTest {
std::string current;
ASSERT_OK(ReadFileToString(env_, CurrentFileName(dbname_), &current));
size_t len = current.size();
- if (len > 0 && current[len-1] == '\n') {
+ if (len > 0 && current[len - 1] == '\n') {
current.resize(len - 1);
}
return dbname_ + "/" + current;
}
- std::string LogName(uint64_t number) {
- return LogFileName(dbname_, number);
- }
+ std::string LogName(uint64_t number) { return LogFileName(dbname_, number); }
size_t DeleteLogFiles() {
+ // Linux allows unlinking open files, but Windows does not.
+ // Closing the db allows for file deletion.
+ Close();
std::vector<uint64_t> logs = GetFiles(kLogFile);
for (size_t i = 0; i < logs.size(); i++) {
ASSERT_OK(env_->DeleteFile(LogName(logs[i]))) << LogName(logs[i]);
@@ -100,9 +105,9 @@ class RecoveryTest {
return logs.size();
}
- uint64_t FirstLogFile() {
- return GetFiles(kLogFile)[0];
- }
+ void DeleteManifestFile() { ASSERT_OK(env_->DeleteFile(ManifestFileName())); }
+
+ uint64_t FirstLogFile() { return GetFiles(kLogFile)[0]; }
std::vector<uint64_t> GetFiles(FileType t) {
std::vector<std::string> filenames;
@@ -118,13 +123,9 @@ class RecoveryTest {
return result;
}
- int NumLogs() {
- return GetFiles(kLogFile).size();
- }
+ int NumLogs() { return GetFiles(kLogFile).size(); }
- int NumTables() {
- return GetFiles(kTableFile).size();
- }
+ int NumTables() { return GetFiles(kTableFile).size(); }
uint64_t FileSize(const std::string& fname) {
uint64_t result;
@@ -132,9 +133,7 @@ class RecoveryTest {
return result;
}
- void CompactMemTable() {
- dbfull()->TEST_CompactMemTable();
- }
+ void CompactMemTable() { dbfull()->TEST_CompactMemTable(); }
// Directly construct a log file that sets key to val.
void MakeLogFile(uint64_t lognum, SequenceNumber seq, Slice key, Slice val) {
@@ -186,7 +185,7 @@ TEST(RecoveryTest, LargeManifestCompacted) {
uint64_t len = FileSize(old_manifest);
WritableFile* file;
ASSERT_OK(env()->NewAppendableFile(old_manifest, &file));
- std::string zeroes(3*1048576 - static_cast<size_t>(len), 0);
+ std::string zeroes(3 * 1048576 - static_cast<size_t>(len), 0);
ASSERT_OK(file->Append(zeroes));
ASSERT_OK(file->Flush());
delete file;
@@ -259,7 +258,7 @@ TEST(RecoveryTest, MultipleMemTables) {
// Force creation of multiple memtables by reducing the write buffer size.
Options opt;
opt.reuse_logs = true;
- opt.write_buffer_size = (kNum*100) / 2;
+ opt.write_buffer_size = (kNum * 100) / 2;
Open(&opt);
ASSERT_LE(2, NumTables());
ASSERT_EQ(1, NumLogs());
@@ -278,16 +277,16 @@ TEST(RecoveryTest, MultipleLogFiles) {
// Make a bunch of uncompacted log files.
uint64_t old_log = FirstLogFile();
- MakeLogFile(old_log+1, 1000, "hello", "world");
- MakeLogFile(old_log+2, 1001, "hi", "there");
- MakeLogFile(old_log+3, 1002, "foo", "bar2");
+ MakeLogFile(old_log + 1, 1000, "hello", "world");
+ MakeLogFile(old_log + 2, 1001, "hi", "there");
+ MakeLogFile(old_log + 3, 1002, "foo", "bar2");
// Recover and check that all log files were processed.
Open();
ASSERT_LE(1, NumTables());
ASSERT_EQ(1, NumLogs());
uint64_t new_log = FirstLogFile();
- ASSERT_LE(old_log+3, new_log);
+ ASSERT_LE(old_log + 3, new_log);
ASSERT_EQ("bar2", Get("foo"));
ASSERT_EQ("world", Get("hello"));
ASSERT_EQ("there", Get("hi"));
@@ -305,7 +304,7 @@ TEST(RecoveryTest, MultipleLogFiles) {
// Check that introducing an older log file does not cause it to be re-read.
Close();
- MakeLogFile(old_log+1, 2000, "hello", "stale write");
+ MakeLogFile(old_log + 1, 2000, "hello", "stale write");
Open();
ASSERT_LE(1, NumTables());
ASSERT_EQ(1, NumLogs());
@@ -317,8 +316,15 @@ TEST(RecoveryTest, MultipleLogFiles) {
ASSERT_EQ("there", Get("hi"));
}
-} // namespace leveldb
+TEST(RecoveryTest, ManifestMissing) {
+ ASSERT_OK(Put("foo", "bar"));
+ Close();
+ DeleteManifestFile();
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
+ Status status = OpenWithStatus();
+ ASSERT_TRUE(status.IsCorruption());
}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/repair.cc b/src/leveldb/db/repair.cc
index 7281e3d345..04847c3bbf 100644
--- a/src/leveldb/db/repair.cc
+++ b/src/leveldb/db/repair.cc
@@ -54,7 +54,7 @@ class Repairer {
owns_cache_(options_.block_cache != options.block_cache),
next_file_number_(1) {
// TableCache can be small since we expect each table to be opened once.
- table_cache_ = new TableCache(dbname_, &options_, 10);
+ table_cache_ = new TableCache(dbname_, options_, 10);
}
~Repairer() {
@@ -84,9 +84,7 @@ class Repairer {
"recovered %d files; %llu bytes. "
"Some data may have been lost. "
"****",
- dbname_.c_str(),
- static_cast<int>(tables_.size()),
- bytes);
+ dbname_.c_str(), static_cast<int>(tables_.size()), bytes);
}
return status;
}
@@ -97,22 +95,6 @@ class Repairer {
SequenceNumber max_sequence;
};
- std::string const dbname_;
- Env* const env_;
- InternalKeyComparator const icmp_;
- InternalFilterPolicy const ipolicy_;
- Options const options_;
- bool owns_info_log_;
- bool owns_cache_;
- TableCache* table_cache_;
- VersionEdit edit_;
-
- std::vector<std::string> manifests_;
- std::vector<uint64_t> table_numbers_;
- std::vector<uint64_t> logs_;
- std::vector<TableInfo> tables_;
- uint64_t next_file_number_;
-
Status FindFiles() {
std::vector<std::string> filenames;
Status status = env_->GetChildren(dbname_, &filenames);
@@ -152,8 +134,7 @@ class Repairer {
Status status = ConvertLogToTable(logs_[i]);
if (!status.ok()) {
Log(options_.info_log, "Log #%llu: ignoring conversion error: %s",
- (unsigned long long) logs_[i],
- status.ToString().c_str());
+ (unsigned long long)logs_[i], status.ToString().c_str());
}
ArchiveFile(logname);
}
@@ -164,11 +145,10 @@ class Repairer {
Env* env;
Logger* info_log;
uint64_t lognum;
- virtual void Corruption(size_t bytes, const Status& s) {
+ void Corruption(size_t bytes, const Status& s) override {
// We print error messages for corruption, but continue repairing.
Log(info_log, "Log #%llu: dropping %d bytes; %s",
- (unsigned long long) lognum,
- static_cast<int>(bytes),
+ (unsigned long long)lognum, static_cast<int>(bytes),
s.ToString().c_str());
}
};
@@ -190,8 +170,8 @@ class Repairer {
// corruptions cause entire commits to be skipped instead of
// propagating bad information (like overly large sequence
// numbers).
- log::Reader reader(lfile, &reporter, false/*do not checksum*/,
- 0/*initial_offset*/);
+ log::Reader reader(lfile, &reporter, false /*do not checksum*/,
+ 0 /*initial_offset*/);
// Read all the records and add to a memtable
std::string scratch;
@@ -202,8 +182,8 @@ class Repairer {
int counter = 0;
while (reader.ReadRecord(&record, &scratch)) {
if (record.size() < 12) {
- reporter.Corruption(
- record.size(), Status::Corruption("log record too small", logname));
+ reporter.Corruption(record.size(),
+ Status::Corruption("log record too small", logname));
continue;
}
WriteBatchInternal::SetContents(&batch, record);
@@ -212,8 +192,7 @@ class Repairer {
counter += WriteBatchInternal::Count(&batch);
} else {
Log(options_.info_log, "Log #%llu: ignoring %s",
- (unsigned long long) log,
- status.ToString().c_str());
+ (unsigned long long)log, status.ToString().c_str());
status = Status::OK(); // Keep going with rest of file
}
}
@@ -227,16 +206,14 @@ class Repairer {
status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta);
delete iter;
mem->Unref();
- mem = NULL;
+ mem = nullptr;
if (status.ok()) {
if (meta.file_size > 0) {
table_numbers_.push_back(meta.number);
}
}
Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s",
- (unsigned long long) log,
- counter,
- (unsigned long long) meta.number,
+ (unsigned long long)log, counter, (unsigned long long)meta.number,
status.ToString().c_str());
return status;
}
@@ -272,8 +249,7 @@ class Repairer {
ArchiveFile(TableFileName(dbname_, number));
ArchiveFile(SSTTableFileName(dbname_, number));
Log(options_.info_log, "Table #%llu: dropped: %s",
- (unsigned long long) t.meta.number,
- status.ToString().c_str());
+ (unsigned long long)t.meta.number, status.ToString().c_str());
return;
}
@@ -287,8 +263,7 @@ class Repairer {
Slice key = iter->key();
if (!ParseInternalKey(key, &parsed)) {
Log(options_.info_log, "Table #%llu: unparsable key %s",
- (unsigned long long) t.meta.number,
- EscapeString(key).c_str());
+ (unsigned long long)t.meta.number, EscapeString(key).c_str());
continue;
}
@@ -307,9 +282,7 @@ class Repairer {
}
delete iter;
Log(options_.info_log, "Table #%llu: %d entries %s",
- (unsigned long long) t.meta.number,
- counter,
- status.ToString().c_str());
+ (unsigned long long)t.meta.number, counter, status.ToString().c_str());
if (status.ok()) {
tables_.push_back(t);
@@ -350,20 +323,20 @@ class Repairer {
}
}
delete builder;
- builder = NULL;
+ builder = nullptr;
if (s.ok()) {
s = file->Close();
}
delete file;
- file = NULL;
+ file = nullptr;
if (counter > 0 && s.ok()) {
std::string orig = TableFileName(dbname_, t.meta.number);
s = env_->RenameFile(copy, orig);
if (s.ok()) {
Log(options_.info_log, "Table #%llu: %d entries repaired",
- (unsigned long long) t.meta.number, counter);
+ (unsigned long long)t.meta.number, counter);
tables_.push_back(t);
}
}
@@ -395,11 +368,11 @@ class Repairer {
for (size_t i = 0; i < tables_.size(); i++) {
// TODO(opt): separate out into multiple levels
const TableInfo& t = tables_[i];
- edit_.AddFile(0, t.meta.number, t.meta.file_size,
- t.meta.smallest, t.meta.largest);
+ edit_.AddFile(0, t.meta.number, t.meta.file_size, t.meta.smallest,
+ t.meta.largest);
}
- //fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str());
+ // fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str());
{
log::Writer log(file);
std::string record;
@@ -410,7 +383,7 @@ class Repairer {
status = file->Close();
}
delete file;
- file = NULL;
+ file = nullptr;
if (!status.ok()) {
env_->DeleteFile(tmp);
@@ -438,18 +411,34 @@ class Repairer {
// dir/lost/foo
const char* slash = strrchr(fname.c_str(), '/');
std::string new_dir;
- if (slash != NULL) {
+ if (slash != nullptr) {
new_dir.assign(fname.data(), slash - fname.data());
}
new_dir.append("/lost");
env_->CreateDir(new_dir); // Ignore error
std::string new_file = new_dir;
new_file.append("/");
- new_file.append((slash == NULL) ? fname.c_str() : slash + 1);
+ new_file.append((slash == nullptr) ? fname.c_str() : slash + 1);
Status s = env_->RenameFile(fname, new_file);
- Log(options_.info_log, "Archiving %s: %s\n",
- fname.c_str(), s.ToString().c_str());
+ Log(options_.info_log, "Archiving %s: %s\n", fname.c_str(),
+ s.ToString().c_str());
}
+
+ const std::string dbname_;
+ Env* const env_;
+ InternalKeyComparator const icmp_;
+ InternalFilterPolicy const ipolicy_;
+ const Options options_;
+ bool owns_info_log_;
+ bool owns_cache_;
+ TableCache* table_cache_;
+ VersionEdit edit_;
+
+ std::vector<std::string> manifests_;
+ std::vector<uint64_t> table_numbers_;
+ std::vector<uint64_t> logs_;
+ std::vector<TableInfo> tables_;
+ uint64_t next_file_number_;
};
} // namespace
diff --git a/src/leveldb/db/skiplist.h b/src/leveldb/db/skiplist.h
index 8bd77764d8..a59b45b380 100644
--- a/src/leveldb/db/skiplist.h
+++ b/src/leveldb/db/skiplist.h
@@ -27,9 +27,10 @@
//
// ... prev vs. next pointer ordering ...
-#include <assert.h>
-#include <stdlib.h>
-#include "port/port.h"
+#include <atomic>
+#include <cassert>
+#include <cstdlib>
+
#include "util/arena.h"
#include "util/random.h"
@@ -37,7 +38,7 @@ namespace leveldb {
class Arena;
-template<typename Key, class Comparator>
+template <typename Key, class Comparator>
class SkipList {
private:
struct Node;
@@ -48,6 +49,9 @@ class SkipList {
// must remain allocated for the lifetime of the skiplist object.
explicit SkipList(Comparator cmp, Arena* arena);
+ SkipList(const SkipList&) = delete;
+ SkipList& operator=(const SkipList&) = delete;
+
// Insert key into the list.
// REQUIRES: nothing that compares equal to key is currently in the list.
void Insert(const Key& key);
@@ -97,24 +101,10 @@ class SkipList {
private:
enum { kMaxHeight = 12 };
- // Immutable after construction
- Comparator const compare_;
- Arena* const arena_; // Arena used for allocations of nodes
-
- Node* const head_;
-
- // Modified only by Insert(). Read racily by readers, but stale
- // values are ok.
- port::AtomicPointer max_height_; // Height of the entire list
-
inline int GetMaxHeight() const {
- return static_cast<int>(
- reinterpret_cast<intptr_t>(max_height_.NoBarrier_Load()));
+ return max_height_.load(std::memory_order_relaxed);
}
- // Read/written only by Insert().
- Random rnd_;
-
Node* NewNode(const Key& key, int height);
int RandomHeight();
bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); }
@@ -123,9 +113,9 @@ class SkipList {
bool KeyIsAfterNode(const Key& key, Node* n) const;
// Return the earliest node that comes at or after key.
- // Return NULL if there is no such node.
+ // Return nullptr if there is no such node.
//
- // If prev is non-NULL, fills prev[level] with pointer to previous
+ // If prev is non-null, fills prev[level] with pointer to previous
// node at "level" for every level in [0..max_height_-1].
Node* FindGreaterOrEqual(const Key& key, Node** prev) const;
@@ -137,15 +127,24 @@ class SkipList {
// Return head_ if list is empty.
Node* FindLast() const;
- // No copying allowed
- SkipList(const SkipList&);
- void operator=(const SkipList&);
+ // Immutable after construction
+ Comparator const compare_;
+ Arena* const arena_; // Arena used for allocations of nodes
+
+ Node* const head_;
+
+ // Modified only by Insert(). Read racily by readers, but stale
+ // values are ok.
+ std::atomic<int> max_height_; // Height of the entire list
+
+ // Read/written only by Insert().
+ Random rnd_;
};
// Implementation details follow
-template<typename Key, class Comparator>
-struct SkipList<Key,Comparator>::Node {
- explicit Node(const Key& k) : key(k) { }
+template <typename Key, class Comparator>
+struct SkipList<Key, Comparator>::Node {
+ explicit Node(const Key& k) : key(k) {}
Key const key;
@@ -155,92 +154,92 @@ struct SkipList<Key,Comparator>::Node {
assert(n >= 0);
// Use an 'acquire load' so that we observe a fully initialized
// version of the returned Node.
- return reinterpret_cast<Node*>(next_[n].Acquire_Load());
+ return next_[n].load(std::memory_order_acquire);
}
void SetNext(int n, Node* x) {
assert(n >= 0);
// Use a 'release store' so that anybody who reads through this
// pointer observes a fully initialized version of the inserted node.
- next_[n].Release_Store(x);
+ next_[n].store(x, std::memory_order_release);
}
// No-barrier variants that can be safely used in a few locations.
Node* NoBarrier_Next(int n) {
assert(n >= 0);
- return reinterpret_cast<Node*>(next_[n].NoBarrier_Load());
+ return next_[n].load(std::memory_order_relaxed);
}
void NoBarrier_SetNext(int n, Node* x) {
assert(n >= 0);
- next_[n].NoBarrier_Store(x);
+ next_[n].store(x, std::memory_order_relaxed);
}
private:
// Array of length equal to the node height. next_[0] is lowest level link.
- port::AtomicPointer next_[1];
+ std::atomic<Node*> next_[1];
};
-template<typename Key, class Comparator>
-typename SkipList<Key,Comparator>::Node*
-SkipList<Key,Comparator>::NewNode(const Key& key, int height) {
- char* mem = arena_->AllocateAligned(
- sizeof(Node) + sizeof(port::AtomicPointer) * (height - 1));
- return new (mem) Node(key);
+template <typename Key, class Comparator>
+typename SkipList<Key, Comparator>::Node* SkipList<Key, Comparator>::NewNode(
+ const Key& key, int height) {
+ char* const node_memory = arena_->AllocateAligned(
+ sizeof(Node) + sizeof(std::atomic<Node*>) * (height - 1));
+ return new (node_memory) Node(key);
}
-template<typename Key, class Comparator>
-inline SkipList<Key,Comparator>::Iterator::Iterator(const SkipList* list) {
+template <typename Key, class Comparator>
+inline SkipList<Key, Comparator>::Iterator::Iterator(const SkipList* list) {
list_ = list;
- node_ = NULL;
+ node_ = nullptr;
}
-template<typename Key, class Comparator>
-inline bool SkipList<Key,Comparator>::Iterator::Valid() const {
- return node_ != NULL;
+template <typename Key, class Comparator>
+inline bool SkipList<Key, Comparator>::Iterator::Valid() const {
+ return node_ != nullptr;
}
-template<typename Key, class Comparator>
-inline const Key& SkipList<Key,Comparator>::Iterator::key() const {
+template <typename Key, class Comparator>
+inline const Key& SkipList<Key, Comparator>::Iterator::key() const {
assert(Valid());
return node_->key;
}
-template<typename Key, class Comparator>
-inline void SkipList<Key,Comparator>::Iterator::Next() {
+template <typename Key, class Comparator>
+inline void SkipList<Key, Comparator>::Iterator::Next() {
assert(Valid());
node_ = node_->Next(0);
}
-template<typename Key, class Comparator>
-inline void SkipList<Key,Comparator>::Iterator::Prev() {
+template <typename Key, class Comparator>
+inline void SkipList<Key, Comparator>::Iterator::Prev() {
// Instead of using explicit "prev" links, we just search for the
// last node that falls before key.
assert(Valid());
node_ = list_->FindLessThan(node_->key);
if (node_ == list_->head_) {
- node_ = NULL;
+ node_ = nullptr;
}
}
-template<typename Key, class Comparator>
-inline void SkipList<Key,Comparator>::Iterator::Seek(const Key& target) {
- node_ = list_->FindGreaterOrEqual(target, NULL);
+template <typename Key, class Comparator>
+inline void SkipList<Key, Comparator>::Iterator::Seek(const Key& target) {
+ node_ = list_->FindGreaterOrEqual(target, nullptr);
}
-template<typename Key, class Comparator>
-inline void SkipList<Key,Comparator>::Iterator::SeekToFirst() {
+template <typename Key, class Comparator>
+inline void SkipList<Key, Comparator>::Iterator::SeekToFirst() {
node_ = list_->head_->Next(0);
}
-template<typename Key, class Comparator>
-inline void SkipList<Key,Comparator>::Iterator::SeekToLast() {
+template <typename Key, class Comparator>
+inline void SkipList<Key, Comparator>::Iterator::SeekToLast() {
node_ = list_->FindLast();
if (node_ == list_->head_) {
- node_ = NULL;
+ node_ = nullptr;
}
}
-template<typename Key, class Comparator>
-int SkipList<Key,Comparator>::RandomHeight() {
+template <typename Key, class Comparator>
+int SkipList<Key, Comparator>::RandomHeight() {
// Increase height with probability 1 in kBranching
static const unsigned int kBranching = 4;
int height = 1;
@@ -252,15 +251,16 @@ int SkipList<Key,Comparator>::RandomHeight() {
return height;
}
-template<typename Key, class Comparator>
-bool SkipList<Key,Comparator>::KeyIsAfterNode(const Key& key, Node* n) const {
- // NULL n is considered infinite
- return (n != NULL) && (compare_(n->key, key) < 0);
+template <typename Key, class Comparator>
+bool SkipList<Key, Comparator>::KeyIsAfterNode(const Key& key, Node* n) const {
+ // null n is considered infinite
+ return (n != nullptr) && (compare_(n->key, key) < 0);
}
-template<typename Key, class Comparator>
-typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOrEqual(const Key& key, Node** prev)
- const {
+template <typename Key, class Comparator>
+typename SkipList<Key, Comparator>::Node*
+SkipList<Key, Comparator>::FindGreaterOrEqual(const Key& key,
+ Node** prev) const {
Node* x = head_;
int level = GetMaxHeight() - 1;
while (true) {
@@ -269,7 +269,7 @@ typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOr
// Keep searching in this list
x = next;
} else {
- if (prev != NULL) prev[level] = x;
+ if (prev != nullptr) prev[level] = x;
if (level == 0) {
return next;
} else {
@@ -280,15 +280,15 @@ typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOr
}
}
-template<typename Key, class Comparator>
-typename SkipList<Key,Comparator>::Node*
-SkipList<Key,Comparator>::FindLessThan(const Key& key) const {
+template <typename Key, class Comparator>
+typename SkipList<Key, Comparator>::Node*
+SkipList<Key, Comparator>::FindLessThan(const Key& key) const {
Node* x = head_;
int level = GetMaxHeight() - 1;
while (true) {
assert(x == head_ || compare_(x->key, key) < 0);
Node* next = x->Next(level);
- if (next == NULL || compare_(next->key, key) >= 0) {
+ if (next == nullptr || compare_(next->key, key) >= 0) {
if (level == 0) {
return x;
} else {
@@ -301,14 +301,14 @@ SkipList<Key,Comparator>::FindLessThan(const Key& key) const {
}
}
-template<typename Key, class Comparator>
-typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindLast()
+template <typename Key, class Comparator>
+typename SkipList<Key, Comparator>::Node* SkipList<Key, Comparator>::FindLast()
const {
Node* x = head_;
int level = GetMaxHeight() - 1;
while (true) {
Node* next = x->Next(level);
- if (next == NULL) {
+ if (next == nullptr) {
if (level == 0) {
return x;
} else {
@@ -321,43 +321,41 @@ typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindLast()
}
}
-template<typename Key, class Comparator>
-SkipList<Key,Comparator>::SkipList(Comparator cmp, Arena* arena)
+template <typename Key, class Comparator>
+SkipList<Key, Comparator>::SkipList(Comparator cmp, Arena* arena)
: compare_(cmp),
arena_(arena),
head_(NewNode(0 /* any key will do */, kMaxHeight)),
- max_height_(reinterpret_cast<void*>(1)),
+ max_height_(1),
rnd_(0xdeadbeef) {
for (int i = 0; i < kMaxHeight; i++) {
- head_->SetNext(i, NULL);
+ head_->SetNext(i, nullptr);
}
}
-template<typename Key, class Comparator>
-void SkipList<Key,Comparator>::Insert(const Key& key) {
+template <typename Key, class Comparator>
+void SkipList<Key, Comparator>::Insert(const Key& key) {
// TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual()
// here since Insert() is externally synchronized.
Node* prev[kMaxHeight];
Node* x = FindGreaterOrEqual(key, prev);
// Our data structure does not allow duplicate insertion
- assert(x == NULL || !Equal(key, x->key));
+ assert(x == nullptr || !Equal(key, x->key));
int height = RandomHeight();
if (height > GetMaxHeight()) {
for (int i = GetMaxHeight(); i < height; i++) {
prev[i] = head_;
}
- //fprintf(stderr, "Change height from %d to %d\n", max_height_, height);
-
// It is ok to mutate max_height_ without any synchronization
// with concurrent readers. A concurrent reader that observes
// the new value of max_height_ will see either the old value of
- // new level pointers from head_ (NULL), or a new value set in
+ // new level pointers from head_ (nullptr), or a new value set in
// the loop below. In the former case the reader will
- // immediately drop to the next level since NULL sorts after all
+ // immediately drop to the next level since nullptr sorts after all
// keys. In the latter case the reader will use the new node.
- max_height_.NoBarrier_Store(reinterpret_cast<void*>(height));
+ max_height_.store(height, std::memory_order_relaxed);
}
x = NewNode(key, height);
@@ -369,10 +367,10 @@ void SkipList<Key,Comparator>::Insert(const Key& key) {
}
}
-template<typename Key, class Comparator>
-bool SkipList<Key,Comparator>::Contains(const Key& key) const {
- Node* x = FindGreaterOrEqual(key, NULL);
- if (x != NULL && Equal(key, x->key)) {
+template <typename Key, class Comparator>
+bool SkipList<Key, Comparator>::Contains(const Key& key) const {
+ Node* x = FindGreaterOrEqual(key, nullptr);
+ if (x != nullptr && Equal(key, x->key)) {
return true;
} else {
return false;
diff --git a/src/leveldb/db/skiplist_test.cc b/src/leveldb/db/skiplist_test.cc
index aee1461e1b..9fa2d96829 100644
--- a/src/leveldb/db/skiplist_test.cc
+++ b/src/leveldb/db/skiplist_test.cc
@@ -3,8 +3,13 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "db/skiplist.h"
+
+#include <atomic>
#include <set>
+
#include "leveldb/env.h"
+#include "port/port.h"
+#include "port/thread_annotations.h"
#include "util/arena.h"
#include "util/hash.h"
#include "util/random.h"
@@ -26,7 +31,7 @@ struct Comparator {
}
};
-class SkipTest { };
+class SkipTest {};
TEST(SkipTest, Empty) {
Arena arena;
@@ -112,8 +117,7 @@ TEST(SkipTest, InsertAndLookup) {
// Compare against model iterator
for (std::set<Key>::reverse_iterator model_iter = keys.rbegin();
- model_iter != keys.rend();
- ++model_iter) {
+ model_iter != keys.rend(); ++model_iter) {
ASSERT_TRUE(iter.Valid());
ASSERT_EQ(*model_iter, iter.key());
iter.Prev();
@@ -126,7 +130,7 @@ TEST(SkipTest, InsertAndLookup) {
// concurrent readers (with no synchronization other than when a
// reader's iterator is created), the reader always observes all the
// data that was present in the skip list when the iterator was
-// constructor. Because insertions are happening concurrently, we may
+// constructed. Because insertions are happening concurrently, we may
// also observe new values that were inserted since the iterator was
// constructed, but we should never miss any values that were present
// at iterator construction time.
@@ -155,12 +159,12 @@ class ConcurrentTest {
static uint64_t hash(Key key) { return key & 0xff; }
static uint64_t HashNumbers(uint64_t k, uint64_t g) {
- uint64_t data[2] = { k, g };
+ uint64_t data[2] = {k, g};
return Hash(reinterpret_cast<char*>(data), sizeof(data), 0);
}
static Key MakeKey(uint64_t k, uint64_t g) {
- assert(sizeof(Key) == sizeof(uint64_t));
+ static_assert(sizeof(Key) == sizeof(uint64_t), "");
assert(k <= K); // We sometimes pass K to seek to the end of the skiplist
assert(g <= 0xffffffffu);
return ((k << 40) | (g << 8) | (HashNumbers(k, g) & 0xff));
@@ -186,13 +190,11 @@ class ConcurrentTest {
// Per-key generation
struct State {
- port::AtomicPointer generation[K];
- void Set(int k, intptr_t v) {
- generation[k].Release_Store(reinterpret_cast<void*>(v));
- }
- intptr_t Get(int k) {
- return reinterpret_cast<intptr_t>(generation[k].Acquire_Load());
+ std::atomic<int> generation[K];
+ void Set(int k, int v) {
+ generation[k].store(v, std::memory_order_release);
}
+ int Get(int k) { return generation[k].load(std::memory_order_acquire); }
State() {
for (int k = 0; k < K; k++) {
@@ -211,7 +213,7 @@ class ConcurrentTest {
SkipList<Key, Comparator> list_;
public:
- ConcurrentTest() : list_(Comparator(), &arena_) { }
+ ConcurrentTest() : list_(Comparator(), &arena_) {}
// REQUIRES: External synchronization
void WriteStep(Random* rnd) {
@@ -250,11 +252,9 @@ class ConcurrentTest {
// Note that generation 0 is never inserted, so it is ok if
// <*,0,*> is missing.
ASSERT_TRUE((gen(pos) == 0) ||
- (gen(pos) > static_cast<Key>(initial_state.Get(key(pos))))
- ) << "key: " << key(pos)
- << "; gen: " << gen(pos)
- << "; initgen: "
- << initial_state.Get(key(pos));
+ (gen(pos) > static_cast<Key>(initial_state.Get(key(pos)))))
+ << "key: " << key(pos) << "; gen: " << gen(pos)
+ << "; initgen: " << initial_state.Get(key(pos));
// Advance to next key in the valid key space
if (key(pos) < key(current)) {
@@ -298,21 +298,14 @@ class TestState {
public:
ConcurrentTest t_;
int seed_;
- port::AtomicPointer quit_flag_;
+ std::atomic<bool> quit_flag_;
- enum ReaderState {
- STARTING,
- RUNNING,
- DONE
- };
+ enum ReaderState { STARTING, RUNNING, DONE };
explicit TestState(int s)
- : seed_(s),
- quit_flag_(NULL),
- state_(STARTING),
- state_cv_(&mu_) {}
+ : seed_(s), quit_flag_(false), state_(STARTING), state_cv_(&mu_) {}
- void Wait(ReaderState s) {
+ void Wait(ReaderState s) LOCKS_EXCLUDED(mu_) {
mu_.Lock();
while (state_ != s) {
state_cv_.Wait();
@@ -320,7 +313,7 @@ class TestState {
mu_.Unlock();
}
- void Change(ReaderState s) {
+ void Change(ReaderState s) LOCKS_EXCLUDED(mu_) {
mu_.Lock();
state_ = s;
state_cv_.Signal();
@@ -329,8 +322,8 @@ class TestState {
private:
port::Mutex mu_;
- ReaderState state_;
- port::CondVar state_cv_;
+ ReaderState state_ GUARDED_BY(mu_);
+ port::CondVar state_cv_ GUARDED_BY(mu_);
};
static void ConcurrentReader(void* arg) {
@@ -338,7 +331,7 @@ static void ConcurrentReader(void* arg) {
Random rnd(state->seed_);
int64_t reads = 0;
state->Change(TestState::RUNNING);
- while (!state->quit_flag_.Acquire_Load()) {
+ while (!state->quit_flag_.load(std::memory_order_acquire)) {
state->t_.ReadStep(&rnd);
++reads;
}
@@ -360,7 +353,7 @@ static void RunConcurrent(int run) {
for (int i = 0; i < kSize; i++) {
state.t_.WriteStep(&rnd);
}
- state.quit_flag_.Release_Store(&state); // Any non-NULL arg will do
+ state.quit_flag_.store(true, std::memory_order_release);
state.Wait(TestState::DONE);
}
}
@@ -373,6 +366,4 @@ TEST(SkipTest, Concurrent5) { RunConcurrent(5); }
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/snapshot.h b/src/leveldb/db/snapshot.h
index 6ed413c42d..9f1d66491d 100644
--- a/src/leveldb/db/snapshot.h
+++ b/src/leveldb/db/snapshot.h
@@ -16,50 +16,78 @@ class SnapshotList;
// Each SnapshotImpl corresponds to a particular sequence number.
class SnapshotImpl : public Snapshot {
public:
- SequenceNumber number_; // const after creation
+ SnapshotImpl(SequenceNumber sequence_number)
+ : sequence_number_(sequence_number) {}
+
+ SequenceNumber sequence_number() const { return sequence_number_; }
private:
friend class SnapshotList;
- // SnapshotImpl is kept in a doubly-linked circular list
+ // SnapshotImpl is kept in a doubly-linked circular list. The SnapshotList
+ // implementation operates on the next/previous fields direcly.
SnapshotImpl* prev_;
SnapshotImpl* next_;
- SnapshotList* list_; // just for sanity checks
+ const SequenceNumber sequence_number_;
+
+#if !defined(NDEBUG)
+ SnapshotList* list_ = nullptr;
+#endif // !defined(NDEBUG)
};
class SnapshotList {
public:
- SnapshotList() {
- list_.prev_ = &list_;
- list_.next_ = &list_;
+ SnapshotList() : head_(0) {
+ head_.prev_ = &head_;
+ head_.next_ = &head_;
+ }
+
+ bool empty() const { return head_.next_ == &head_; }
+ SnapshotImpl* oldest() const {
+ assert(!empty());
+ return head_.next_;
}
+ SnapshotImpl* newest() const {
+ assert(!empty());
+ return head_.prev_;
+ }
+
+ // Creates a SnapshotImpl and appends it to the end of the list.
+ SnapshotImpl* New(SequenceNumber sequence_number) {
+ assert(empty() || newest()->sequence_number_ <= sequence_number);
+
+ SnapshotImpl* snapshot = new SnapshotImpl(sequence_number);
- bool empty() const { return list_.next_ == &list_; }
- SnapshotImpl* oldest() const { assert(!empty()); return list_.next_; }
- SnapshotImpl* newest() const { assert(!empty()); return list_.prev_; }
-
- const SnapshotImpl* New(SequenceNumber seq) {
- SnapshotImpl* s = new SnapshotImpl;
- s->number_ = seq;
- s->list_ = this;
- s->next_ = &list_;
- s->prev_ = list_.prev_;
- s->prev_->next_ = s;
- s->next_->prev_ = s;
- return s;
+#if !defined(NDEBUG)
+ snapshot->list_ = this;
+#endif // !defined(NDEBUG)
+ snapshot->next_ = &head_;
+ snapshot->prev_ = head_.prev_;
+ snapshot->prev_->next_ = snapshot;
+ snapshot->next_->prev_ = snapshot;
+ return snapshot;
}
- void Delete(const SnapshotImpl* s) {
- assert(s->list_ == this);
- s->prev_->next_ = s->next_;
- s->next_->prev_ = s->prev_;
- delete s;
+ // Removes a SnapshotImpl from this list.
+ //
+ // The snapshot must have been created by calling New() on this list.
+ //
+ // The snapshot pointer should not be const, because its memory is
+ // deallocated. However, that would force us to change DB::ReleaseSnapshot(),
+ // which is in the API, and currently takes a const Snapshot.
+ void Delete(const SnapshotImpl* snapshot) {
+#if !defined(NDEBUG)
+ assert(snapshot->list_ == this);
+#endif // !defined(NDEBUG)
+ snapshot->prev_->next_ = snapshot->next_;
+ snapshot->next_->prev_ = snapshot->prev_;
+ delete snapshot;
}
private:
// Dummy head of doubly-linked list of snapshots
- SnapshotImpl list_;
+ SnapshotImpl head_;
};
} // namespace leveldb
diff --git a/src/leveldb/db/table_cache.cc b/src/leveldb/db/table_cache.cc
index e3d82cd3ea..73f05fd7b1 100644
--- a/src/leveldb/db/table_cache.cc
+++ b/src/leveldb/db/table_cache.cc
@@ -29,18 +29,14 @@ static void UnrefEntry(void* arg1, void* arg2) {
cache->Release(h);
}
-TableCache::TableCache(const std::string& dbname,
- const Options* options,
+TableCache::TableCache(const std::string& dbname, const Options& options,
int entries)
- : env_(options->env),
+ : env_(options.env),
dbname_(dbname),
options_(options),
- cache_(NewLRUCache(entries)) {
-}
+ cache_(NewLRUCache(entries)) {}
-TableCache::~TableCache() {
- delete cache_;
-}
+TableCache::~TableCache() { delete cache_; }
Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
Cache::Handle** handle) {
@@ -49,10 +45,10 @@ Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
EncodeFixed64(buf, file_number);
Slice key(buf, sizeof(buf));
*handle = cache_->Lookup(key);
- if (*handle == NULL) {
+ if (*handle == nullptr) {
std::string fname = TableFileName(dbname_, file_number);
- RandomAccessFile* file = NULL;
- Table* table = NULL;
+ RandomAccessFile* file = nullptr;
+ Table* table = nullptr;
s = env_->NewRandomAccessFile(fname, &file);
if (!s.ok()) {
std::string old_fname = SSTTableFileName(dbname_, file_number);
@@ -61,11 +57,11 @@ Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
}
}
if (s.ok()) {
- s = Table::Open(*options_, file, file_size, &table);
+ s = Table::Open(options_, file, file_size, &table);
}
if (!s.ok()) {
- assert(table == NULL);
+ assert(table == nullptr);
delete file;
// We do not cache error results so that if the error is transient,
// or somebody repairs the file, we recover automatically.
@@ -80,14 +76,13 @@ Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
}
Iterator* TableCache::NewIterator(const ReadOptions& options,
- uint64_t file_number,
- uint64_t file_size,
+ uint64_t file_number, uint64_t file_size,
Table** tableptr) {
- if (tableptr != NULL) {
- *tableptr = NULL;
+ if (tableptr != nullptr) {
+ *tableptr = nullptr;
}
- Cache::Handle* handle = NULL;
+ Cache::Handle* handle = nullptr;
Status s = FindTable(file_number, file_size, &handle);
if (!s.ok()) {
return NewErrorIterator(s);
@@ -96,23 +91,21 @@ Iterator* TableCache::NewIterator(const ReadOptions& options,
Table* table = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
Iterator* result = table->NewIterator(options);
result->RegisterCleanup(&UnrefEntry, cache_, handle);
- if (tableptr != NULL) {
+ if (tableptr != nullptr) {
*tableptr = table;
}
return result;
}
-Status TableCache::Get(const ReadOptions& options,
- uint64_t file_number,
- uint64_t file_size,
- const Slice& k,
- void* arg,
- void (*saver)(void*, const Slice&, const Slice&)) {
- Cache::Handle* handle = NULL;
+Status TableCache::Get(const ReadOptions& options, uint64_t file_number,
+ uint64_t file_size, const Slice& k, void* arg,
+ void (*handle_result)(void*, const Slice&,
+ const Slice&)) {
+ Cache::Handle* handle = nullptr;
Status s = FindTable(file_number, file_size, &handle);
if (s.ok()) {
Table* t = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
- s = t->InternalGet(options, k, arg, saver);
+ s = t->InternalGet(options, k, arg, handle_result);
cache_->Release(handle);
}
return s;
diff --git a/src/leveldb/db/table_cache.h b/src/leveldb/db/table_cache.h
index 8cf4aaf12d..93069c8844 100644
--- a/src/leveldb/db/table_cache.h
+++ b/src/leveldb/db/table_cache.h
@@ -7,8 +7,10 @@
#ifndef STORAGE_LEVELDB_DB_TABLE_CACHE_H_
#define STORAGE_LEVELDB_DB_TABLE_CACHE_H_
-#include <string>
#include <stdint.h>
+
+#include <string>
+
#include "db/dbformat.h"
#include "leveldb/cache.h"
#include "leveldb/table.h"
@@ -20,40 +22,35 @@ class Env;
class TableCache {
public:
- TableCache(const std::string& dbname, const Options* options, int entries);
+ TableCache(const std::string& dbname, const Options& options, int entries);
~TableCache();
// Return an iterator for the specified file number (the corresponding
// file length must be exactly "file_size" bytes). If "tableptr" is
- // non-NULL, also sets "*tableptr" to point to the Table object
- // underlying the returned iterator, or NULL if no Table object underlies
- // the returned iterator. The returned "*tableptr" object is owned by
- // the cache and should not be deleted, and is valid for as long as the
+ // non-null, also sets "*tableptr" to point to the Table object
+ // underlying the returned iterator, or to nullptr if no Table object
+ // underlies the returned iterator. The returned "*tableptr" object is owned
+ // by the cache and should not be deleted, and is valid for as long as the
// returned iterator is live.
- Iterator* NewIterator(const ReadOptions& options,
- uint64_t file_number,
- uint64_t file_size,
- Table** tableptr = NULL);
+ Iterator* NewIterator(const ReadOptions& options, uint64_t file_number,
+ uint64_t file_size, Table** tableptr = nullptr);
// If a seek to internal key "k" in specified file finds an entry,
// call (*handle_result)(arg, found_key, found_value).
- Status Get(const ReadOptions& options,
- uint64_t file_number,
- uint64_t file_size,
- const Slice& k,
- void* arg,
+ Status Get(const ReadOptions& options, uint64_t file_number,
+ uint64_t file_size, const Slice& k, void* arg,
void (*handle_result)(void*, const Slice&, const Slice&));
// Evict any entry for the specified file number
void Evict(uint64_t file_number);
private:
+ Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**);
+
Env* const env_;
const std::string dbname_;
- const Options* options_;
+ const Options& options_;
Cache* cache_;
-
- Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**);
};
} // namespace leveldb
diff --git a/src/leveldb/db/version_edit.cc b/src/leveldb/db/version_edit.cc
index f10a2d58b2..cd770ef12d 100644
--- a/src/leveldb/db/version_edit.cc
+++ b/src/leveldb/db/version_edit.cc
@@ -12,15 +12,15 @@ namespace leveldb {
// Tag numbers for serialized VersionEdit. These numbers are written to
// disk and should not be changed.
enum Tag {
- kComparator = 1,
- kLogNumber = 2,
- kNextFileNumber = 3,
- kLastSequence = 4,
- kCompactPointer = 5,
- kDeletedFile = 6,
- kNewFile = 7,
+ kComparator = 1,
+ kLogNumber = 2,
+ kNextFileNumber = 3,
+ kLastSequence = 4,
+ kCompactPointer = 5,
+ kDeletedFile = 6,
+ kNewFile = 7,
// 8 was used for large value refs
- kPrevLogNumber = 9
+ kPrevLogNumber = 9
};
void VersionEdit::Clear() {
@@ -66,12 +66,10 @@ void VersionEdit::EncodeTo(std::string* dst) const {
PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode());
}
- for (DeletedFileSet::const_iterator iter = deleted_files_.begin();
- iter != deleted_files_.end();
- ++iter) {
+ for (const auto& deleted_file_kvp : deleted_files_) {
PutVarint32(dst, kDeletedFile);
- PutVarint32(dst, iter->first); // level
- PutVarint64(dst, iter->second); // file number
+ PutVarint32(dst, deleted_file_kvp.first); // level
+ PutVarint64(dst, deleted_file_kvp.second); // file number
}
for (size_t i = 0; i < new_files_.size(); i++) {
@@ -88,8 +86,7 @@ void VersionEdit::EncodeTo(std::string* dst) const {
static bool GetInternalKey(Slice* input, InternalKey* dst) {
Slice str;
if (GetLengthPrefixedSlice(input, &str)) {
- dst->DecodeFrom(str);
- return true;
+ return dst->DecodeFrom(str);
} else {
return false;
}
@@ -97,8 +94,7 @@ static bool GetInternalKey(Slice* input, InternalKey* dst) {
static bool GetLevel(Slice* input, int* level) {
uint32_t v;
- if (GetVarint32(input, &v) &&
- v < config::kNumLevels) {
+ if (GetVarint32(input, &v) && v < config::kNumLevels) {
*level = v;
return true;
} else {
@@ -109,7 +105,7 @@ static bool GetLevel(Slice* input, int* level) {
Status VersionEdit::DecodeFrom(const Slice& src) {
Clear();
Slice input = src;
- const char* msg = NULL;
+ const char* msg = nullptr;
uint32_t tag;
// Temporary storage for parsing
@@ -119,7 +115,7 @@ Status VersionEdit::DecodeFrom(const Slice& src) {
Slice str;
InternalKey key;
- while (msg == NULL && GetVarint32(&input, &tag)) {
+ while (msg == nullptr && GetVarint32(&input, &tag)) {
switch (tag) {
case kComparator:
if (GetLengthPrefixedSlice(&input, &str)) {
@@ -163,8 +159,7 @@ Status VersionEdit::DecodeFrom(const Slice& src) {
break;
case kCompactPointer:
- if (GetLevel(&input, &level) &&
- GetInternalKey(&input, &key)) {
+ if (GetLevel(&input, &level) && GetInternalKey(&input, &key)) {
compact_pointers_.push_back(std::make_pair(level, key));
} else {
msg = "compaction pointer";
@@ -172,8 +167,7 @@ Status VersionEdit::DecodeFrom(const Slice& src) {
break;
case kDeletedFile:
- if (GetLevel(&input, &level) &&
- GetVarint64(&input, &number)) {
+ if (GetLevel(&input, &level) && GetVarint64(&input, &number)) {
deleted_files_.insert(std::make_pair(level, number));
} else {
msg = "deleted file";
@@ -181,8 +175,7 @@ Status VersionEdit::DecodeFrom(const Slice& src) {
break;
case kNewFile:
- if (GetLevel(&input, &level) &&
- GetVarint64(&input, &f.number) &&
+ if (GetLevel(&input, &level) && GetVarint64(&input, &f.number) &&
GetVarint64(&input, &f.file_size) &&
GetInternalKey(&input, &f.smallest) &&
GetInternalKey(&input, &f.largest)) {
@@ -198,12 +191,12 @@ Status VersionEdit::DecodeFrom(const Slice& src) {
}
}
- if (msg == NULL && !input.empty()) {
+ if (msg == nullptr && !input.empty()) {
msg = "invalid tag";
}
Status result;
- if (msg != NULL) {
+ if (msg != nullptr) {
result = Status::Corruption("VersionEdit", msg);
}
return result;
@@ -238,13 +231,11 @@ std::string VersionEdit::DebugString() const {
r.append(" ");
r.append(compact_pointers_[i].second.DebugString());
}
- for (DeletedFileSet::const_iterator iter = deleted_files_.begin();
- iter != deleted_files_.end();
- ++iter) {
+ for (const auto& deleted_files_kvp : deleted_files_) {
r.append("\n DeleteFile: ");
- AppendNumberTo(&r, iter->first);
+ AppendNumberTo(&r, deleted_files_kvp.first);
r.append(" ");
- AppendNumberTo(&r, iter->second);
+ AppendNumberTo(&r, deleted_files_kvp.second);
}
for (size_t i = 0; i < new_files_.size(); i++) {
const FileMetaData& f = new_files_[i].second;
diff --git a/src/leveldb/db/version_edit.h b/src/leveldb/db/version_edit.h
index eaef77b327..0de4531773 100644
--- a/src/leveldb/db/version_edit.h
+++ b/src/leveldb/db/version_edit.h
@@ -8,6 +8,7 @@
#include <set>
#include <utility>
#include <vector>
+
#include "db/dbformat.h"
namespace leveldb {
@@ -15,20 +16,20 @@ namespace leveldb {
class VersionSet;
struct FileMetaData {
+ FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0) {}
+
int refs;
- int allowed_seeks; // Seeks allowed until compaction
+ int allowed_seeks; // Seeks allowed until compaction
uint64_t number;
- uint64_t file_size; // File size in bytes
- InternalKey smallest; // Smallest internal key served by table
- InternalKey largest; // Largest internal key served by table
-
- FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0) { }
+ uint64_t file_size; // File size in bytes
+ InternalKey smallest; // Smallest internal key served by table
+ InternalKey largest; // Largest internal key served by table
};
class VersionEdit {
public:
VersionEdit() { Clear(); }
- ~VersionEdit() { }
+ ~VersionEdit() = default;
void Clear();
@@ -59,10 +60,8 @@ class VersionEdit {
// Add the specified file at the specified number.
// REQUIRES: This version has not been saved (see VersionSet::SaveTo)
// REQUIRES: "smallest" and "largest" are smallest and largest keys in file
- void AddFile(int level, uint64_t file,
- uint64_t file_size,
- const InternalKey& smallest,
- const InternalKey& largest) {
+ void AddFile(int level, uint64_t file, uint64_t file_size,
+ const InternalKey& smallest, const InternalKey& largest) {
FileMetaData f;
f.number = file;
f.file_size = file_size;
@@ -84,7 +83,7 @@ class VersionEdit {
private:
friend class VersionSet;
- typedef std::set< std::pair<int, uint64_t> > DeletedFileSet;
+ typedef std::set<std::pair<int, uint64_t>> DeletedFileSet;
std::string comparator_;
uint64_t log_number_;
@@ -97,9 +96,9 @@ class VersionEdit {
bool has_next_file_number_;
bool has_last_sequence_;
- std::vector< std::pair<int, InternalKey> > compact_pointers_;
+ std::vector<std::pair<int, InternalKey>> compact_pointers_;
DeletedFileSet deleted_files_;
- std::vector< std::pair<int, FileMetaData> > new_files_;
+ std::vector<std::pair<int, FileMetaData>> new_files_;
};
} // namespace leveldb
diff --git a/src/leveldb/db/version_edit_test.cc b/src/leveldb/db/version_edit_test.cc
index 280310b49d..0b7cda8854 100644
--- a/src/leveldb/db/version_edit_test.cc
+++ b/src/leveldb/db/version_edit_test.cc
@@ -17,7 +17,7 @@ static void TestEncodeDecode(const VersionEdit& edit) {
ASSERT_EQ(encoded, encoded2);
}
-class VersionEditTest { };
+class VersionEditTest {};
TEST(VersionEditTest, EncodeDecode) {
static const uint64_t kBig = 1ull << 50;
@@ -41,6 +41,4 @@ TEST(VersionEditTest, EncodeDecode) {
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/version_set.cc b/src/leveldb/db/version_set.cc
index 2cb6d80ed3..cd07346ea8 100644
--- a/src/leveldb/db/version_set.cc
+++ b/src/leveldb/db/version_set.cc
@@ -4,8 +4,10 @@
#include "db/version_set.h"
-#include <algorithm>
#include <stdio.h>
+
+#include <algorithm>
+
#include "db/filename.h"
#include "db/log_reader.h"
#include "db/log_writer.h"
@@ -84,8 +86,7 @@ Version::~Version() {
}
int FindFile(const InternalKeyComparator& icmp,
- const std::vector<FileMetaData*>& files,
- const Slice& key) {
+ const std::vector<FileMetaData*>& files, const Slice& key) {
uint32_t left = 0;
uint32_t right = files.size();
while (left < right) {
@@ -104,26 +105,25 @@ int FindFile(const InternalKeyComparator& icmp,
return right;
}
-static bool AfterFile(const Comparator* ucmp,
- const Slice* user_key, const FileMetaData* f) {
- // NULL user_key occurs before all keys and is therefore never after *f
- return (user_key != NULL &&
+static bool AfterFile(const Comparator* ucmp, const Slice* user_key,
+ const FileMetaData* f) {
+ // null user_key occurs before all keys and is therefore never after *f
+ return (user_key != nullptr &&
ucmp->Compare(*user_key, f->largest.user_key()) > 0);
}
-static bool BeforeFile(const Comparator* ucmp,
- const Slice* user_key, const FileMetaData* f) {
- // NULL user_key occurs after all keys and is therefore never before *f
- return (user_key != NULL &&
+static bool BeforeFile(const Comparator* ucmp, const Slice* user_key,
+ const FileMetaData* f) {
+ // null user_key occurs after all keys and is therefore never before *f
+ return (user_key != nullptr &&
ucmp->Compare(*user_key, f->smallest.user_key()) < 0);
}
-bool SomeFileOverlapsRange(
- const InternalKeyComparator& icmp,
- bool disjoint_sorted_files,
- const std::vector<FileMetaData*>& files,
- const Slice* smallest_user_key,
- const Slice* largest_user_key) {
+bool SomeFileOverlapsRange(const InternalKeyComparator& icmp,
+ bool disjoint_sorted_files,
+ const std::vector<FileMetaData*>& files,
+ const Slice* smallest_user_key,
+ const Slice* largest_user_key) {
const Comparator* ucmp = icmp.user_comparator();
if (!disjoint_sorted_files) {
// Need to check against all files
@@ -141,10 +141,11 @@ bool SomeFileOverlapsRange(
// Binary search over file list
uint32_t index = 0;
- if (smallest_user_key != NULL) {
+ if (smallest_user_key != nullptr) {
// Find the earliest possible internal key for smallest_user_key
- InternalKey small(*smallest_user_key, kMaxSequenceNumber,kValueTypeForSeek);
- index = FindFile(icmp, files, small.Encode());
+ InternalKey small_key(*smallest_user_key, kMaxSequenceNumber,
+ kValueTypeForSeek);
+ index = FindFile(icmp, files, small_key.Encode());
}
if (index >= files.size()) {
@@ -164,25 +165,21 @@ class Version::LevelFileNumIterator : public Iterator {
public:
LevelFileNumIterator(const InternalKeyComparator& icmp,
const std::vector<FileMetaData*>* flist)
- : icmp_(icmp),
- flist_(flist),
- index_(flist->size()) { // Marks as invalid
- }
- virtual bool Valid() const {
- return index_ < flist_->size();
+ : icmp_(icmp), flist_(flist), index_(flist->size()) { // Marks as invalid
}
- virtual void Seek(const Slice& target) {
+ bool Valid() const override { return index_ < flist_->size(); }
+ void Seek(const Slice& target) override {
index_ = FindFile(icmp_, *flist_, target);
}
- virtual void SeekToFirst() { index_ = 0; }
- virtual void SeekToLast() {
+ void SeekToFirst() override { index_ = 0; }
+ void SeekToLast() override {
index_ = flist_->empty() ? 0 : flist_->size() - 1;
}
- virtual void Next() {
+ void Next() override {
assert(Valid());
index_++;
}
- virtual void Prev() {
+ void Prev() override {
assert(Valid());
if (index_ == 0) {
index_ = flist_->size(); // Marks as invalid
@@ -190,17 +187,18 @@ class Version::LevelFileNumIterator : public Iterator {
index_--;
}
}
- Slice key() const {
+ Slice key() const override {
assert(Valid());
return (*flist_)[index_]->largest.Encode();
}
- Slice value() const {
+ Slice value() const override {
assert(Valid());
EncodeFixed64(value_buf_, (*flist_)[index_]->number);
- EncodeFixed64(value_buf_+8, (*flist_)[index_]->file_size);
+ EncodeFixed64(value_buf_ + 8, (*flist_)[index_]->file_size);
return Slice(value_buf_, sizeof(value_buf_));
}
- virtual Status status() const { return Status::OK(); }
+ Status status() const override { return Status::OK(); }
+
private:
const InternalKeyComparator icmp_;
const std::vector<FileMetaData*>* const flist_;
@@ -210,16 +208,14 @@ class Version::LevelFileNumIterator : public Iterator {
mutable char value_buf_[16];
};
-static Iterator* GetFileIterator(void* arg,
- const ReadOptions& options,
+static Iterator* GetFileIterator(void* arg, const ReadOptions& options,
const Slice& file_value) {
TableCache* cache = reinterpret_cast<TableCache*>(arg);
if (file_value.size() != 16) {
return NewErrorIterator(
Status::Corruption("FileReader invoked with unexpected value"));
} else {
- return cache->NewIterator(options,
- DecodeFixed64(file_value.data()),
+ return cache->NewIterator(options, DecodeFixed64(file_value.data()),
DecodeFixed64(file_value.data() + 8));
}
}
@@ -227,17 +223,16 @@ static Iterator* GetFileIterator(void* arg,
Iterator* Version::NewConcatenatingIterator(const ReadOptions& options,
int level) const {
return NewTwoLevelIterator(
- new LevelFileNumIterator(vset_->icmp_, &files_[level]),
- &GetFileIterator, vset_->table_cache_, options);
+ new LevelFileNumIterator(vset_->icmp_, &files_[level]), &GetFileIterator,
+ vset_->table_cache_, options);
}
void Version::AddIterators(const ReadOptions& options,
std::vector<Iterator*>* iters) {
// Merge all level zero files together since they may overlap
for (size_t i = 0; i < files_[0].size(); i++) {
- iters->push_back(
- vset_->table_cache_->NewIterator(
- options, files_[0][i]->number, files_[0][i]->file_size));
+ iters->push_back(vset_->table_cache_->NewIterator(
+ options, files_[0][i]->number, files_[0][i]->file_size));
}
// For levels > 0, we can use a concatenating iterator that sequentially
@@ -264,7 +259,7 @@ struct Saver {
Slice user_key;
std::string* value;
};
-}
+} // namespace
static void SaveValue(void* arg, const Slice& ikey, const Slice& v) {
Saver* s = reinterpret_cast<Saver*>(arg);
ParsedInternalKey parsed_key;
@@ -284,10 +279,8 @@ static bool NewestFirst(FileMetaData* a, FileMetaData* b) {
return a->number > b->number;
}
-void Version::ForEachOverlapping(Slice user_key, Slice internal_key,
- void* arg,
+void Version::ForEachOverlapping(Slice user_key, Slice internal_key, void* arg,
bool (*func)(void*, int, FileMetaData*)) {
- // TODO(sanjay): Change Version::Get() to use this function.
const Comparator* ucmp = vset_->icmp_.user_comparator();
// Search level-0 in order from newest to oldest.
@@ -329,110 +322,89 @@ void Version::ForEachOverlapping(Slice user_key, Slice internal_key,
}
}
-Status Version::Get(const ReadOptions& options,
- const LookupKey& k,
- std::string* value,
- GetStats* stats) {
- Slice ikey = k.internal_key();
- Slice user_key = k.user_key();
- const Comparator* ucmp = vset_->icmp_.user_comparator();
- Status s;
-
- stats->seek_file = NULL;
+Status Version::Get(const ReadOptions& options, const LookupKey& k,
+ std::string* value, GetStats* stats) {
+ stats->seek_file = nullptr;
stats->seek_file_level = -1;
- FileMetaData* last_file_read = NULL;
- int last_file_read_level = -1;
- // We can search level-by-level since entries never hop across
- // levels. Therefore we are guaranteed that if we find data
- // in an smaller level, later levels are irrelevant.
- std::vector<FileMetaData*> tmp;
- FileMetaData* tmp2;
- for (int level = 0; level < config::kNumLevels; level++) {
- size_t num_files = files_[level].size();
- if (num_files == 0) continue;
+ struct State {
+ Saver saver;
+ GetStats* stats;
+ const ReadOptions* options;
+ Slice ikey;
+ FileMetaData* last_file_read;
+ int last_file_read_level;
- // Get the list of files to search in this level
- FileMetaData* const* files = &files_[level][0];
- if (level == 0) {
- // Level-0 files may overlap each other. Find all files that
- // overlap user_key and process them in order from newest to oldest.
- tmp.reserve(num_files);
- for (uint32_t i = 0; i < num_files; i++) {
- FileMetaData* f = files[i];
- if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 &&
- ucmp->Compare(user_key, f->largest.user_key()) <= 0) {
- tmp.push_back(f);
- }
- }
- if (tmp.empty()) continue;
+ VersionSet* vset;
+ Status s;
+ bool found;
- std::sort(tmp.begin(), tmp.end(), NewestFirst);
- files = &tmp[0];
- num_files = tmp.size();
- } else {
- // Binary search to find earliest index whose largest key >= ikey.
- uint32_t index = FindFile(vset_->icmp_, files_[level], ikey);
- if (index >= num_files) {
- files = NULL;
- num_files = 0;
- } else {
- tmp2 = files[index];
- if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) {
- // All of "tmp2" is past any data for user_key
- files = NULL;
- num_files = 0;
- } else {
- files = &tmp2;
- num_files = 1;
- }
- }
- }
+ static bool Match(void* arg, int level, FileMetaData* f) {
+ State* state = reinterpret_cast<State*>(arg);
- for (uint32_t i = 0; i < num_files; ++i) {
- if (last_file_read != NULL && stats->seek_file == NULL) {
+ if (state->stats->seek_file == nullptr &&
+ state->last_file_read != nullptr) {
// We have had more than one seek for this read. Charge the 1st file.
- stats->seek_file = last_file_read;
- stats->seek_file_level = last_file_read_level;
+ state->stats->seek_file = state->last_file_read;
+ state->stats->seek_file_level = state->last_file_read_level;
}
- FileMetaData* f = files[i];
- last_file_read = f;
- last_file_read_level = level;
-
- Saver saver;
- saver.state = kNotFound;
- saver.ucmp = ucmp;
- saver.user_key = user_key;
- saver.value = value;
- s = vset_->table_cache_->Get(options, f->number, f->file_size,
- ikey, &saver, SaveValue);
- if (!s.ok()) {
- return s;
+ state->last_file_read = f;
+ state->last_file_read_level = level;
+
+ state->s = state->vset->table_cache_->Get(*state->options, f->number,
+ f->file_size, state->ikey,
+ &state->saver, SaveValue);
+ if (!state->s.ok()) {
+ state->found = true;
+ return false;
}
- switch (saver.state) {
+ switch (state->saver.state) {
case kNotFound:
- break; // Keep searching in other files
+ return true; // Keep searching in other files
case kFound:
- return s;
+ state->found = true;
+ return false;
case kDeleted:
- s = Status::NotFound(Slice()); // Use empty error message for speed
- return s;
+ return false;
case kCorrupt:
- s = Status::Corruption("corrupted key for ", user_key);
- return s;
+ state->s =
+ Status::Corruption("corrupted key for ", state->saver.user_key);
+ state->found = true;
+ return false;
}
+
+ // Not reached. Added to avoid false compilation warnings of
+ // "control reaches end of non-void function".
+ return false;
}
- }
+ };
+
+ State state;
+ state.found = false;
+ state.stats = stats;
+ state.last_file_read = nullptr;
+ state.last_file_read_level = -1;
- return Status::NotFound(Slice()); // Use an empty error message for speed
+ state.options = &options;
+ state.ikey = k.internal_key();
+ state.vset = vset_;
+
+ state.saver.state = kNotFound;
+ state.saver.ucmp = vset_->icmp_.user_comparator();
+ state.saver.user_key = k.user_key();
+ state.saver.value = value;
+
+ ForEachOverlapping(state.saver.user_key, state.ikey, &state, &State::Match);
+
+ return state.found ? state.s : Status::NotFound(Slice());
}
bool Version::UpdateStats(const GetStats& stats) {
FileMetaData* f = stats.seek_file;
- if (f != NULL) {
+ if (f != nullptr) {
f->allowed_seeks--;
- if (f->allowed_seeks <= 0 && file_to_compact_ == NULL) {
+ if (f->allowed_seeks <= 0 && file_to_compact_ == nullptr) {
file_to_compact_ = f;
file_to_compact_level_ = stats.seek_file_level;
return true;
@@ -479,9 +451,7 @@ bool Version::RecordReadSample(Slice internal_key) {
return false;
}
-void Version::Ref() {
- ++refs_;
-}
+void Version::Ref() { ++refs_; }
void Version::Unref() {
assert(this != &vset_->dummy_versions_);
@@ -492,16 +462,14 @@ void Version::Unref() {
}
}
-bool Version::OverlapInLevel(int level,
- const Slice* smallest_user_key,
+bool Version::OverlapInLevel(int level, const Slice* smallest_user_key,
const Slice* largest_user_key) {
return SomeFileOverlapsRange(vset_->icmp_, (level > 0), files_[level],
smallest_user_key, largest_user_key);
}
-int Version::PickLevelForMemTableOutput(
- const Slice& smallest_user_key,
- const Slice& largest_user_key) {
+int Version::PickLevelForMemTableOutput(const Slice& smallest_user_key,
+ const Slice& largest_user_key) {
int level = 0;
if (!OverlapInLevel(0, &smallest_user_key, &largest_user_key)) {
// Push to next level if there is no overlap in next level,
@@ -528,40 +496,39 @@ int Version::PickLevelForMemTableOutput(
}
// Store in "*inputs" all files in "level" that overlap [begin,end]
-void Version::GetOverlappingInputs(
- int level,
- const InternalKey* begin,
- const InternalKey* end,
- std::vector<FileMetaData*>* inputs) {
+void Version::GetOverlappingInputs(int level, const InternalKey* begin,
+ const InternalKey* end,
+ std::vector<FileMetaData*>* inputs) {
assert(level >= 0);
assert(level < config::kNumLevels);
inputs->clear();
Slice user_begin, user_end;
- if (begin != NULL) {
+ if (begin != nullptr) {
user_begin = begin->user_key();
}
- if (end != NULL) {
+ if (end != nullptr) {
user_end = end->user_key();
}
const Comparator* user_cmp = vset_->icmp_.user_comparator();
- for (size_t i = 0; i < files_[level].size(); ) {
+ for (size_t i = 0; i < files_[level].size();) {
FileMetaData* f = files_[level][i++];
const Slice file_start = f->smallest.user_key();
const Slice file_limit = f->largest.user_key();
- if (begin != NULL && user_cmp->Compare(file_limit, user_begin) < 0) {
+ if (begin != nullptr && user_cmp->Compare(file_limit, user_begin) < 0) {
// "f" is completely before specified range; skip it
- } else if (end != NULL && user_cmp->Compare(file_start, user_end) > 0) {
+ } else if (end != nullptr && user_cmp->Compare(file_start, user_end) > 0) {
// "f" is completely after specified range; skip it
} else {
inputs->push_back(f);
if (level == 0) {
// Level-0 files may overlap each other. So check if the newly
// added file has expanded the range. If so, restart search.
- if (begin != NULL && user_cmp->Compare(file_start, user_begin) < 0) {
+ if (begin != nullptr && user_cmp->Compare(file_start, user_begin) < 0) {
user_begin = file_start;
inputs->clear();
i = 0;
- } else if (end != NULL && user_cmp->Compare(file_limit, user_end) > 0) {
+ } else if (end != nullptr &&
+ user_cmp->Compare(file_limit, user_end) > 0) {
user_end = file_limit;
inputs->clear();
i = 0;
@@ -629,9 +596,7 @@ class VersionSet::Builder {
public:
// Initialize a builder with the files from *base and other info from *vset
- Builder(VersionSet* vset, Version* base)
- : vset_(vset),
- base_(base) {
+ Builder(VersionSet* vset, Version* base) : vset_(vset), base_(base) {
base_->Ref();
BySmallestKey cmp;
cmp.internal_comparator = &vset_->icmp_;
@@ -645,8 +610,8 @@ class VersionSet::Builder {
const FileSet* added = levels_[level].added_files;
std::vector<FileMetaData*> to_unref;
to_unref.reserve(added->size());
- for (FileSet::const_iterator it = added->begin();
- it != added->end(); ++it) {
+ for (FileSet::const_iterator it = added->begin(); it != added->end();
+ ++it) {
to_unref.push_back(*it);
}
delete added;
@@ -671,12 +636,9 @@ class VersionSet::Builder {
}
// Delete files
- const VersionEdit::DeletedFileSet& del = edit->deleted_files_;
- for (VersionEdit::DeletedFileSet::const_iterator iter = del.begin();
- iter != del.end();
- ++iter) {
- const int level = iter->first;
- const uint64_t number = iter->second;
+ for (const auto& deleted_file_set_kvp : edit->deleted_files_) {
+ const int level = deleted_file_set_kvp.first;
+ const uint64_t number = deleted_file_set_kvp.second;
levels_[level].deleted_files.insert(number);
}
@@ -699,7 +661,7 @@ class VersionSet::Builder {
// same as the compaction of 40KB of data. We are a little
// conservative and allow approximately one seek for every 16KB
// of data before triggering a compaction.
- f->allowed_seeks = (f->file_size / 16384);
+ f->allowed_seeks = static_cast<int>((f->file_size / 16384U));
if (f->allowed_seeks < 100) f->allowed_seeks = 100;
levels_[level].deleted_files.erase(f->number);
@@ -717,20 +679,17 @@ class VersionSet::Builder {
const std::vector<FileMetaData*>& base_files = base_->files_[level];
std::vector<FileMetaData*>::const_iterator base_iter = base_files.begin();
std::vector<FileMetaData*>::const_iterator base_end = base_files.end();
- const FileSet* added = levels_[level].added_files;
- v->files_[level].reserve(base_files.size() + added->size());
- for (FileSet::const_iterator added_iter = added->begin();
- added_iter != added->end();
- ++added_iter) {
+ const FileSet* added_files = levels_[level].added_files;
+ v->files_[level].reserve(base_files.size() + added_files->size());
+ for (const auto& added_file : *added_files) {
// Add all smaller files listed in base_
- for (std::vector<FileMetaData*>::const_iterator bpos
- = std::upper_bound(base_iter, base_end, *added_iter, cmp);
- base_iter != bpos;
- ++base_iter) {
+ for (std::vector<FileMetaData*>::const_iterator bpos =
+ std::upper_bound(base_iter, base_end, added_file, cmp);
+ base_iter != bpos; ++base_iter) {
MaybeAddFile(v, level, *base_iter);
}
- MaybeAddFile(v, level, *added_iter);
+ MaybeAddFile(v, level, added_file);
}
// Add remaining base files
@@ -742,7 +701,7 @@ class VersionSet::Builder {
// Make sure there is no overlap in levels > 0
if (level > 0) {
for (uint32_t i = 1; i < v->files_[level].size(); i++) {
- const InternalKey& prev_end = v->files_[level][i-1]->largest;
+ const InternalKey& prev_end = v->files_[level][i - 1]->largest;
const InternalKey& this_begin = v->files_[level][i]->smallest;
if (vset_->icmp_.Compare(prev_end, this_begin) >= 0) {
fprintf(stderr, "overlapping ranges in same level %s vs. %s\n",
@@ -763,7 +722,7 @@ class VersionSet::Builder {
std::vector<FileMetaData*>* files = &v->files_[level];
if (level > 0 && !files->empty()) {
// Must not overlap
- assert(vset_->icmp_.Compare((*files)[files->size()-1]->largest,
+ assert(vset_->icmp_.Compare((*files)[files->size() - 1]->largest,
f->smallest) < 0);
}
f->refs++;
@@ -772,8 +731,7 @@ class VersionSet::Builder {
}
};
-VersionSet::VersionSet(const std::string& dbname,
- const Options* options,
+VersionSet::VersionSet(const std::string& dbname, const Options* options,
TableCache* table_cache,
const InternalKeyComparator* cmp)
: env_(options->env),
@@ -786,10 +744,10 @@ VersionSet::VersionSet(const std::string& dbname,
last_sequence_(0),
log_number_(0),
prev_log_number_(0),
- descriptor_file_(NULL),
- descriptor_log_(NULL),
+ descriptor_file_(nullptr),
+ descriptor_log_(nullptr),
dummy_versions_(this),
- current_(NULL) {
+ current_(nullptr) {
AppendVersion(new Version(this));
}
@@ -804,7 +762,7 @@ void VersionSet::AppendVersion(Version* v) {
// Make "v" current
assert(v->refs_ == 0);
assert(v != current_);
- if (current_ != NULL) {
+ if (current_ != nullptr) {
current_->Unref();
}
current_ = v;
@@ -844,10 +802,10 @@ Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) {
// a temporary file that contains a snapshot of the current version.
std::string new_manifest_file;
Status s;
- if (descriptor_log_ == NULL) {
+ if (descriptor_log_ == nullptr) {
// No reason to unlock *mu here since we only hit this path in the
// first call to LogAndApply (when opening the database).
- assert(descriptor_file_ == NULL);
+ assert(descriptor_file_ == nullptr);
new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_);
edit->SetNextFile(next_file_number_);
s = env_->NewWritableFile(new_manifest_file, &descriptor_file_);
@@ -893,8 +851,8 @@ Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) {
if (!new_manifest_file.empty()) {
delete descriptor_log_;
delete descriptor_file_;
- descriptor_log_ = NULL;
- descriptor_file_ = NULL;
+ descriptor_log_ = nullptr;
+ descriptor_file_ = nullptr;
env_->DeleteFile(new_manifest_file);
}
}
@@ -902,10 +860,10 @@ Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) {
return s;
}
-Status VersionSet::Recover(bool *save_manifest) {
+Status VersionSet::Recover(bool* save_manifest) {
struct LogReporter : public log::Reader::Reporter {
Status* status;
- virtual void Corruption(size_t bytes, const Status& s) {
+ void Corruption(size_t bytes, const Status& s) override {
if (this->status->ok()) *this->status = s;
}
};
@@ -916,7 +874,7 @@ Status VersionSet::Recover(bool *save_manifest) {
if (!s.ok()) {
return s;
}
- if (current.empty() || current[current.size()-1] != '\n') {
+ if (current.empty() || current[current.size() - 1] != '\n') {
return Status::Corruption("CURRENT file does not end with newline");
}
current.resize(current.size() - 1);
@@ -925,6 +883,10 @@ Status VersionSet::Recover(bool *save_manifest) {
SequentialFile* file;
s = env_->NewSequentialFile(dscname, &file);
if (!s.ok()) {
+ if (s.IsNotFound()) {
+ return Status::Corruption("CURRENT points to a non-existent file",
+ s.ToString());
+ }
return s;
}
@@ -941,7 +903,8 @@ Status VersionSet::Recover(bool *save_manifest) {
{
LogReporter reporter;
reporter.status = &s;
- log::Reader reader(file, &reporter, true/*checksum*/, 0/*initial_offset*/);
+ log::Reader reader(file, &reporter, true /*checksum*/,
+ 0 /*initial_offset*/);
Slice record;
std::string scratch;
while (reader.ReadRecord(&record, &scratch) && s.ok()) {
@@ -982,7 +945,7 @@ Status VersionSet::Recover(bool *save_manifest) {
}
}
delete file;
- file = NULL;
+ file = nullptr;
if (s.ok()) {
if (!have_next_file) {
@@ -1040,12 +1003,12 @@ bool VersionSet::ReuseManifest(const std::string& dscname,
return false;
}
- assert(descriptor_file_ == NULL);
- assert(descriptor_log_ == NULL);
+ assert(descriptor_file_ == nullptr);
+ assert(descriptor_log_ == nullptr);
Status r = env_->NewAppendableFile(dscname, &descriptor_file_);
if (!r.ok()) {
Log(options_->info_log, "Reuse MANIFEST: %s\n", r.ToString().c_str());
- assert(descriptor_file_ == NULL);
+ assert(descriptor_file_ == nullptr);
return false;
}
@@ -1066,7 +1029,7 @@ void VersionSet::Finalize(Version* v) {
int best_level = -1;
double best_score = -1;
- for (int level = 0; level < config::kNumLevels-1; level++) {
+ for (int level = 0; level < config::kNumLevels - 1; level++) {
double score;
if (level == 0) {
// We treat level-0 specially by bounding the number of files
@@ -1081,7 +1044,7 @@ void VersionSet::Finalize(Version* v) {
// setting, or very high compression ratios, or lots of
// overwrites/deletions).
score = v->files_[level].size() /
- static_cast<double>(config::kL0_CompactionTrigger);
+ static_cast<double>(config::kL0_CompactionTrigger);
} else {
// Compute the ratio of current size to size limit.
const uint64_t level_bytes = TotalFileSize(v->files_[level]);
@@ -1137,16 +1100,12 @@ int VersionSet::NumLevelFiles(int level) const {
const char* VersionSet::LevelSummary(LevelSummaryStorage* scratch) const {
// Update code if kNumLevels changes
- assert(config::kNumLevels == 7);
+ static_assert(config::kNumLevels == 7, "");
snprintf(scratch->buffer, sizeof(scratch->buffer),
- "files[ %d %d %d %d %d %d %d ]",
- int(current_->files_[0].size()),
- int(current_->files_[1].size()),
- int(current_->files_[2].size()),
- int(current_->files_[3].size()),
- int(current_->files_[4].size()),
- int(current_->files_[5].size()),
- int(current_->files_[6].size()));
+ "files[ %d %d %d %d %d %d %d ]", int(current_->files_[0].size()),
+ int(current_->files_[1].size()), int(current_->files_[2].size()),
+ int(current_->files_[3].size()), int(current_->files_[4].size()),
+ int(current_->files_[5].size()), int(current_->files_[6].size()));
return scratch->buffer;
}
@@ -1172,7 +1131,7 @@ uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) {
Table* tableptr;
Iterator* iter = table_cache_->NewIterator(
ReadOptions(), files[i]->number, files[i]->file_size, &tableptr);
- if (tableptr != NULL) {
+ if (tableptr != nullptr) {
result += tableptr->ApproximateOffsetOf(ikey.Encode());
}
delete iter;
@@ -1183,8 +1142,7 @@ uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) {
}
void VersionSet::AddLiveFiles(std::set<uint64_t>* live) {
- for (Version* v = dummy_versions_.next_;
- v != &dummy_versions_;
+ for (Version* v = dummy_versions_.next_; v != &dummy_versions_;
v = v->next_) {
for (int level = 0; level < config::kNumLevels; level++) {
const std::vector<FileMetaData*>& files = v->files_[level];
@@ -1207,7 +1165,7 @@ int64_t VersionSet::MaxNextLevelOverlappingBytes() {
for (int level = 1; level < config::kNumLevels - 1; level++) {
for (size_t i = 0; i < current_->files_[level].size(); i++) {
const FileMetaData* f = current_->files_[level][i];
- current_->GetOverlappingInputs(level+1, &f->smallest, &f->largest,
+ current_->GetOverlappingInputs(level + 1, &f->smallest, &f->largest,
&overlaps);
const int64_t sum = TotalFileSize(overlaps);
if (sum > result) {
@@ -1222,8 +1180,7 @@ int64_t VersionSet::MaxNextLevelOverlappingBytes() {
// *smallest, *largest.
// REQUIRES: inputs is not empty
void VersionSet::GetRange(const std::vector<FileMetaData*>& inputs,
- InternalKey* smallest,
- InternalKey* largest) {
+ InternalKey* smallest, InternalKey* largest) {
assert(!inputs.empty());
smallest->Clear();
largest->Clear();
@@ -1248,8 +1205,7 @@ void VersionSet::GetRange(const std::vector<FileMetaData*>& inputs,
// REQUIRES: inputs is not empty
void VersionSet::GetRange2(const std::vector<FileMetaData*>& inputs1,
const std::vector<FileMetaData*>& inputs2,
- InternalKey* smallest,
- InternalKey* largest) {
+ InternalKey* smallest, InternalKey* largest) {
std::vector<FileMetaData*> all = inputs1;
all.insert(all.end(), inputs2.begin(), inputs2.end());
GetRange(all, smallest, largest);
@@ -1271,8 +1227,8 @@ Iterator* VersionSet::MakeInputIterator(Compaction* c) {
if (c->level() + which == 0) {
const std::vector<FileMetaData*>& files = c->inputs_[which];
for (size_t i = 0; i < files.size(); i++) {
- list[num++] = table_cache_->NewIterator(
- options, files[i]->number, files[i]->file_size);
+ list[num++] = table_cache_->NewIterator(options, files[i]->number,
+ files[i]->file_size);
}
} else {
// Create concatenating iterator for the files from this level
@@ -1295,11 +1251,11 @@ Compaction* VersionSet::PickCompaction() {
// We prefer compactions triggered by too much data in a level over
// the compactions triggered by seeks.
const bool size_compaction = (current_->compaction_score_ >= 1);
- const bool seek_compaction = (current_->file_to_compact_ != NULL);
+ const bool seek_compaction = (current_->file_to_compact_ != nullptr);
if (size_compaction) {
level = current_->compaction_level_;
assert(level >= 0);
- assert(level+1 < config::kNumLevels);
+ assert(level + 1 < config::kNumLevels);
c = new Compaction(options_, level);
// Pick the first file that comes after compact_pointer_[level]
@@ -1320,7 +1276,7 @@ Compaction* VersionSet::PickCompaction() {
c = new Compaction(options_, level);
c->inputs_[0].push_back(current_->file_to_compact_);
} else {
- return NULL;
+ return nullptr;
}
c->input_version_ = current_;
@@ -1342,12 +1298,94 @@ Compaction* VersionSet::PickCompaction() {
return c;
}
+// Finds the largest key in a vector of files. Returns true if files it not
+// empty.
+bool FindLargestKey(const InternalKeyComparator& icmp,
+ const std::vector<FileMetaData*>& files,
+ InternalKey* largest_key) {
+ if (files.empty()) {
+ return false;
+ }
+ *largest_key = files[0]->largest;
+ for (size_t i = 1; i < files.size(); ++i) {
+ FileMetaData* f = files[i];
+ if (icmp.Compare(f->largest, *largest_key) > 0) {
+ *largest_key = f->largest;
+ }
+ }
+ return true;
+}
+
+// Finds minimum file b2=(l2, u2) in level file for which l2 > u1 and
+// user_key(l2) = user_key(u1)
+FileMetaData* FindSmallestBoundaryFile(
+ const InternalKeyComparator& icmp,
+ const std::vector<FileMetaData*>& level_files,
+ const InternalKey& largest_key) {
+ const Comparator* user_cmp = icmp.user_comparator();
+ FileMetaData* smallest_boundary_file = nullptr;
+ for (size_t i = 0; i < level_files.size(); ++i) {
+ FileMetaData* f = level_files[i];
+ if (icmp.Compare(f->smallest, largest_key) > 0 &&
+ user_cmp->Compare(f->smallest.user_key(), largest_key.user_key()) ==
+ 0) {
+ if (smallest_boundary_file == nullptr ||
+ icmp.Compare(f->smallest, smallest_boundary_file->smallest) < 0) {
+ smallest_boundary_file = f;
+ }
+ }
+ }
+ return smallest_boundary_file;
+}
+
+// Extracts the largest file b1 from |compaction_files| and then searches for a
+// b2 in |level_files| for which user_key(u1) = user_key(l2). If it finds such a
+// file b2 (known as a boundary file) it adds it to |compaction_files| and then
+// searches again using this new upper bound.
+//
+// If there are two blocks, b1=(l1, u1) and b2=(l2, u2) and
+// user_key(u1) = user_key(l2), and if we compact b1 but not b2 then a
+// subsequent get operation will yield an incorrect result because it will
+// return the record from b2 in level i rather than from b1 because it searches
+// level by level for records matching the supplied user key.
+//
+// parameters:
+// in level_files: List of files to search for boundary files.
+// in/out compaction_files: List of files to extend by adding boundary files.
+void AddBoundaryInputs(const InternalKeyComparator& icmp,
+ const std::vector<FileMetaData*>& level_files,
+ std::vector<FileMetaData*>* compaction_files) {
+ InternalKey largest_key;
+
+ // Quick return if compaction_files is empty.
+ if (!FindLargestKey(icmp, *compaction_files, &largest_key)) {
+ return;
+ }
+
+ bool continue_searching = true;
+ while (continue_searching) {
+ FileMetaData* smallest_boundary_file =
+ FindSmallestBoundaryFile(icmp, level_files, largest_key);
+
+ // If a boundary file was found advance largest_key, otherwise we're done.
+ if (smallest_boundary_file != NULL) {
+ compaction_files->push_back(smallest_boundary_file);
+ largest_key = smallest_boundary_file->largest;
+ } else {
+ continue_searching = false;
+ }
+ }
+}
+
void VersionSet::SetupOtherInputs(Compaction* c) {
const int level = c->level();
InternalKey smallest, largest;
+
+ AddBoundaryInputs(icmp_, current_->files_[level], &c->inputs_[0]);
GetRange(c->inputs_[0], &smallest, &largest);
- current_->GetOverlappingInputs(level+1, &smallest, &largest, &c->inputs_[1]);
+ current_->GetOverlappingInputs(level + 1, &smallest, &largest,
+ &c->inputs_[1]);
// Get entire range covered by compaction
InternalKey all_start, all_limit;
@@ -1358,6 +1396,7 @@ void VersionSet::SetupOtherInputs(Compaction* c) {
if (!c->inputs_[1].empty()) {
std::vector<FileMetaData*> expanded0;
current_->GetOverlappingInputs(level, &all_start, &all_limit, &expanded0);
+ AddBoundaryInputs(icmp_, current_->files_[level], &expanded0);
const int64_t inputs0_size = TotalFileSize(c->inputs_[0]);
const int64_t inputs1_size = TotalFileSize(c->inputs_[1]);
const int64_t expanded0_size = TotalFileSize(expanded0);
@@ -1367,18 +1406,14 @@ void VersionSet::SetupOtherInputs(Compaction* c) {
InternalKey new_start, new_limit;
GetRange(expanded0, &new_start, &new_limit);
std::vector<FileMetaData*> expanded1;
- current_->GetOverlappingInputs(level+1, &new_start, &new_limit,
+ current_->GetOverlappingInputs(level + 1, &new_start, &new_limit,
&expanded1);
if (expanded1.size() == c->inputs_[1].size()) {
Log(options_->info_log,
"Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n",
- level,
- int(c->inputs_[0].size()),
- int(c->inputs_[1].size()),
- long(inputs0_size), long(inputs1_size),
- int(expanded0.size()),
- int(expanded1.size()),
- long(expanded0_size), long(inputs1_size));
+ level, int(c->inputs_[0].size()), int(c->inputs_[1].size()),
+ long(inputs0_size), long(inputs1_size), int(expanded0.size()),
+ int(expanded1.size()), long(expanded0_size), long(inputs1_size));
smallest = new_start;
largest = new_limit;
c->inputs_[0] = expanded0;
@@ -1395,13 +1430,6 @@ void VersionSet::SetupOtherInputs(Compaction* c) {
&c->grandparents_);
}
- if (false) {
- Log(options_->info_log, "Compacting %d '%s' .. '%s'",
- level,
- smallest.DebugString().c_str(),
- largest.DebugString().c_str());
- }
-
// Update the place where we will do the next compaction for this level.
// We update this immediately instead of waiting for the VersionEdit
// to be applied so that if the compaction fails, we will try a different
@@ -1410,14 +1438,12 @@ void VersionSet::SetupOtherInputs(Compaction* c) {
c->edit_.SetCompactPointer(level, largest);
}
-Compaction* VersionSet::CompactRange(
- int level,
- const InternalKey* begin,
- const InternalKey* end) {
+Compaction* VersionSet::CompactRange(int level, const InternalKey* begin,
+ const InternalKey* end) {
std::vector<FileMetaData*> inputs;
current_->GetOverlappingInputs(level, begin, end, &inputs);
if (inputs.empty()) {
- return NULL;
+ return nullptr;
}
// Avoid compacting too much in one shot in case the range is large.
@@ -1448,7 +1474,7 @@ Compaction* VersionSet::CompactRange(
Compaction::Compaction(const Options* options, int level)
: level_(level),
max_output_file_size_(MaxFileSizeForLevel(options, level)),
- input_version_(NULL),
+ input_version_(nullptr),
grandparent_index_(0),
seen_key_(false),
overlapped_bytes_(0) {
@@ -1458,7 +1484,7 @@ Compaction::Compaction(const Options* options, int level)
}
Compaction::~Compaction() {
- if (input_version_ != NULL) {
+ if (input_version_ != nullptr) {
input_version_->Unref();
}
}
@@ -1486,7 +1512,7 @@ bool Compaction::IsBaseLevelForKey(const Slice& user_key) {
const Comparator* user_cmp = input_version_->vset_->icmp_.user_comparator();
for (int lvl = level_ + 2; lvl < config::kNumLevels; lvl++) {
const std::vector<FileMetaData*>& files = input_version_->files_[lvl];
- for (; level_ptrs_[lvl] < files.size(); ) {
+ while (level_ptrs_[lvl] < files.size()) {
FileMetaData* f = files[level_ptrs_[lvl]];
if (user_cmp->Compare(user_key, f->largest.user_key()) <= 0) {
// We've advanced far enough
@@ -1507,8 +1533,9 @@ bool Compaction::ShouldStopBefore(const Slice& internal_key) {
// Scan to find earliest grandparent file that contains key.
const InternalKeyComparator* icmp = &vset->icmp_;
while (grandparent_index_ < grandparents_.size() &&
- icmp->Compare(internal_key,
- grandparents_[grandparent_index_]->largest.Encode()) > 0) {
+ icmp->Compare(internal_key,
+ grandparents_[grandparent_index_]->largest.Encode()) >
+ 0) {
if (seen_key_) {
overlapped_bytes_ += grandparents_[grandparent_index_]->file_size;
}
@@ -1526,9 +1553,9 @@ bool Compaction::ShouldStopBefore(const Slice& internal_key) {
}
void Compaction::ReleaseInputs() {
- if (input_version_ != NULL) {
+ if (input_version_ != nullptr) {
input_version_->Unref();
- input_version_ = NULL;
+ input_version_ = nullptr;
}
}
diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h
index 7935a965a7..69f3d70133 100644
--- a/src/leveldb/db/version_set.h
+++ b/src/leveldb/db/version_set.h
@@ -18,6 +18,7 @@
#include <map>
#include <set>
#include <vector>
+
#include "db/dbformat.h"
#include "db/version_edit.h"
#include "port/port.h"
@@ -25,7 +26,9 @@
namespace leveldb {
-namespace log { class Writer; }
+namespace log {
+class Writer;
+}
class Compaction;
class Iterator;
@@ -39,30 +42,23 @@ class WritableFile;
// Return the smallest index i such that files[i]->largest >= key.
// Return files.size() if there is no such file.
// REQUIRES: "files" contains a sorted list of non-overlapping files.
-extern int FindFile(const InternalKeyComparator& icmp,
- const std::vector<FileMetaData*>& files,
- const Slice& key);
+int FindFile(const InternalKeyComparator& icmp,
+ const std::vector<FileMetaData*>& files, const Slice& key);
// Returns true iff some file in "files" overlaps the user key range
// [*smallest,*largest].
-// smallest==NULL represents a key smaller than all keys in the DB.
-// largest==NULL represents a key largest than all keys in the DB.
+// smallest==nullptr represents a key smaller than all keys in the DB.
+// largest==nullptr represents a key largest than all keys in the DB.
// REQUIRES: If disjoint_sorted_files, files[] contains disjoint ranges
// in sorted order.
-extern bool SomeFileOverlapsRange(
- const InternalKeyComparator& icmp,
- bool disjoint_sorted_files,
- const std::vector<FileMetaData*>& files,
- const Slice* smallest_user_key,
- const Slice* largest_user_key);
+bool SomeFileOverlapsRange(const InternalKeyComparator& icmp,
+ bool disjoint_sorted_files,
+ const std::vector<FileMetaData*>& files,
+ const Slice* smallest_user_key,
+ const Slice* largest_user_key);
class Version {
public:
- // Append to *iters a sequence of iterators that will
- // yield the contents of this Version when merged together.
- // REQUIRES: This version has been saved (see VersionSet::SaveTo)
- void AddIterators(const ReadOptions&, std::vector<Iterator*>* iters);
-
// Lookup the value for key. If found, store it in *val and
// return OK. Else return a non-OK status. Fills *stats.
// REQUIRES: lock is not held
@@ -70,6 +66,12 @@ class Version {
FileMetaData* seek_file;
int seek_file_level;
};
+
+ // Append to *iters a sequence of iterators that will
+ // yield the contents of this Version when merged together.
+ // REQUIRES: This version has been saved (see VersionSet::SaveTo)
+ void AddIterators(const ReadOptions&, std::vector<Iterator*>* iters);
+
Status Get(const ReadOptions&, const LookupKey& key, std::string* val,
GetStats* stats);
@@ -91,16 +93,15 @@ class Version {
void GetOverlappingInputs(
int level,
- const InternalKey* begin, // NULL means before all keys
- const InternalKey* end, // NULL means after all keys
+ const InternalKey* begin, // nullptr means before all keys
+ const InternalKey* end, // nullptr means after all keys
std::vector<FileMetaData*>* inputs);
// Returns true iff some file in the specified level overlaps
// some part of [*smallest_user_key,*largest_user_key].
- // smallest_user_key==NULL represents a key smaller than all keys in the DB.
- // largest_user_key==NULL represents a key largest than all keys in the DB.
- bool OverlapInLevel(int level,
- const Slice* smallest_user_key,
+ // smallest_user_key==nullptr represents a key smaller than all the DB's keys.
+ // largest_user_key==nullptr represents a key largest than all the DB's keys.
+ bool OverlapInLevel(int level, const Slice* smallest_user_key,
const Slice* largest_user_key);
// Return the level at which we should place a new memtable compaction
@@ -118,6 +119,22 @@ class Version {
friend class VersionSet;
class LevelFileNumIterator;
+
+ explicit Version(VersionSet* vset)
+ : vset_(vset),
+ next_(this),
+ prev_(this),
+ refs_(0),
+ file_to_compact_(nullptr),
+ file_to_compact_level_(-1),
+ compaction_score_(-1),
+ compaction_level_(-1) {}
+
+ Version(const Version&) = delete;
+ Version& operator=(const Version&) = delete;
+
+ ~Version();
+
Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const;
// Call func(arg, level, f) for every file that overlaps user_key in
@@ -125,14 +142,13 @@ class Version {
// false, makes no more calls.
//
// REQUIRES: user portion of internal_key == user_key.
- void ForEachOverlapping(Slice user_key, Slice internal_key,
- void* arg,
+ void ForEachOverlapping(Slice user_key, Slice internal_key, void* arg,
bool (*func)(void*, int, FileMetaData*));
- VersionSet* vset_; // VersionSet to which this Version belongs
- Version* next_; // Next version in linked list
- Version* prev_; // Previous version in linked list
- int refs_; // Number of live refs to this version
+ VersionSet* vset_; // VersionSet to which this Version belongs
+ Version* next_; // Next version in linked list
+ Version* prev_; // Previous version in linked list
+ int refs_; // Number of live refs to this version
// List of files per level
std::vector<FileMetaData*> files_[config::kNumLevels];
@@ -146,28 +162,15 @@ class Version {
// are initialized by Finalize().
double compaction_score_;
int compaction_level_;
-
- explicit Version(VersionSet* vset)
- : vset_(vset), next_(this), prev_(this), refs_(0),
- file_to_compact_(NULL),
- file_to_compact_level_(-1),
- compaction_score_(-1),
- compaction_level_(-1) {
- }
-
- ~Version();
-
- // No copying allowed
- Version(const Version&);
- void operator=(const Version&);
};
class VersionSet {
public:
- VersionSet(const std::string& dbname,
- const Options* options,
- TableCache* table_cache,
- const InternalKeyComparator*);
+ VersionSet(const std::string& dbname, const Options* options,
+ TableCache* table_cache, const InternalKeyComparator*);
+ VersionSet(const VersionSet&) = delete;
+ VersionSet& operator=(const VersionSet&) = delete;
+
~VersionSet();
// Apply *edit to the current version to form a new descriptor that
@@ -179,7 +182,7 @@ class VersionSet {
EXCLUSIVE_LOCKS_REQUIRED(mu);
// Recover the last saved descriptor from persistent storage.
- Status Recover(bool *save_manifest);
+ Status Recover(bool* save_manifest);
// Return the current version.
Version* current() const { return current_; }
@@ -225,19 +228,17 @@ class VersionSet {
uint64_t PrevLogNumber() const { return prev_log_number_; }
// Pick level and inputs for a new compaction.
- // Returns NULL if there is no compaction to be done.
+ // Returns nullptr if there is no compaction to be done.
// Otherwise returns a pointer to a heap-allocated object that
// describes the compaction. Caller should delete the result.
Compaction* PickCompaction();
// Return a compaction object for compacting the range [begin,end] in
- // the specified level. Returns NULL if there is nothing in that
+ // the specified level. Returns nullptr if there is nothing in that
// level that overlaps the specified range. Caller should delete
// the result.
- Compaction* CompactRange(
- int level,
- const InternalKey* begin,
- const InternalKey* end);
+ Compaction* CompactRange(int level, const InternalKey* begin,
+ const InternalKey* end);
// Return the maximum overlapping data (in bytes) at next level for any
// file at a level >= 1.
@@ -250,7 +251,7 @@ class VersionSet {
// Returns true iff some level needs a compaction.
bool NeedsCompaction() const {
Version* v = current_;
- return (v->compaction_score_ >= 1) || (v->file_to_compact_ != NULL);
+ return (v->compaction_score_ >= 1) || (v->file_to_compact_ != nullptr);
}
// Add all files listed in any live version to *live.
@@ -278,14 +279,12 @@ class VersionSet {
void Finalize(Version* v);
- void GetRange(const std::vector<FileMetaData*>& inputs,
- InternalKey* smallest,
+ void GetRange(const std::vector<FileMetaData*>& inputs, InternalKey* smallest,
InternalKey* largest);
void GetRange2(const std::vector<FileMetaData*>& inputs1,
const std::vector<FileMetaData*>& inputs2,
- InternalKey* smallest,
- InternalKey* largest);
+ InternalKey* smallest, InternalKey* largest);
void SetupOtherInputs(Compaction* c);
@@ -314,10 +313,6 @@ class VersionSet {
// Per-level key at which the next compaction at that level should start.
// Either an empty string, or a valid InternalKey.
std::string compact_pointer_[config::kNumLevels];
-
- // No copying allowed
- VersionSet(const VersionSet&);
- void operator=(const VersionSet&);
};
// A Compaction encapsulates information about a compaction.
@@ -374,7 +369,7 @@ class Compaction {
VersionEdit edit_;
// Each compaction reads inputs from "level_" and "level_+1"
- std::vector<FileMetaData*> inputs_[2]; // The two sets of inputs
+ std::vector<FileMetaData*> inputs_[2]; // The two sets of inputs
// State used to check for number of overlapping grandparent files
// (parent == level_ + 1, grandparent == level_ + 2)
diff --git a/src/leveldb/db/version_set_test.cc b/src/leveldb/db/version_set_test.cc
index 501e34d133..c1056a1e7d 100644
--- a/src/leveldb/db/version_set_test.cc
+++ b/src/leveldb/db/version_set_test.cc
@@ -11,10 +11,7 @@ namespace leveldb {
class FindFileTest {
public:
- std::vector<FileMetaData*> files_;
- bool disjoint_sorted_files_;
-
- FindFileTest() : disjoint_sorted_files_(true) { }
+ FindFileTest() : disjoint_sorted_files_(true) {}
~FindFileTest() {
for (int i = 0; i < files_.size(); i++) {
@@ -40,20 +37,25 @@ class FindFileTest {
bool Overlaps(const char* smallest, const char* largest) {
InternalKeyComparator cmp(BytewiseComparator());
- Slice s(smallest != NULL ? smallest : "");
- Slice l(largest != NULL ? largest : "");
+ Slice s(smallest != nullptr ? smallest : "");
+ Slice l(largest != nullptr ? largest : "");
return SomeFileOverlapsRange(cmp, disjoint_sorted_files_, files_,
- (smallest != NULL ? &s : NULL),
- (largest != NULL ? &l : NULL));
+ (smallest != nullptr ? &s : nullptr),
+ (largest != nullptr ? &l : nullptr));
}
+
+ bool disjoint_sorted_files_;
+
+ private:
+ std::vector<FileMetaData*> files_;
};
TEST(FindFileTest, Empty) {
ASSERT_EQ(0, Find("foo"));
- ASSERT_TRUE(! Overlaps("a", "z"));
- ASSERT_TRUE(! Overlaps(NULL, "z"));
- ASSERT_TRUE(! Overlaps("a", NULL));
- ASSERT_TRUE(! Overlaps(NULL, NULL));
+ ASSERT_TRUE(!Overlaps("a", "z"));
+ ASSERT_TRUE(!Overlaps(nullptr, "z"));
+ ASSERT_TRUE(!Overlaps("a", nullptr));
+ ASSERT_TRUE(!Overlaps(nullptr, nullptr));
}
TEST(FindFileTest, Single) {
@@ -65,8 +67,8 @@ TEST(FindFileTest, Single) {
ASSERT_EQ(1, Find("q1"));
ASSERT_EQ(1, Find("z"));
- ASSERT_TRUE(! Overlaps("a", "b"));
- ASSERT_TRUE(! Overlaps("z1", "z2"));
+ ASSERT_TRUE(!Overlaps("a", "b"));
+ ASSERT_TRUE(!Overlaps("z1", "z2"));
ASSERT_TRUE(Overlaps("a", "p"));
ASSERT_TRUE(Overlaps("a", "q"));
ASSERT_TRUE(Overlaps("a", "z"));
@@ -78,15 +80,14 @@ TEST(FindFileTest, Single) {
ASSERT_TRUE(Overlaps("q", "q"));
ASSERT_TRUE(Overlaps("q", "q1"));
- ASSERT_TRUE(! Overlaps(NULL, "j"));
- ASSERT_TRUE(! Overlaps("r", NULL));
- ASSERT_TRUE(Overlaps(NULL, "p"));
- ASSERT_TRUE(Overlaps(NULL, "p1"));
- ASSERT_TRUE(Overlaps("q", NULL));
- ASSERT_TRUE(Overlaps(NULL, NULL));
+ ASSERT_TRUE(!Overlaps(nullptr, "j"));
+ ASSERT_TRUE(!Overlaps("r", nullptr));
+ ASSERT_TRUE(Overlaps(nullptr, "p"));
+ ASSERT_TRUE(Overlaps(nullptr, "p1"));
+ ASSERT_TRUE(Overlaps("q", nullptr));
+ ASSERT_TRUE(Overlaps(nullptr, nullptr));
}
-
TEST(FindFileTest, Multiple) {
Add("150", "200");
Add("200", "250");
@@ -110,10 +111,10 @@ TEST(FindFileTest, Multiple) {
ASSERT_EQ(3, Find("450"));
ASSERT_EQ(4, Find("451"));
- ASSERT_TRUE(! Overlaps("100", "149"));
- ASSERT_TRUE(! Overlaps("251", "299"));
- ASSERT_TRUE(! Overlaps("451", "500"));
- ASSERT_TRUE(! Overlaps("351", "399"));
+ ASSERT_TRUE(!Overlaps("100", "149"));
+ ASSERT_TRUE(!Overlaps("251", "299"));
+ ASSERT_TRUE(!Overlaps("451", "500"));
+ ASSERT_TRUE(!Overlaps("351", "399"));
ASSERT_TRUE(Overlaps("100", "150"));
ASSERT_TRUE(Overlaps("100", "200"));
@@ -130,25 +131,25 @@ TEST(FindFileTest, MultipleNullBoundaries) {
Add("200", "250");
Add("300", "350");
Add("400", "450");
- ASSERT_TRUE(! Overlaps(NULL, "149"));
- ASSERT_TRUE(! Overlaps("451", NULL));
- ASSERT_TRUE(Overlaps(NULL, NULL));
- ASSERT_TRUE(Overlaps(NULL, "150"));
- ASSERT_TRUE(Overlaps(NULL, "199"));
- ASSERT_TRUE(Overlaps(NULL, "200"));
- ASSERT_TRUE(Overlaps(NULL, "201"));
- ASSERT_TRUE(Overlaps(NULL, "400"));
- ASSERT_TRUE(Overlaps(NULL, "800"));
- ASSERT_TRUE(Overlaps("100", NULL));
- ASSERT_TRUE(Overlaps("200", NULL));
- ASSERT_TRUE(Overlaps("449", NULL));
- ASSERT_TRUE(Overlaps("450", NULL));
+ ASSERT_TRUE(!Overlaps(nullptr, "149"));
+ ASSERT_TRUE(!Overlaps("451", nullptr));
+ ASSERT_TRUE(Overlaps(nullptr, nullptr));
+ ASSERT_TRUE(Overlaps(nullptr, "150"));
+ ASSERT_TRUE(Overlaps(nullptr, "199"));
+ ASSERT_TRUE(Overlaps(nullptr, "200"));
+ ASSERT_TRUE(Overlaps(nullptr, "201"));
+ ASSERT_TRUE(Overlaps(nullptr, "400"));
+ ASSERT_TRUE(Overlaps(nullptr, "800"));
+ ASSERT_TRUE(Overlaps("100", nullptr));
+ ASSERT_TRUE(Overlaps("200", nullptr));
+ ASSERT_TRUE(Overlaps("449", nullptr));
+ ASSERT_TRUE(Overlaps("450", nullptr));
}
TEST(FindFileTest, OverlapSequenceChecks) {
Add("200", "200", 5000, 3000);
- ASSERT_TRUE(! Overlaps("199", "199"));
- ASSERT_TRUE(! Overlaps("201", "300"));
+ ASSERT_TRUE(!Overlaps("199", "199"));
+ ASSERT_TRUE(!Overlaps("201", "300"));
ASSERT_TRUE(Overlaps("200", "200"));
ASSERT_TRUE(Overlaps("190", "200"));
ASSERT_TRUE(Overlaps("200", "210"));
@@ -158,8 +159,8 @@ TEST(FindFileTest, OverlappingFiles) {
Add("150", "600");
Add("400", "500");
disjoint_sorted_files_ = false;
- ASSERT_TRUE(! Overlaps("100", "149"));
- ASSERT_TRUE(! Overlaps("601", "700"));
+ ASSERT_TRUE(!Overlaps("100", "149"));
+ ASSERT_TRUE(!Overlaps("601", "700"));
ASSERT_TRUE(Overlaps("100", "150"));
ASSERT_TRUE(Overlaps("100", "200"));
ASSERT_TRUE(Overlaps("100", "300"));
@@ -172,8 +173,160 @@ TEST(FindFileTest, OverlappingFiles) {
ASSERT_TRUE(Overlaps("600", "700"));
}
-} // namespace leveldb
+void AddBoundaryInputs(const InternalKeyComparator& icmp,
+ const std::vector<FileMetaData*>& level_files,
+ std::vector<FileMetaData*>* compaction_files);
+
+class AddBoundaryInputsTest {
+ public:
+ std::vector<FileMetaData*> level_files_;
+ std::vector<FileMetaData*> compaction_files_;
+ std::vector<FileMetaData*> all_files_;
+ InternalKeyComparator icmp_;
+
+ AddBoundaryInputsTest() : icmp_(BytewiseComparator()) {}
+
+ ~AddBoundaryInputsTest() {
+ for (size_t i = 0; i < all_files_.size(); ++i) {
+ delete all_files_[i];
+ }
+ all_files_.clear();
+ }
+
+ FileMetaData* CreateFileMetaData(uint64_t number, InternalKey smallest,
+ InternalKey largest) {
+ FileMetaData* f = new FileMetaData();
+ f->number = number;
+ f->smallest = smallest;
+ f->largest = largest;
+ all_files_.push_back(f);
+ return f;
+ }
+};
+
+TEST(AddBoundaryInputsTest, TestEmptyFileSets) {
+ AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
+ ASSERT_TRUE(compaction_files_.empty());
+ ASSERT_TRUE(level_files_.empty());
+}
+
+TEST(AddBoundaryInputsTest, TestEmptyLevelFiles) {
+ FileMetaData* f1 =
+ CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
+ InternalKey(InternalKey("100", 1, kTypeValue)));
+ compaction_files_.push_back(f1);
+
+ AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
+ ASSERT_EQ(1, compaction_files_.size());
+ ASSERT_EQ(f1, compaction_files_[0]);
+ ASSERT_TRUE(level_files_.empty());
+}
+
+TEST(AddBoundaryInputsTest, TestEmptyCompactionFiles) {
+ FileMetaData* f1 =
+ CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
+ InternalKey(InternalKey("100", 1, kTypeValue)));
+ level_files_.push_back(f1);
+
+ AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
+ ASSERT_TRUE(compaction_files_.empty());
+ ASSERT_EQ(1, level_files_.size());
+ ASSERT_EQ(f1, level_files_[0]);
+}
+
+TEST(AddBoundaryInputsTest, TestNoBoundaryFiles) {
+ FileMetaData* f1 =
+ CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
+ InternalKey(InternalKey("100", 1, kTypeValue)));
+ FileMetaData* f2 =
+ CreateFileMetaData(1, InternalKey("200", 2, kTypeValue),
+ InternalKey(InternalKey("200", 1, kTypeValue)));
+ FileMetaData* f3 =
+ CreateFileMetaData(1, InternalKey("300", 2, kTypeValue),
+ InternalKey(InternalKey("300", 1, kTypeValue)));
+
+ level_files_.push_back(f3);
+ level_files_.push_back(f2);
+ level_files_.push_back(f1);
+ compaction_files_.push_back(f2);
+ compaction_files_.push_back(f3);
+
+ AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
+ ASSERT_EQ(2, compaction_files_.size());
+}
+
+TEST(AddBoundaryInputsTest, TestOneBoundaryFiles) {
+ FileMetaData* f1 =
+ CreateFileMetaData(1, InternalKey("100", 3, kTypeValue),
+ InternalKey(InternalKey("100", 2, kTypeValue)));
+ FileMetaData* f2 =
+ CreateFileMetaData(1, InternalKey("100", 1, kTypeValue),
+ InternalKey(InternalKey("200", 3, kTypeValue)));
+ FileMetaData* f3 =
+ CreateFileMetaData(1, InternalKey("300", 2, kTypeValue),
+ InternalKey(InternalKey("300", 1, kTypeValue)));
+
+ level_files_.push_back(f3);
+ level_files_.push_back(f2);
+ level_files_.push_back(f1);
+ compaction_files_.push_back(f1);
+
+ AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
+ ASSERT_EQ(2, compaction_files_.size());
+ ASSERT_EQ(f1, compaction_files_[0]);
+ ASSERT_EQ(f2, compaction_files_[1]);
+}
+
+TEST(AddBoundaryInputsTest, TestTwoBoundaryFiles) {
+ FileMetaData* f1 =
+ CreateFileMetaData(1, InternalKey("100", 6, kTypeValue),
+ InternalKey(InternalKey("100", 5, kTypeValue)));
+ FileMetaData* f2 =
+ CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
+ InternalKey(InternalKey("300", 1, kTypeValue)));
+ FileMetaData* f3 =
+ CreateFileMetaData(1, InternalKey("100", 4, kTypeValue),
+ InternalKey(InternalKey("100", 3, kTypeValue)));
+
+ level_files_.push_back(f2);
+ level_files_.push_back(f3);
+ level_files_.push_back(f1);
+ compaction_files_.push_back(f1);
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
+ AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
+ ASSERT_EQ(3, compaction_files_.size());
+ ASSERT_EQ(f1, compaction_files_[0]);
+ ASSERT_EQ(f3, compaction_files_[1]);
+ ASSERT_EQ(f2, compaction_files_[2]);
}
+
+TEST(AddBoundaryInputsTest, TestDisjoinFilePointers) {
+ FileMetaData* f1 =
+ CreateFileMetaData(1, InternalKey("100", 6, kTypeValue),
+ InternalKey(InternalKey("100", 5, kTypeValue)));
+ FileMetaData* f2 =
+ CreateFileMetaData(1, InternalKey("100", 6, kTypeValue),
+ InternalKey(InternalKey("100", 5, kTypeValue)));
+ FileMetaData* f3 =
+ CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
+ InternalKey(InternalKey("300", 1, kTypeValue)));
+ FileMetaData* f4 =
+ CreateFileMetaData(1, InternalKey("100", 4, kTypeValue),
+ InternalKey(InternalKey("100", 3, kTypeValue)));
+
+ level_files_.push_back(f2);
+ level_files_.push_back(f3);
+ level_files_.push_back(f4);
+
+ compaction_files_.push_back(f1);
+
+ AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
+ ASSERT_EQ(3, compaction_files_.size());
+ ASSERT_EQ(f1, compaction_files_[0]);
+ ASSERT_EQ(f4, compaction_files_[1]);
+ ASSERT_EQ(f3, compaction_files_[2]);
+}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/db/write_batch.cc b/src/leveldb/db/write_batch.cc
index 33f4a4257e..b54313c35e 100644
--- a/src/leveldb/db/write_batch.cc
+++ b/src/leveldb/db/write_batch.cc
@@ -15,10 +15,10 @@
#include "leveldb/write_batch.h"
-#include "leveldb/db.h"
#include "db/dbformat.h"
#include "db/memtable.h"
#include "db/write_batch_internal.h"
+#include "leveldb/db.h"
#include "util/coding.h"
namespace leveldb {
@@ -26,19 +26,19 @@ namespace leveldb {
// WriteBatch header has an 8-byte sequence number followed by a 4-byte count.
static const size_t kHeader = 12;
-WriteBatch::WriteBatch() {
- Clear();
-}
+WriteBatch::WriteBatch() { Clear(); }
-WriteBatch::~WriteBatch() { }
+WriteBatch::~WriteBatch() = default;
-WriteBatch::Handler::~Handler() { }
+WriteBatch::Handler::~Handler() = default;
void WriteBatch::Clear() {
rep_.clear();
rep_.resize(kHeader);
}
+size_t WriteBatch::ApproximateSize() const { return rep_.size(); }
+
Status WriteBatch::Iterate(Handler* handler) const {
Slice input(rep_);
if (input.size() < kHeader) {
@@ -108,25 +108,28 @@ void WriteBatch::Delete(const Slice& key) {
PutLengthPrefixedSlice(&rep_, key);
}
+void WriteBatch::Append(const WriteBatch& source) {
+ WriteBatchInternal::Append(this, &source);
+}
+
namespace {
class MemTableInserter : public WriteBatch::Handler {
public:
SequenceNumber sequence_;
MemTable* mem_;
- virtual void Put(const Slice& key, const Slice& value) {
+ void Put(const Slice& key, const Slice& value) override {
mem_->Add(sequence_, kTypeValue, key, value);
sequence_++;
}
- virtual void Delete(const Slice& key) {
+ void Delete(const Slice& key) override {
mem_->Add(sequence_, kTypeDeletion, key, Slice());
sequence_++;
}
};
} // namespace
-Status WriteBatchInternal::InsertInto(const WriteBatch* b,
- MemTable* memtable) {
+Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) {
MemTableInserter inserter;
inserter.sequence_ = WriteBatchInternal::Sequence(b);
inserter.mem_ = memtable;
diff --git a/src/leveldb/db/write_batch_internal.h b/src/leveldb/db/write_batch_internal.h
index 9448ef7b21..fce86e3f1f 100644
--- a/src/leveldb/db/write_batch_internal.h
+++ b/src/leveldb/db/write_batch_internal.h
@@ -29,13 +29,9 @@ class WriteBatchInternal {
// this batch.
static void SetSequence(WriteBatch* batch, SequenceNumber seq);
- static Slice Contents(const WriteBatch* batch) {
- return Slice(batch->rep_);
- }
+ static Slice Contents(const WriteBatch* batch) { return Slice(batch->rep_); }
- static size_t ByteSize(const WriteBatch* batch) {
- return batch->rep_.size();
- }
+ static size_t ByteSize(const WriteBatch* batch) { return batch->rep_.size(); }
static void SetContents(WriteBatch* batch, const Slice& contents);
@@ -46,5 +42,4 @@ class WriteBatchInternal {
} // namespace leveldb
-
#endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_
diff --git a/src/leveldb/db/write_batch_test.cc b/src/leveldb/db/write_batch_test.cc
index 9064e3d85e..c32317fb5e 100644
--- a/src/leveldb/db/write_batch_test.cc
+++ b/src/leveldb/db/write_batch_test.cc
@@ -52,7 +52,7 @@ static std::string PrintContents(WriteBatch* b) {
return state;
}
-class WriteBatchTest { };
+class WriteBatchTest {};
TEST(WriteBatchTest, Empty) {
WriteBatch batch;
@@ -68,10 +68,11 @@ TEST(WriteBatchTest, Multiple) {
WriteBatchInternal::SetSequence(&batch, 100);
ASSERT_EQ(100, WriteBatchInternal::Sequence(&batch));
ASSERT_EQ(3, WriteBatchInternal::Count(&batch));
- ASSERT_EQ("Put(baz, boo)@102"
- "Delete(box)@101"
- "Put(foo, bar)@100",
- PrintContents(&batch));
+ ASSERT_EQ(
+ "Put(baz, boo)@102"
+ "Delete(box)@101"
+ "Put(foo, bar)@100",
+ PrintContents(&batch));
}
TEST(WriteBatchTest, Corruption) {
@@ -81,40 +82,56 @@ TEST(WriteBatchTest, Corruption) {
WriteBatchInternal::SetSequence(&batch, 200);
Slice contents = WriteBatchInternal::Contents(&batch);
WriteBatchInternal::SetContents(&batch,
- Slice(contents.data(),contents.size()-1));
- ASSERT_EQ("Put(foo, bar)@200"
- "ParseError()",
- PrintContents(&batch));
+ Slice(contents.data(), contents.size() - 1));
+ ASSERT_EQ(
+ "Put(foo, bar)@200"
+ "ParseError()",
+ PrintContents(&batch));
}
TEST(WriteBatchTest, Append) {
WriteBatch b1, b2;
WriteBatchInternal::SetSequence(&b1, 200);
WriteBatchInternal::SetSequence(&b2, 300);
- WriteBatchInternal::Append(&b1, &b2);
- ASSERT_EQ("",
- PrintContents(&b1));
+ b1.Append(b2);
+ ASSERT_EQ("", PrintContents(&b1));
b2.Put("a", "va");
- WriteBatchInternal::Append(&b1, &b2);
- ASSERT_EQ("Put(a, va)@200",
- PrintContents(&b1));
+ b1.Append(b2);
+ ASSERT_EQ("Put(a, va)@200", PrintContents(&b1));
b2.Clear();
b2.Put("b", "vb");
- WriteBatchInternal::Append(&b1, &b2);
- ASSERT_EQ("Put(a, va)@200"
- "Put(b, vb)@201",
- PrintContents(&b1));
+ b1.Append(b2);
+ ASSERT_EQ(
+ "Put(a, va)@200"
+ "Put(b, vb)@201",
+ PrintContents(&b1));
b2.Delete("foo");
- WriteBatchInternal::Append(&b1, &b2);
- ASSERT_EQ("Put(a, va)@200"
- "Put(b, vb)@202"
- "Put(b, vb)@201"
- "Delete(foo)@203",
- PrintContents(&b1));
+ b1.Append(b2);
+ ASSERT_EQ(
+ "Put(a, va)@200"
+ "Put(b, vb)@202"
+ "Put(b, vb)@201"
+ "Delete(foo)@203",
+ PrintContents(&b1));
}
-} // namespace leveldb
+TEST(WriteBatchTest, ApproximateSize) {
+ WriteBatch batch;
+ size_t empty_size = batch.ApproximateSize();
+
+ batch.Put(Slice("foo"), Slice("bar"));
+ size_t one_key_size = batch.ApproximateSize();
+ ASSERT_LT(empty_size, one_key_size);
+
+ batch.Put(Slice("baz"), Slice("boo"));
+ size_t two_keys_size = batch.ApproximateSize();
+ ASSERT_LT(one_key_size, two_keys_size);
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
+ batch.Delete(Slice("box"));
+ size_t post_delete_size = batch.ApproximateSize();
+ ASSERT_LT(two_keys_size, post_delete_size);
}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/doc/benchmark.html b/src/leveldb/doc/benchmark.html
index c4639772c1..f3fd77144c 100644
--- a/src/leveldb/doc/benchmark.html
+++ b/src/leveldb/doc/benchmark.html
@@ -90,9 +90,9 @@ div.bsql {
<h4>Benchmark Source Code</h4>
<p>We wrote benchmark tools for SQLite and Kyoto TreeDB based on LevelDB's <span class="code">db_bench</span>. The code for each of the benchmarks resides here:</p>
<ul>
- <li> <b>LevelDB:</b> <a href="http://code.google.com/p/leveldb/source/browse/trunk/db/db_bench.cc">db/db_bench.cc</a>.</li>
- <li> <b>SQLite:</b> <a href="http://code.google.com/p/leveldb/source/browse/#svn%2Ftrunk%2Fdoc%2Fbench%2Fdb_bench_sqlite3.cc">doc/bench/db_bench_sqlite3.cc</a>.</li>
- <li> <b>Kyoto TreeDB:</b> <a href="http://code.google.com/p/leveldb/source/browse/#svn%2Ftrunk%2Fdoc%2Fbench%2Fdb_bench_tree_db.cc">doc/bench/db_bench_tree_db.cc</a>.</li>
+ <li> <b>LevelDB:</b> <a href="https://github.com/google/leveldb/blob/master/benchmarks/db_bench.cc">benchmarks/db_bench.cc</a>.</li>
+ <li> <b>SQLite:</b> <a href="https://github.com/google/leveldb/blob/master/benchmarks/db_bench_sqlite3.cc">benchmarks/db_bench_sqlite3.cc</a>.</li>
+ <li> <b>Kyoto TreeDB:</b> <a href="https://github.com/google/leveldb/blob/master/benchmarks/db_bench_tree_db.cc">benchmarks/db_bench_tree_db.cc</a>.</li>
</ul>
<h4>Custom Build Specifications</h4>
diff --git a/src/leveldb/doc/impl.md b/src/leveldb/doc/impl.md
index 4b13f2a6ba..cacabb96fc 100644
--- a/src/leveldb/doc/impl.md
+++ b/src/leveldb/doc/impl.md
@@ -64,13 +64,15 @@ Other files used for miscellaneous purposes may also be present (LOCK, *.dbtmp).
## Level 0
-When the log file grows above a certain size (1MB by default):
-Create a brand new memtable and log file and direct future updates here
+When the log file grows above a certain size (4MB by default):
+Create a brand new memtable and log file and direct future updates here.
+
In the background:
-Write the contents of the previous memtable to an sstable
-Discard the memtable
-Delete the old log file and the old memtable
-Add the new sstable to the young (level-0) level.
+
+1. Write the contents of the previous memtable to an sstable.
+2. Discard the memtable.
+3. Delete the old log file and the old memtable.
+4. Add the new sstable to the young (level-0) level.
## Compactions
diff --git a/src/leveldb/doc/index.md b/src/leveldb/doc/index.md
index be8569692b..3d9a25805b 100644
--- a/src/leveldb/doc/index.md
+++ b/src/leveldb/doc/index.md
@@ -307,7 +307,7 @@ version numbers found in the keys to decide how to interpret them.
## Performance
Performance can be tuned by changing the default values of the types defined in
-`include/leveldb/options.h`.
+`include/options.h`.
### Block size
@@ -338,19 +338,19 @@ options.compression = leveldb::kNoCompression;
### Cache
The contents of the database are stored in a set of files in the filesystem and
-each file stores a sequence of compressed blocks. If options.cache is non-NULL,
-it is used to cache frequently used uncompressed block contents.
+each file stores a sequence of compressed blocks. If options.block_cache is
+non-NULL, it is used to cache frequently used uncompressed block contents.
```c++
#include "leveldb/cache.h"
leveldb::Options options;
-options.cache = leveldb::NewLRUCache(100 * 1048576); // 100MB cache
+options.block_cache = leveldb::NewLRUCache(100 * 1048576); // 100MB cache
leveldb::DB* db;
leveldb::DB::Open(options, name, &db);
... use the db ...
delete db
-delete options.cache;
+delete options.block_cache;
```
Note that the cache holds uncompressed data, and therefore it should be sized
diff --git a/src/leveldb/helpers/memenv/memenv.cc b/src/leveldb/helpers/memenv/memenv.cc
index 68c0614a59..47e4481f7c 100644
--- a/src/leveldb/helpers/memenv/memenv.cc
+++ b/src/leveldb/helpers/memenv/memenv.cc
@@ -4,14 +4,18 @@
#include "helpers/memenv/memenv.h"
+#include <string.h>
+
+#include <limits>
+#include <map>
+#include <string>
+#include <vector>
+
#include "leveldb/env.h"
#include "leveldb/status.h"
#include "port/port.h"
+#include "port/thread_annotations.h"
#include "util/mutexlock.h"
-#include <map>
-#include <string.h>
-#include <string>
-#include <vector>
namespace leveldb {
@@ -23,6 +27,10 @@ class FileState {
// and the caller must call Ref() at least once.
FileState() : refs_(0), size_(0) {}
+ // No copying allowed.
+ FileState(const FileState&) = delete;
+ FileState& operator=(const FileState&) = delete;
+
// Increase the reference count.
void Ref() {
MutexLock lock(&refs_mutex_);
@@ -47,9 +55,22 @@ class FileState {
}
}
- uint64_t Size() const { return size_; }
+ uint64_t Size() const {
+ MutexLock lock(&blocks_mutex_);
+ return size_;
+ }
+
+ void Truncate() {
+ MutexLock lock(&blocks_mutex_);
+ for (char*& block : blocks_) {
+ delete[] block;
+ }
+ blocks_.clear();
+ size_ = 0;
+ }
Status Read(uint64_t offset, size_t n, Slice* result, char* scratch) const {
+ MutexLock lock(&blocks_mutex_);
if (offset > size_) {
return Status::IOError("Offset greater than file size.");
}
@@ -62,16 +83,9 @@ class FileState {
return Status::OK();
}
- assert(offset / kBlockSize <= SIZE_MAX);
+ assert(offset / kBlockSize <= std::numeric_limits<size_t>::max());
size_t block = static_cast<size_t>(offset / kBlockSize);
size_t block_offset = offset % kBlockSize;
-
- if (n <= kBlockSize - block_offset) {
- // The requested bytes are all in the first block.
- *result = Slice(blocks_[block] + block_offset, n);
- return Status::OK();
- }
-
size_t bytes_to_copy = n;
char* dst = scratch;
@@ -96,6 +110,7 @@ class FileState {
const char* src = data.data();
size_t src_len = data.size();
+ MutexLock lock(&blocks_mutex_);
while (src_len > 0) {
size_t avail;
size_t offset = size_ % kBlockSize;
@@ -122,28 +137,17 @@ class FileState {
}
private:
- // Private since only Unref() should be used to delete it.
- ~FileState() {
- for (std::vector<char*>::iterator i = blocks_.begin(); i != blocks_.end();
- ++i) {
- delete [] *i;
- }
- }
+ enum { kBlockSize = 8 * 1024 };
- // No copying allowed.
- FileState(const FileState&);
- void operator=(const FileState&);
+ // Private since only Unref() should be used to delete it.
+ ~FileState() { Truncate(); }
port::Mutex refs_mutex_;
- int refs_; // Protected by refs_mutex_;
+ int refs_ GUARDED_BY(refs_mutex_);
- // The following fields are not protected by any mutex. They are only mutable
- // while the file is being written, and concurrent access is not allowed
- // to writable files.
- std::vector<char*> blocks_;
- uint64_t size_;
-
- enum { kBlockSize = 8 * 1024 };
+ mutable port::Mutex blocks_mutex_;
+ std::vector<char*> blocks_ GUARDED_BY(blocks_mutex_);
+ uint64_t size_ GUARDED_BY(blocks_mutex_);
};
class SequentialFileImpl : public SequentialFile {
@@ -152,11 +156,9 @@ class SequentialFileImpl : public SequentialFile {
file_->Ref();
}
- ~SequentialFileImpl() {
- file_->Unref();
- }
+ ~SequentialFileImpl() override { file_->Unref(); }
- virtual Status Read(size_t n, Slice* result, char* scratch) {
+ Status Read(size_t n, Slice* result, char* scratch) override {
Status s = file_->Read(pos_, n, result, scratch);
if (s.ok()) {
pos_ += result->size();
@@ -164,7 +166,7 @@ class SequentialFileImpl : public SequentialFile {
return s;
}
- virtual Status Skip(uint64_t n) {
+ Status Skip(uint64_t n) override {
if (pos_ > file_->Size()) {
return Status::IOError("pos_ > file_->Size()");
}
@@ -176,7 +178,7 @@ class SequentialFileImpl : public SequentialFile {
return Status::OK();
}
- virtual std::string GetName() const { return "[memenv]"; }
+ virtual std::string GetName() const override { return "[memenv]"; }
private:
FileState* file_;
uint64_t pos_;
@@ -184,68 +186,58 @@ class SequentialFileImpl : public SequentialFile {
class RandomAccessFileImpl : public RandomAccessFile {
public:
- explicit RandomAccessFileImpl(FileState* file) : file_(file) {
- file_->Ref();
- }
+ explicit RandomAccessFileImpl(FileState* file) : file_(file) { file_->Ref(); }
- ~RandomAccessFileImpl() {
- file_->Unref();
- }
+ ~RandomAccessFileImpl() override { file_->Unref(); }
- virtual Status Read(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
+ Status Read(uint64_t offset, size_t n, Slice* result,
+ char* scratch) const override {
return file_->Read(offset, n, result, scratch);
}
- virtual std::string GetName() const { return "[memenv]"; }
+ virtual std::string GetName() const override { return "[memenv]"; }
private:
FileState* file_;
};
class WritableFileImpl : public WritableFile {
public:
- WritableFileImpl(FileState* file) : file_(file) {
- file_->Ref();
- }
+ WritableFileImpl(FileState* file) : file_(file) { file_->Ref(); }
- ~WritableFileImpl() {
- file_->Unref();
- }
+ ~WritableFileImpl() override { file_->Unref(); }
- virtual Status Append(const Slice& data) {
- return file_->Append(data);
- }
+ Status Append(const Slice& data) override { return file_->Append(data); }
- virtual Status Close() { return Status::OK(); }
- virtual Status Flush() { return Status::OK(); }
- virtual Status Sync() { return Status::OK(); }
+ Status Close() override { return Status::OK(); }
+ Status Flush() override { return Status::OK(); }
+ Status Sync() override { return Status::OK(); }
- virtual std::string GetName() const { return "[memenv]"; }
+ virtual std::string GetName() const override { return "[memenv]"; }
private:
FileState* file_;
};
class NoOpLogger : public Logger {
public:
- virtual void Logv(const char* format, va_list ap) { }
+ void Logv(const char* format, va_list ap) override {}
};
class InMemoryEnv : public EnvWrapper {
public:
- explicit InMemoryEnv(Env* base_env) : EnvWrapper(base_env) { }
+ explicit InMemoryEnv(Env* base_env) : EnvWrapper(base_env) {}
- virtual ~InMemoryEnv() {
- for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){
- i->second->Unref();
+ ~InMemoryEnv() override {
+ for (const auto& kvp : file_map_) {
+ kvp.second->Unref();
}
}
// Partial implementation of the Env interface.
- virtual Status NewSequentialFile(const std::string& fname,
- SequentialFile** result) {
+ Status NewSequentialFile(const std::string& fname,
+ SequentialFile** result) override {
MutexLock lock(&mutex_);
if (file_map_.find(fname) == file_map_.end()) {
- *result = NULL;
+ *result = nullptr;
return Status::IOError(fname, "File not found");
}
@@ -253,11 +245,11 @@ class InMemoryEnv : public EnvWrapper {
return Status::OK();
}
- virtual Status NewRandomAccessFile(const std::string& fname,
- RandomAccessFile** result) {
+ Status NewRandomAccessFile(const std::string& fname,
+ RandomAccessFile** result) override {
MutexLock lock(&mutex_);
if (file_map_.find(fname) == file_map_.end()) {
- *result = NULL;
+ *result = nullptr;
return Status::IOError(fname, "File not found");
}
@@ -265,27 +257,32 @@ class InMemoryEnv : public EnvWrapper {
return Status::OK();
}
- virtual Status NewWritableFile(const std::string& fname,
- WritableFile** result) {
+ Status NewWritableFile(const std::string& fname,
+ WritableFile** result) override {
MutexLock lock(&mutex_);
- if (file_map_.find(fname) != file_map_.end()) {
- DeleteFileInternal(fname);
- }
+ FileSystem::iterator it = file_map_.find(fname);
- FileState* file = new FileState();
- file->Ref();
- file_map_[fname] = file;
+ FileState* file;
+ if (it == file_map_.end()) {
+ // File is not currently open.
+ file = new FileState();
+ file->Ref();
+ file_map_[fname] = file;
+ } else {
+ file = it->second;
+ file->Truncate();
+ }
*result = new WritableFileImpl(file);
return Status::OK();
}
- virtual Status NewAppendableFile(const std::string& fname,
- WritableFile** result) {
+ Status NewAppendableFile(const std::string& fname,
+ WritableFile** result) override {
MutexLock lock(&mutex_);
FileState** sptr = &file_map_[fname];
FileState* file = *sptr;
- if (file == NULL) {
+ if (file == nullptr) {
file = new FileState();
file->Ref();
}
@@ -293,18 +290,18 @@ class InMemoryEnv : public EnvWrapper {
return Status::OK();
}
- virtual bool FileExists(const std::string& fname) {
+ bool FileExists(const std::string& fname) override {
MutexLock lock(&mutex_);
return file_map_.find(fname) != file_map_.end();
}
- virtual Status GetChildren(const std::string& dir,
- std::vector<std::string>* result) {
+ Status GetChildren(const std::string& dir,
+ std::vector<std::string>* result) override {
MutexLock lock(&mutex_);
result->clear();
- for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){
- const std::string& filename = i->first;
+ for (const auto& kvp : file_map_) {
+ const std::string& filename = kvp.first;
if (filename.size() >= dir.size() + 1 && filename[dir.size()] == '/' &&
Slice(filename).starts_with(Slice(dir))) {
@@ -315,7 +312,8 @@ class InMemoryEnv : public EnvWrapper {
return Status::OK();
}
- void DeleteFileInternal(const std::string& fname) {
+ void DeleteFileInternal(const std::string& fname)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
if (file_map_.find(fname) == file_map_.end()) {
return;
}
@@ -324,7 +322,7 @@ class InMemoryEnv : public EnvWrapper {
file_map_.erase(fname);
}
- virtual Status DeleteFile(const std::string& fname) {
+ Status DeleteFile(const std::string& fname) override {
MutexLock lock(&mutex_);
if (file_map_.find(fname) == file_map_.end()) {
return Status::IOError(fname, "File not found");
@@ -334,15 +332,11 @@ class InMemoryEnv : public EnvWrapper {
return Status::OK();
}
- virtual Status CreateDir(const std::string& dirname) {
- return Status::OK();
- }
+ Status CreateDir(const std::string& dirname) override { return Status::OK(); }
- virtual Status DeleteDir(const std::string& dirname) {
- return Status::OK();
- }
+ Status DeleteDir(const std::string& dirname) override { return Status::OK(); }
- virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) {
+ Status GetFileSize(const std::string& fname, uint64_t* file_size) override {
MutexLock lock(&mutex_);
if (file_map_.find(fname) == file_map_.end()) {
return Status::IOError(fname, "File not found");
@@ -352,8 +346,8 @@ class InMemoryEnv : public EnvWrapper {
return Status::OK();
}
- virtual Status RenameFile(const std::string& src,
- const std::string& target) {
+ Status RenameFile(const std::string& src,
+ const std::string& target) override {
MutexLock lock(&mutex_);
if (file_map_.find(src) == file_map_.end()) {
return Status::IOError(src, "File not found");
@@ -365,22 +359,22 @@ class InMemoryEnv : public EnvWrapper {
return Status::OK();
}
- virtual Status LockFile(const std::string& fname, FileLock** lock) {
+ Status LockFile(const std::string& fname, FileLock** lock) override {
*lock = new FileLock;
return Status::OK();
}
- virtual Status UnlockFile(FileLock* lock) {
+ Status UnlockFile(FileLock* lock) override {
delete lock;
return Status::OK();
}
- virtual Status GetTestDirectory(std::string* path) {
+ Status GetTestDirectory(std::string* path) override {
*path = "/test";
return Status::OK();
}
- virtual Status NewLogger(const std::string& fname, Logger** result) {
+ Status NewLogger(const std::string& fname, Logger** result) override {
*result = new NoOpLogger;
return Status::OK();
}
@@ -388,14 +382,13 @@ class InMemoryEnv : public EnvWrapper {
private:
// Map from filenames to FileState objects, representing a simple file system.
typedef std::map<std::string, FileState*> FileSystem;
+
port::Mutex mutex_;
- FileSystem file_map_; // Protected by mutex_.
+ FileSystem file_map_ GUARDED_BY(mutex_);
};
} // namespace
-Env* NewMemEnv(Env* base_env) {
- return new InMemoryEnv(base_env);
-}
+Env* NewMemEnv(Env* base_env) { return new InMemoryEnv(base_env); }
} // namespace leveldb
diff --git a/src/leveldb/helpers/memenv/memenv.h b/src/leveldb/helpers/memenv/memenv.h
index 03b88de761..3d929e4c4e 100644
--- a/src/leveldb/helpers/memenv/memenv.h
+++ b/src/leveldb/helpers/memenv/memenv.h
@@ -5,6 +5,8 @@
#ifndef STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_
#define STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_
+#include "leveldb/export.h"
+
namespace leveldb {
class Env;
@@ -13,7 +15,7 @@ class Env;
// all non-file-storage tasks to base_env. The caller must delete the result
// when it is no longer needed.
// *base_env must remain live while the result is in use.
-Env* NewMemEnv(Env* base_env);
+LEVELDB_EXPORT Env* NewMemEnv(Env* base_env);
} // namespace leveldb
diff --git a/src/leveldb/helpers/memenv/memenv_test.cc b/src/leveldb/helpers/memenv/memenv_test.cc
index 5cff77613f..94ad06be68 100644
--- a/src/leveldb/helpers/memenv/memenv_test.cc
+++ b/src/leveldb/helpers/memenv/memenv_test.cc
@@ -4,25 +4,22 @@
#include "helpers/memenv/memenv.h"
+#include <string>
+#include <vector>
+
#include "db/db_impl.h"
#include "leveldb/db.h"
#include "leveldb/env.h"
#include "util/testharness.h"
-#include <string>
-#include <vector>
namespace leveldb {
class MemEnvTest {
public:
- Env* env_;
+ MemEnvTest() : env_(NewMemEnv(Env::Default())) {}
+ ~MemEnvTest() { delete env_; }
- MemEnvTest()
- : env_(NewMemEnv(Env::Default())) {
- }
- ~MemEnvTest() {
- delete env_;
- }
+ Env* env_;
};
TEST(MemEnvTest, Basics) {
@@ -109,25 +106,25 @@ TEST(MemEnvTest, ReadWrite) {
// Read sequentially.
ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file));
- ASSERT_OK(seq_file->Read(5, &result, scratch)); // Read "hello".
+ ASSERT_OK(seq_file->Read(5, &result, scratch)); // Read "hello".
ASSERT_EQ(0, result.compare("hello"));
ASSERT_OK(seq_file->Skip(1));
- ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Read "world".
+ ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Read "world".
ASSERT_EQ(0, result.compare("world"));
- ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Try reading past EOF.
+ ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Try reading past EOF.
ASSERT_EQ(0, result.size());
- ASSERT_OK(seq_file->Skip(100)); // Try to skip past end of file.
+ ASSERT_OK(seq_file->Skip(100)); // Try to skip past end of file.
ASSERT_OK(seq_file->Read(1000, &result, scratch));
ASSERT_EQ(0, result.size());
delete seq_file;
// Random reads.
ASSERT_OK(env_->NewRandomAccessFile("/dir/f", &rand_file));
- ASSERT_OK(rand_file->Read(6, 5, &result, scratch)); // Read "world".
+ ASSERT_OK(rand_file->Read(6, 5, &result, scratch)); // Read "world".
ASSERT_EQ(0, result.compare("world"));
- ASSERT_OK(rand_file->Read(0, 5, &result, scratch)); // Read "hello".
+ ASSERT_OK(rand_file->Read(0, 5, &result, scratch)); // Read "hello".
ASSERT_EQ(0, result.compare("hello"));
- ASSERT_OK(rand_file->Read(10, 100, &result, scratch)); // Read "d".
+ ASSERT_OK(rand_file->Read(10, 100, &result, scratch)); // Read "d".
ASSERT_EQ(0, result.compare("d"));
// Too high offset.
@@ -176,7 +173,7 @@ TEST(MemEnvTest, LargeWrite) {
SequentialFile* seq_file;
Slice result;
ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file));
- ASSERT_OK(seq_file->Read(3, &result, scratch)); // Read "foo".
+ ASSERT_OK(seq_file->Read(3, &result, scratch)); // Read "foo".
ASSERT_EQ(0, result.compare("foo"));
size_t read = 0;
@@ -188,7 +185,30 @@ TEST(MemEnvTest, LargeWrite) {
}
ASSERT_TRUE(write_data == read_data);
delete seq_file;
- delete [] scratch;
+ delete[] scratch;
+}
+
+TEST(MemEnvTest, OverwriteOpenFile) {
+ const char kWrite1Data[] = "Write #1 data";
+ const size_t kFileDataLen = sizeof(kWrite1Data) - 1;
+ const std::string kTestFileName = test::TmpDir() + "/leveldb-TestFile.dat";
+
+ ASSERT_OK(WriteStringToFile(env_, kWrite1Data, kTestFileName));
+
+ RandomAccessFile* rand_file;
+ ASSERT_OK(env_->NewRandomAccessFile(kTestFileName, &rand_file));
+
+ const char kWrite2Data[] = "Write #2 data";
+ ASSERT_OK(WriteStringToFile(env_, kWrite2Data, kTestFileName));
+
+ // Verify that overwriting an open file will result in the new file data
+ // being read from files opened before the write.
+ Slice result;
+ char scratch[kFileDataLen];
+ ASSERT_OK(rand_file->Read(0, kFileDataLen, &result, scratch));
+ ASSERT_EQ(0, result.compare(kWrite2Data));
+
+ delete rand_file;
}
TEST(MemEnvTest, DBTest) {
@@ -236,6 +256,4 @@ TEST(MemEnvTest, DBTest) {
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/include/leveldb/c.h b/src/leveldb/include/leveldb/c.h
index 1048fe3b86..02c79ba72e 100644
--- a/src/leveldb/include/leveldb/c.h
+++ b/src/leveldb/include/leveldb/c.h
@@ -32,7 +32,7 @@
On failure, leveldb frees the old value of *errptr and
set *errptr to a malloc()ed error message.
- (4) Bools have the type unsigned char (0 == false; rest == true)
+ (4) Bools have the type uint8_t (0 == false; rest == true)
(5) All of the pointer arguments must be non-NULL.
*/
@@ -48,225 +48,205 @@ extern "C" {
#include <stddef.h>
#include <stdint.h>
+#include "leveldb/export.h"
+
/* Exported types */
-typedef struct leveldb_t leveldb_t;
-typedef struct leveldb_cache_t leveldb_cache_t;
-typedef struct leveldb_comparator_t leveldb_comparator_t;
-typedef struct leveldb_env_t leveldb_env_t;
-typedef struct leveldb_filelock_t leveldb_filelock_t;
-typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t;
-typedef struct leveldb_iterator_t leveldb_iterator_t;
-typedef struct leveldb_logger_t leveldb_logger_t;
-typedef struct leveldb_options_t leveldb_options_t;
-typedef struct leveldb_randomfile_t leveldb_randomfile_t;
-typedef struct leveldb_readoptions_t leveldb_readoptions_t;
-typedef struct leveldb_seqfile_t leveldb_seqfile_t;
-typedef struct leveldb_snapshot_t leveldb_snapshot_t;
-typedef struct leveldb_writablefile_t leveldb_writablefile_t;
-typedef struct leveldb_writebatch_t leveldb_writebatch_t;
-typedef struct leveldb_writeoptions_t leveldb_writeoptions_t;
+typedef struct leveldb_t leveldb_t;
+typedef struct leveldb_cache_t leveldb_cache_t;
+typedef struct leveldb_comparator_t leveldb_comparator_t;
+typedef struct leveldb_env_t leveldb_env_t;
+typedef struct leveldb_filelock_t leveldb_filelock_t;
+typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t;
+typedef struct leveldb_iterator_t leveldb_iterator_t;
+typedef struct leveldb_logger_t leveldb_logger_t;
+typedef struct leveldb_options_t leveldb_options_t;
+typedef struct leveldb_randomfile_t leveldb_randomfile_t;
+typedef struct leveldb_readoptions_t leveldb_readoptions_t;
+typedef struct leveldb_seqfile_t leveldb_seqfile_t;
+typedef struct leveldb_snapshot_t leveldb_snapshot_t;
+typedef struct leveldb_writablefile_t leveldb_writablefile_t;
+typedef struct leveldb_writebatch_t leveldb_writebatch_t;
+typedef struct leveldb_writeoptions_t leveldb_writeoptions_t;
/* DB operations */
-extern leveldb_t* leveldb_open(
- const leveldb_options_t* options,
- const char* name,
- char** errptr);
+LEVELDB_EXPORT leveldb_t* leveldb_open(const leveldb_options_t* options,
+ const char* name, char** errptr);
-extern void leveldb_close(leveldb_t* db);
+LEVELDB_EXPORT void leveldb_close(leveldb_t* db);
-extern void leveldb_put(
- leveldb_t* db,
- const leveldb_writeoptions_t* options,
- const char* key, size_t keylen,
- const char* val, size_t vallen,
- char** errptr);
+LEVELDB_EXPORT void leveldb_put(leveldb_t* db,
+ const leveldb_writeoptions_t* options,
+ const char* key, size_t keylen, const char* val,
+ size_t vallen, char** errptr);
-extern void leveldb_delete(
- leveldb_t* db,
- const leveldb_writeoptions_t* options,
- const char* key, size_t keylen,
- char** errptr);
+LEVELDB_EXPORT void leveldb_delete(leveldb_t* db,
+ const leveldb_writeoptions_t* options,
+ const char* key, size_t keylen,
+ char** errptr);
-extern void leveldb_write(
- leveldb_t* db,
- const leveldb_writeoptions_t* options,
- leveldb_writebatch_t* batch,
- char** errptr);
+LEVELDB_EXPORT void leveldb_write(leveldb_t* db,
+ const leveldb_writeoptions_t* options,
+ leveldb_writebatch_t* batch, char** errptr);
/* Returns NULL if not found. A malloc()ed array otherwise.
Stores the length of the array in *vallen. */
-extern char* leveldb_get(
- leveldb_t* db,
- const leveldb_readoptions_t* options,
- const char* key, size_t keylen,
- size_t* vallen,
- char** errptr);
+LEVELDB_EXPORT char* leveldb_get(leveldb_t* db,
+ const leveldb_readoptions_t* options,
+ const char* key, size_t keylen, size_t* vallen,
+ char** errptr);
-extern leveldb_iterator_t* leveldb_create_iterator(
- leveldb_t* db,
- const leveldb_readoptions_t* options);
+LEVELDB_EXPORT leveldb_iterator_t* leveldb_create_iterator(
+ leveldb_t* db, const leveldb_readoptions_t* options);
-extern const leveldb_snapshot_t* leveldb_create_snapshot(
- leveldb_t* db);
+LEVELDB_EXPORT const leveldb_snapshot_t* leveldb_create_snapshot(leveldb_t* db);
-extern void leveldb_release_snapshot(
- leveldb_t* db,
- const leveldb_snapshot_t* snapshot);
+LEVELDB_EXPORT void leveldb_release_snapshot(
+ leveldb_t* db, const leveldb_snapshot_t* snapshot);
/* Returns NULL if property name is unknown.
Else returns a pointer to a malloc()-ed null-terminated value. */
-extern char* leveldb_property_value(
- leveldb_t* db,
- const char* propname);
-
-extern void leveldb_approximate_sizes(
- leveldb_t* db,
- int num_ranges,
- const char* const* range_start_key, const size_t* range_start_key_len,
- const char* const* range_limit_key, const size_t* range_limit_key_len,
- uint64_t* sizes);
-
-extern void leveldb_compact_range(
- leveldb_t* db,
- const char* start_key, size_t start_key_len,
- const char* limit_key, size_t limit_key_len);
+LEVELDB_EXPORT char* leveldb_property_value(leveldb_t* db,
+ const char* propname);
+
+LEVELDB_EXPORT void leveldb_approximate_sizes(
+ leveldb_t* db, int num_ranges, const char* const* range_start_key,
+ const size_t* range_start_key_len, const char* const* range_limit_key,
+ const size_t* range_limit_key_len, uint64_t* sizes);
+
+LEVELDB_EXPORT void leveldb_compact_range(leveldb_t* db, const char* start_key,
+ size_t start_key_len,
+ const char* limit_key,
+ size_t limit_key_len);
/* Management operations */
-extern void leveldb_destroy_db(
- const leveldb_options_t* options,
- const char* name,
- char** errptr);
+LEVELDB_EXPORT void leveldb_destroy_db(const leveldb_options_t* options,
+ const char* name, char** errptr);
-extern void leveldb_repair_db(
- const leveldb_options_t* options,
- const char* name,
- char** errptr);
+LEVELDB_EXPORT void leveldb_repair_db(const leveldb_options_t* options,
+ const char* name, char** errptr);
/* Iterator */
-extern void leveldb_iter_destroy(leveldb_iterator_t*);
-extern unsigned char leveldb_iter_valid(const leveldb_iterator_t*);
-extern void leveldb_iter_seek_to_first(leveldb_iterator_t*);
-extern void leveldb_iter_seek_to_last(leveldb_iterator_t*);
-extern void leveldb_iter_seek(leveldb_iterator_t*, const char* k, size_t klen);
-extern void leveldb_iter_next(leveldb_iterator_t*);
-extern void leveldb_iter_prev(leveldb_iterator_t*);
-extern const char* leveldb_iter_key(const leveldb_iterator_t*, size_t* klen);
-extern const char* leveldb_iter_value(const leveldb_iterator_t*, size_t* vlen);
-extern void leveldb_iter_get_error(const leveldb_iterator_t*, char** errptr);
+LEVELDB_EXPORT void leveldb_iter_destroy(leveldb_iterator_t*);
+LEVELDB_EXPORT uint8_t leveldb_iter_valid(const leveldb_iterator_t*);
+LEVELDB_EXPORT void leveldb_iter_seek_to_first(leveldb_iterator_t*);
+LEVELDB_EXPORT void leveldb_iter_seek_to_last(leveldb_iterator_t*);
+LEVELDB_EXPORT void leveldb_iter_seek(leveldb_iterator_t*, const char* k,
+ size_t klen);
+LEVELDB_EXPORT void leveldb_iter_next(leveldb_iterator_t*);
+LEVELDB_EXPORT void leveldb_iter_prev(leveldb_iterator_t*);
+LEVELDB_EXPORT const char* leveldb_iter_key(const leveldb_iterator_t*,
+ size_t* klen);
+LEVELDB_EXPORT const char* leveldb_iter_value(const leveldb_iterator_t*,
+ size_t* vlen);
+LEVELDB_EXPORT void leveldb_iter_get_error(const leveldb_iterator_t*,
+ char** errptr);
/* Write batch */
-extern leveldb_writebatch_t* leveldb_writebatch_create();
-extern void leveldb_writebatch_destroy(leveldb_writebatch_t*);
-extern void leveldb_writebatch_clear(leveldb_writebatch_t*);
-extern void leveldb_writebatch_put(
- leveldb_writebatch_t*,
- const char* key, size_t klen,
- const char* val, size_t vlen);
-extern void leveldb_writebatch_delete(
- leveldb_writebatch_t*,
- const char* key, size_t klen);
-extern void leveldb_writebatch_iterate(
- leveldb_writebatch_t*,
- void* state,
+LEVELDB_EXPORT leveldb_writebatch_t* leveldb_writebatch_create(void);
+LEVELDB_EXPORT void leveldb_writebatch_destroy(leveldb_writebatch_t*);
+LEVELDB_EXPORT void leveldb_writebatch_clear(leveldb_writebatch_t*);
+LEVELDB_EXPORT void leveldb_writebatch_put(leveldb_writebatch_t*,
+ const char* key, size_t klen,
+ const char* val, size_t vlen);
+LEVELDB_EXPORT void leveldb_writebatch_delete(leveldb_writebatch_t*,
+ const char* key, size_t klen);
+LEVELDB_EXPORT void leveldb_writebatch_iterate(
+ const leveldb_writebatch_t*, void* state,
void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
void (*deleted)(void*, const char* k, size_t klen));
+LEVELDB_EXPORT void leveldb_writebatch_append(
+ leveldb_writebatch_t* destination, const leveldb_writebatch_t* source);
/* Options */
-extern leveldb_options_t* leveldb_options_create();
-extern void leveldb_options_destroy(leveldb_options_t*);
-extern void leveldb_options_set_comparator(
- leveldb_options_t*,
- leveldb_comparator_t*);
-extern void leveldb_options_set_filter_policy(
- leveldb_options_t*,
- leveldb_filterpolicy_t*);
-extern void leveldb_options_set_create_if_missing(
- leveldb_options_t*, unsigned char);
-extern void leveldb_options_set_error_if_exists(
- leveldb_options_t*, unsigned char);
-extern void leveldb_options_set_paranoid_checks(
- leveldb_options_t*, unsigned char);
-extern void leveldb_options_set_env(leveldb_options_t*, leveldb_env_t*);
-extern void leveldb_options_set_info_log(leveldb_options_t*, leveldb_logger_t*);
-extern void leveldb_options_set_write_buffer_size(leveldb_options_t*, size_t);
-extern void leveldb_options_set_max_open_files(leveldb_options_t*, int);
-extern void leveldb_options_set_cache(leveldb_options_t*, leveldb_cache_t*);
-extern void leveldb_options_set_block_size(leveldb_options_t*, size_t);
-extern void leveldb_options_set_block_restart_interval(leveldb_options_t*, int);
-
-enum {
- leveldb_no_compression = 0,
- leveldb_snappy_compression = 1
-};
-extern void leveldb_options_set_compression(leveldb_options_t*, int);
+LEVELDB_EXPORT leveldb_options_t* leveldb_options_create(void);
+LEVELDB_EXPORT void leveldb_options_destroy(leveldb_options_t*);
+LEVELDB_EXPORT void leveldb_options_set_comparator(leveldb_options_t*,
+ leveldb_comparator_t*);
+LEVELDB_EXPORT void leveldb_options_set_filter_policy(leveldb_options_t*,
+ leveldb_filterpolicy_t*);
+LEVELDB_EXPORT void leveldb_options_set_create_if_missing(leveldb_options_t*,
+ uint8_t);
+LEVELDB_EXPORT void leveldb_options_set_error_if_exists(leveldb_options_t*,
+ uint8_t);
+LEVELDB_EXPORT void leveldb_options_set_paranoid_checks(leveldb_options_t*,
+ uint8_t);
+LEVELDB_EXPORT void leveldb_options_set_env(leveldb_options_t*, leveldb_env_t*);
+LEVELDB_EXPORT void leveldb_options_set_info_log(leveldb_options_t*,
+ leveldb_logger_t*);
+LEVELDB_EXPORT void leveldb_options_set_write_buffer_size(leveldb_options_t*,
+ size_t);
+LEVELDB_EXPORT void leveldb_options_set_max_open_files(leveldb_options_t*, int);
+LEVELDB_EXPORT void leveldb_options_set_cache(leveldb_options_t*,
+ leveldb_cache_t*);
+LEVELDB_EXPORT void leveldb_options_set_block_size(leveldb_options_t*, size_t);
+LEVELDB_EXPORT void leveldb_options_set_block_restart_interval(
+ leveldb_options_t*, int);
+LEVELDB_EXPORT void leveldb_options_set_max_file_size(leveldb_options_t*,
+ size_t);
+
+enum { leveldb_no_compression = 0, leveldb_snappy_compression = 1 };
+LEVELDB_EXPORT void leveldb_options_set_compression(leveldb_options_t*, int);
/* Comparator */
-extern leveldb_comparator_t* leveldb_comparator_create(
- void* state,
- void (*destructor)(void*),
- int (*compare)(
- void*,
- const char* a, size_t alen,
- const char* b, size_t blen),
+LEVELDB_EXPORT leveldb_comparator_t* leveldb_comparator_create(
+ void* state, void (*destructor)(void*),
+ int (*compare)(void*, const char* a, size_t alen, const char* b,
+ size_t blen),
const char* (*name)(void*));
-extern void leveldb_comparator_destroy(leveldb_comparator_t*);
+LEVELDB_EXPORT void leveldb_comparator_destroy(leveldb_comparator_t*);
/* Filter policy */
-extern leveldb_filterpolicy_t* leveldb_filterpolicy_create(
- void* state,
- void (*destructor)(void*),
- char* (*create_filter)(
- void*,
- const char* const* key_array, const size_t* key_length_array,
- int num_keys,
- size_t* filter_length),
- unsigned char (*key_may_match)(
- void*,
- const char* key, size_t length,
- const char* filter, size_t filter_length),
+LEVELDB_EXPORT leveldb_filterpolicy_t* leveldb_filterpolicy_create(
+ void* state, void (*destructor)(void*),
+ char* (*create_filter)(void*, const char* const* key_array,
+ const size_t* key_length_array, int num_keys,
+ size_t* filter_length),
+ uint8_t (*key_may_match)(void*, const char* key, size_t length,
+ const char* filter, size_t filter_length),
const char* (*name)(void*));
-extern void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*);
+LEVELDB_EXPORT void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*);
-extern leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(
+LEVELDB_EXPORT leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(
int bits_per_key);
/* Read options */
-extern leveldb_readoptions_t* leveldb_readoptions_create();
-extern void leveldb_readoptions_destroy(leveldb_readoptions_t*);
-extern void leveldb_readoptions_set_verify_checksums(
- leveldb_readoptions_t*,
- unsigned char);
-extern void leveldb_readoptions_set_fill_cache(
- leveldb_readoptions_t*, unsigned char);
-extern void leveldb_readoptions_set_snapshot(
- leveldb_readoptions_t*,
- const leveldb_snapshot_t*);
+LEVELDB_EXPORT leveldb_readoptions_t* leveldb_readoptions_create(void);
+LEVELDB_EXPORT void leveldb_readoptions_destroy(leveldb_readoptions_t*);
+LEVELDB_EXPORT void leveldb_readoptions_set_verify_checksums(
+ leveldb_readoptions_t*, uint8_t);
+LEVELDB_EXPORT void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t*,
+ uint8_t);
+LEVELDB_EXPORT void leveldb_readoptions_set_snapshot(leveldb_readoptions_t*,
+ const leveldb_snapshot_t*);
/* Write options */
-extern leveldb_writeoptions_t* leveldb_writeoptions_create();
-extern void leveldb_writeoptions_destroy(leveldb_writeoptions_t*);
-extern void leveldb_writeoptions_set_sync(
- leveldb_writeoptions_t*, unsigned char);
+LEVELDB_EXPORT leveldb_writeoptions_t* leveldb_writeoptions_create(void);
+LEVELDB_EXPORT void leveldb_writeoptions_destroy(leveldb_writeoptions_t*);
+LEVELDB_EXPORT void leveldb_writeoptions_set_sync(leveldb_writeoptions_t*,
+ uint8_t);
/* Cache */
-extern leveldb_cache_t* leveldb_cache_create_lru(size_t capacity);
-extern void leveldb_cache_destroy(leveldb_cache_t* cache);
+LEVELDB_EXPORT leveldb_cache_t* leveldb_cache_create_lru(size_t capacity);
+LEVELDB_EXPORT void leveldb_cache_destroy(leveldb_cache_t* cache);
/* Env */
-extern leveldb_env_t* leveldb_create_default_env();
-extern void leveldb_env_destroy(leveldb_env_t*);
+LEVELDB_EXPORT leveldb_env_t* leveldb_create_default_env(void);
+LEVELDB_EXPORT void leveldb_env_destroy(leveldb_env_t*);
+
+/* If not NULL, the returned buffer must be released using leveldb_free(). */
+LEVELDB_EXPORT char* leveldb_env_get_test_directory(leveldb_env_t*);
/* Utility */
@@ -275,16 +255,16 @@ extern void leveldb_env_destroy(leveldb_env_t*);
in this file. Note that in certain cases (typically on Windows), you
may need to call this routine instead of free(ptr) to dispose of
malloc()-ed memory returned by this library. */
-extern void leveldb_free(void* ptr);
+LEVELDB_EXPORT void leveldb_free(void* ptr);
/* Return the major version number for this release. */
-extern int leveldb_major_version();
+LEVELDB_EXPORT int leveldb_major_version(void);
/* Return the minor version number for this release. */
-extern int leveldb_minor_version();
+LEVELDB_EXPORT int leveldb_minor_version(void);
#ifdef __cplusplus
-} /* end extern "C" */
+} /* end extern "C" */
#endif
-#endif /* STORAGE_LEVELDB_INCLUDE_C_H_ */
+#endif /* STORAGE_LEVELDB_INCLUDE_C_H_ */
diff --git a/src/leveldb/include/leveldb/cache.h b/src/leveldb/include/leveldb/cache.h
index 6819d5bc49..7d1a221193 100644
--- a/src/leveldb/include/leveldb/cache.h
+++ b/src/leveldb/include/leveldb/cache.h
@@ -19,26 +19,31 @@
#define STORAGE_LEVELDB_INCLUDE_CACHE_H_
#include <stdint.h>
+
+#include "leveldb/export.h"
#include "leveldb/slice.h"
namespace leveldb {
-class Cache;
+class LEVELDB_EXPORT Cache;
// Create a new cache with a fixed size capacity. This implementation
// of Cache uses a least-recently-used eviction policy.
-extern Cache* NewLRUCache(size_t capacity);
+LEVELDB_EXPORT Cache* NewLRUCache(size_t capacity);
-class Cache {
+class LEVELDB_EXPORT Cache {
public:
- Cache() { }
+ Cache() = default;
+
+ Cache(const Cache&) = delete;
+ Cache& operator=(const Cache&) = delete;
// Destroys all existing entries by calling the "deleter"
// function that was passed to the constructor.
virtual ~Cache();
// Opaque handle to an entry stored in the cache.
- struct Handle { };
+ struct Handle {};
// Insert a mapping from key->value into the cache and assign it
// the specified charge against the total cache capacity.
@@ -52,7 +57,7 @@ class Cache {
virtual Handle* Insert(const Slice& key, void* value, size_t charge,
void (*deleter)(const Slice& key, void* value)) = 0;
- // If the cache has no mapping for "key", returns NULL.
+ // If the cache has no mapping for "key", returns nullptr.
//
// Else return a handle that corresponds to the mapping. The caller
// must call this->Release(handle) when the returned mapping is no
@@ -99,10 +104,6 @@ class Cache {
struct Rep;
Rep* rep_;
-
- // No copying allowed
- Cache(const Cache&);
- void operator=(const Cache&);
};
} // namespace leveldb
diff --git a/src/leveldb/include/leveldb/comparator.h b/src/leveldb/include/leveldb/comparator.h
index 556b984c76..a85b51ebd8 100644
--- a/src/leveldb/include/leveldb/comparator.h
+++ b/src/leveldb/include/leveldb/comparator.h
@@ -7,6 +7,8 @@
#include <string>
+#include "leveldb/export.h"
+
namespace leveldb {
class Slice;
@@ -15,7 +17,7 @@ class Slice;
// used as keys in an sstable or a database. A Comparator implementation
// must be thread-safe since leveldb may invoke its methods concurrently
// from multiple threads.
-class Comparator {
+class LEVELDB_EXPORT Comparator {
public:
virtual ~Comparator();
@@ -43,9 +45,8 @@ class Comparator {
// If *start < limit, changes *start to a short string in [start,limit).
// Simple comparator implementations may return with *start unchanged,
// i.e., an implementation of this method that does nothing is correct.
- virtual void FindShortestSeparator(
- std::string* start,
- const Slice& limit) const = 0;
+ virtual void FindShortestSeparator(std::string* start,
+ const Slice& limit) const = 0;
// Changes *key to a short string >= *key.
// Simple comparator implementations may return with *key unchanged,
@@ -56,7 +57,7 @@ class Comparator {
// Return a builtin comparator that uses lexicographic byte-wise
// ordering. The result remains the property of this module and
// must not be deleted.
-extern const Comparator* BytewiseComparator();
+LEVELDB_EXPORT const Comparator* BytewiseComparator();
} // namespace leveldb
diff --git a/src/leveldb/include/leveldb/db.h b/src/leveldb/include/leveldb/db.h
index bfab10a0b7..b73014a221 100644
--- a/src/leveldb/include/leveldb/db.h
+++ b/src/leveldb/include/leveldb/db.h
@@ -7,14 +7,16 @@
#include <stdint.h>
#include <stdio.h>
+
+#include "leveldb/export.h"
#include "leveldb/iterator.h"
#include "leveldb/options.h"
namespace leveldb {
-// Update Makefile if you change these
+// Update CMakeLists.txt if you change these
static const int kMajorVersion = 1;
-static const int kMinorVersion = 20;
+static const int kMinorVersion = 22;
struct Options;
struct ReadOptions;
@@ -24,42 +26,44 @@ class WriteBatch;
// Abstract handle to particular state of a DB.
// A Snapshot is an immutable object and can therefore be safely
// accessed from multiple threads without any external synchronization.
-class Snapshot {
+class LEVELDB_EXPORT Snapshot {
protected:
virtual ~Snapshot();
};
// A range of keys
-struct Range {
- Slice start; // Included in the range
- Slice limit; // Not included in the range
+struct LEVELDB_EXPORT Range {
+ Range() = default;
+ Range(const Slice& s, const Slice& l) : start(s), limit(l) {}
- Range() { }
- Range(const Slice& s, const Slice& l) : start(s), limit(l) { }
+ Slice start; // Included in the range
+ Slice limit; // Not included in the range
};
// A DB is a persistent ordered map from keys to values.
// A DB is safe for concurrent access from multiple threads without
// any external synchronization.
-class DB {
+class LEVELDB_EXPORT DB {
public:
// Open the database with the specified "name".
// Stores a pointer to a heap-allocated database in *dbptr and returns
// OK on success.
- // Stores NULL in *dbptr and returns a non-OK status on error.
+ // Stores nullptr in *dbptr and returns a non-OK status on error.
// Caller should delete *dbptr when it is no longer needed.
- static Status Open(const Options& options,
- const std::string& name,
+ static Status Open(const Options& options, const std::string& name,
DB** dbptr);
- DB() { }
+ DB() = default;
+
+ DB(const DB&) = delete;
+ DB& operator=(const DB&) = delete;
+
virtual ~DB();
// Set the database entry for "key" to "value". Returns OK on success,
// and a non-OK status on error.
// Note: consider setting options.sync = true.
- virtual Status Put(const WriteOptions& options,
- const Slice& key,
+ virtual Status Put(const WriteOptions& options, const Slice& key,
const Slice& value) = 0;
// Remove the database entry (if any) for "key". Returns OK on
@@ -80,8 +84,8 @@ class DB {
// a status for which Status::IsNotFound() returns true.
//
// May return some other Status on an error.
- virtual Status Get(const ReadOptions& options,
- const Slice& key, std::string* value) = 0;
+ virtual Status Get(const ReadOptions& options, const Slice& key,
+ std::string* value) = 0;
// Return a heap-allocated iterator over the contents of the database.
// The result of NewIterator() is initially invalid (caller must
@@ -136,27 +140,27 @@ class DB {
// needed to access the data. This operation should typically only
// be invoked by users who understand the underlying implementation.
//
- // begin==NULL is treated as a key before all keys in the database.
- // end==NULL is treated as a key after all keys in the database.
+ // begin==nullptr is treated as a key before all keys in the database.
+ // end==nullptr is treated as a key after all keys in the database.
// Therefore the following call will compact the entire database:
- // db->CompactRange(NULL, NULL);
+ // db->CompactRange(nullptr, nullptr);
virtual void CompactRange(const Slice* begin, const Slice* end) = 0;
-
- private:
- // No copying allowed
- DB(const DB&);
- void operator=(const DB&);
};
// Destroy the contents of the specified database.
// Be very careful using this method.
-Status DestroyDB(const std::string& name, const Options& options);
+//
+// Note: For backwards compatibility, if DestroyDB is unable to list the
+// database files, Status::OK() will still be returned masking this failure.
+LEVELDB_EXPORT Status DestroyDB(const std::string& name,
+ const Options& options);
// If a DB cannot be opened, you may attempt to call this method to
// resurrect as much of the contents of the database as possible.
// Some data may be lost, so be careful when calling this function
// on a database that contains important information.
-Status RepairDB(const std::string& dbname, const Options& options);
+LEVELDB_EXPORT Status RepairDB(const std::string& dbname,
+ const Options& options);
} // namespace leveldb
diff --git a/src/leveldb/include/leveldb/dumpfile.h b/src/leveldb/include/leveldb/dumpfile.h
index 3f97fda16b..a58bc6b36c 100644
--- a/src/leveldb/include/leveldb/dumpfile.h
+++ b/src/leveldb/include/leveldb/dumpfile.h
@@ -6,7 +6,9 @@
#define STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_
#include <string>
+
#include "leveldb/env.h"
+#include "leveldb/export.h"
#include "leveldb/status.h"
namespace leveldb {
@@ -18,7 +20,8 @@ namespace leveldb {
//
// Returns a non-OK result if fname does not name a leveldb storage
// file, or if the file cannot be read.
-Status DumpFile(Env* env, const std::string& fname, WritableFile* dst);
+LEVELDB_EXPORT Status DumpFile(Env* env, const std::string& fname,
+ WritableFile* dst);
} // namespace leveldb
diff --git a/src/leveldb/include/leveldb/env.h b/src/leveldb/include/leveldb/env.h
index 275d441eae..96c21b3966 100644
--- a/src/leveldb/include/leveldb/env.h
+++ b/src/leveldb/include/leveldb/env.h
@@ -13,12 +13,36 @@
#ifndef STORAGE_LEVELDB_INCLUDE_ENV_H_
#define STORAGE_LEVELDB_INCLUDE_ENV_H_
-#include <string>
-#include <vector>
#include <stdarg.h>
#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "leveldb/export.h"
#include "leveldb/status.h"
+#if defined(_WIN32)
+// The leveldb::Env class below contains a DeleteFile method.
+// At the same time, <windows.h>, a fairly popular header
+// file for Windows applications, defines a DeleteFile macro.
+//
+// Without any intervention on our part, the result of this
+// unfortunate coincidence is that the name of the
+// leveldb::Env::DeleteFile method seen by the compiler depends on
+// whether <windows.h> was included before or after the LevelDB
+// headers.
+//
+// To avoid headaches, we undefined DeleteFile (if defined) and
+// redefine it at the bottom of this file. This way <windows.h>
+// can be included before this file (or not at all) and the
+// exported method will always be leveldb::Env::DeleteFile.
+#if defined(DeleteFile)
+#undef DeleteFile
+#define LEVELDB_DELETEFILE_UNDEFINED
+#endif // defined(DeleteFile)
+#endif // defined(_WIN32)
+
namespace leveldb {
class FileLock;
@@ -28,9 +52,13 @@ class SequentialFile;
class Slice;
class WritableFile;
-class Env {
+class LEVELDB_EXPORT Env {
public:
- Env() { }
+ Env() = default;
+
+ Env(const Env&) = delete;
+ Env& operator=(const Env&) = delete;
+
virtual ~Env();
// Return a default environment suitable for the current operating
@@ -40,20 +68,22 @@ class Env {
// The result of Default() belongs to leveldb and must never be deleted.
static Env* Default();
- // Create a brand new sequentially-readable file with the specified name.
+ // Create an object that sequentially reads the file with the specified name.
// On success, stores a pointer to the new file in *result and returns OK.
- // On failure stores NULL in *result and returns non-OK. If the file does
- // not exist, returns a non-OK status.
+ // On failure stores nullptr in *result and returns non-OK. If the file does
+ // not exist, returns a non-OK status. Implementations should return a
+ // NotFound status when the file does not exist.
//
// The returned file will only be accessed by one thread at a time.
virtual Status NewSequentialFile(const std::string& fname,
SequentialFile** result) = 0;
- // Create a brand new random access read-only file with the
+ // Create an object supporting random-access reads from the file with the
// specified name. On success, stores a pointer to the new file in
- // *result and returns OK. On failure stores NULL in *result and
+ // *result and returns OK. On failure stores nullptr in *result and
// returns non-OK. If the file does not exist, returns a non-OK
- // status.
+ // status. Implementations should return a NotFound status when the file does
+ // not exist.
//
// The returned file may be concurrently accessed by multiple threads.
virtual Status NewRandomAccessFile(const std::string& fname,
@@ -62,7 +92,7 @@ class Env {
// Create an object that writes to a new file with the specified
// name. Deletes any existing file with the same name and creates a
// new file. On success, stores a pointer to the new file in
- // *result and returns OK. On failure stores NULL in *result and
+ // *result and returns OK. On failure stores nullptr in *result and
// returns non-OK.
//
// The returned file will only be accessed by one thread at a time.
@@ -72,7 +102,7 @@ class Env {
// Create an object that either appends to an existing file, or
// writes to a new file (if the file does not exist to begin with).
// On success, stores a pointer to the new file in *result and
- // returns OK. On failure stores NULL in *result and returns
+ // returns OK. On failure stores nullptr in *result and returns
// non-OK.
//
// The returned file will only be accessed by one thread at a time.
@@ -110,7 +140,7 @@ class Env {
const std::string& target) = 0;
// Lock the specified file. Used to prevent concurrent access to
- // the same db by multiple processes. On failure, stores NULL in
+ // the same db by multiple processes. On failure, stores nullptr in
// *lock and returns non-OK.
//
// On success, stores a pointer to the object that represents the
@@ -136,16 +166,14 @@ class Env {
// added to the same Env may run concurrently in different threads.
// I.e., the caller may not assume that background work items are
// serialized.
- virtual void Schedule(
- void (*function)(void* arg),
- void* arg) = 0;
+ virtual void Schedule(void (*function)(void* arg), void* arg) = 0;
// Start a new thread, invoking "function(arg)" within the new thread.
// When "function(arg)" returns, the thread will be destroyed.
virtual void StartThread(void (*function)(void* arg), void* arg) = 0;
// *path is set to a temporary directory that can be used for testing. It may
- // or many not have just been created. The directory may or may not differ
+ // or may not have just been created. The directory may or may not differ
// between runs of the same process, but subsequent calls will return the
// same directory.
virtual Status GetTestDirectory(std::string* path) = 0;
@@ -159,17 +187,16 @@ class Env {
// Sleep/delay the thread for the prescribed number of micro-seconds.
virtual void SleepForMicroseconds(int micros) = 0;
-
- private:
- // No copying allowed
- Env(const Env&);
- void operator=(const Env&);
};
// A file abstraction for reading sequentially through a file
-class SequentialFile {
+class LEVELDB_EXPORT SequentialFile {
public:
- SequentialFile() { }
+ SequentialFile() = default;
+
+ SequentialFile(const SequentialFile&) = delete;
+ SequentialFile& operator=(const SequentialFile&) = delete;
+
virtual ~SequentialFile();
// Read up to "n" bytes from the file. "scratch[0..n-1]" may be
@@ -193,17 +220,16 @@ class SequentialFile {
// Get a name for the file, only for error reporting
virtual std::string GetName() const = 0;
-
- private:
- // No copying allowed
- SequentialFile(const SequentialFile&);
- void operator=(const SequentialFile&);
};
// A file abstraction for randomly reading the contents of a file.
-class RandomAccessFile {
+class LEVELDB_EXPORT RandomAccessFile {
public:
- RandomAccessFile() { }
+ RandomAccessFile() = default;
+
+ RandomAccessFile(const RandomAccessFile&) = delete;
+ RandomAccessFile& operator=(const RandomAccessFile&) = delete;
+
virtual ~RandomAccessFile();
// Read up to "n" bytes from the file starting at "offset".
@@ -220,19 +246,18 @@ class RandomAccessFile {
// Get a name for the file, only for error reporting
virtual std::string GetName() const = 0;
-
- private:
- // No copying allowed
- RandomAccessFile(const RandomAccessFile&);
- void operator=(const RandomAccessFile&);
};
// A file abstraction for sequential writing. The implementation
// must provide buffering since callers may append small fragments
// at a time to the file.
-class WritableFile {
+class LEVELDB_EXPORT WritableFile {
public:
- WritableFile() { }
+ WritableFile() = default;
+
+ WritableFile(const WritableFile&) = delete;
+ WritableFile& operator=(const WritableFile&) = delete;
+
virtual ~WritableFile();
virtual Status Append(const Slice& data) = 0;
@@ -242,119 +267,130 @@ class WritableFile {
// Get a name for the file, only for error reporting
virtual std::string GetName() const = 0;
-
- private:
- // No copying allowed
- WritableFile(const WritableFile&);
- void operator=(const WritableFile&);
};
// An interface for writing log messages.
-class Logger {
+class LEVELDB_EXPORT Logger {
public:
- Logger() { }
+ Logger() = default;
+
+ Logger(const Logger&) = delete;
+ Logger& operator=(const Logger&) = delete;
+
virtual ~Logger();
// Write an entry to the log file with the specified format.
virtual void Logv(const char* format, va_list ap) = 0;
-
- private:
- // No copying allowed
- Logger(const Logger&);
- void operator=(const Logger&);
};
-
// Identifies a locked file.
-class FileLock {
+class LEVELDB_EXPORT FileLock {
public:
- FileLock() { }
+ FileLock() = default;
+
+ FileLock(const FileLock&) = delete;
+ FileLock& operator=(const FileLock&) = delete;
+
virtual ~FileLock();
- private:
- // No copying allowed
- FileLock(const FileLock&);
- void operator=(const FileLock&);
};
-// Log the specified data to *info_log if info_log is non-NULL.
-extern void Log(Logger* info_log, const char* format, ...)
-# if defined(__GNUC__) || defined(__clang__)
- __attribute__((__format__ (__printf__, 2, 3)))
-# endif
+// Log the specified data to *info_log if info_log is non-null.
+void Log(Logger* info_log, const char* format, ...)
+#if defined(__GNUC__) || defined(__clang__)
+ __attribute__((__format__(__printf__, 2, 3)))
+#endif
;
// A utility routine: write "data" to the named file.
-extern Status WriteStringToFile(Env* env, const Slice& data,
- const std::string& fname);
+LEVELDB_EXPORT Status WriteStringToFile(Env* env, const Slice& data,
+ const std::string& fname);
// A utility routine: read contents of named file into *data
-extern Status ReadFileToString(Env* env, const std::string& fname,
- std::string* data);
+LEVELDB_EXPORT Status ReadFileToString(Env* env, const std::string& fname,
+ std::string* data);
// An implementation of Env that forwards all calls to another Env.
// May be useful to clients who wish to override just part of the
// functionality of another Env.
-class EnvWrapper : public Env {
+class LEVELDB_EXPORT EnvWrapper : public Env {
public:
- // Initialize an EnvWrapper that delegates all calls to *t
- explicit EnvWrapper(Env* t) : target_(t) { }
+ // Initialize an EnvWrapper that delegates all calls to *t.
+ explicit EnvWrapper(Env* t) : target_(t) {}
virtual ~EnvWrapper();
- // Return the target to which this Env forwards all calls
+ // Return the target to which this Env forwards all calls.
Env* target() const { return target_; }
- // The following text is boilerplate that forwards all methods to target()
- Status NewSequentialFile(const std::string& f, SequentialFile** r) {
+ // The following text is boilerplate that forwards all methods to target().
+ Status NewSequentialFile(const std::string& f, SequentialFile** r) override {
return target_->NewSequentialFile(f, r);
}
- Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) {
+ Status NewRandomAccessFile(const std::string& f,
+ RandomAccessFile** r) override {
return target_->NewRandomAccessFile(f, r);
}
- Status NewWritableFile(const std::string& f, WritableFile** r) {
+ Status NewWritableFile(const std::string& f, WritableFile** r) override {
return target_->NewWritableFile(f, r);
}
- Status NewAppendableFile(const std::string& f, WritableFile** r) {
+ Status NewAppendableFile(const std::string& f, WritableFile** r) override {
return target_->NewAppendableFile(f, r);
}
- bool FileExists(const std::string& f) { return target_->FileExists(f); }
- Status GetChildren(const std::string& dir, std::vector<std::string>* r) {
+ bool FileExists(const std::string& f) override {
+ return target_->FileExists(f);
+ }
+ Status GetChildren(const std::string& dir,
+ std::vector<std::string>* r) override {
return target_->GetChildren(dir, r);
}
- Status DeleteFile(const std::string& f) { return target_->DeleteFile(f); }
- Status CreateDir(const std::string& d) { return target_->CreateDir(d); }
- Status DeleteDir(const std::string& d) { return target_->DeleteDir(d); }
- Status GetFileSize(const std::string& f, uint64_t* s) {
+ Status DeleteFile(const std::string& f) override {
+ return target_->DeleteFile(f);
+ }
+ Status CreateDir(const std::string& d) override {
+ return target_->CreateDir(d);
+ }
+ Status DeleteDir(const std::string& d) override {
+ return target_->DeleteDir(d);
+ }
+ Status GetFileSize(const std::string& f, uint64_t* s) override {
return target_->GetFileSize(f, s);
}
- Status RenameFile(const std::string& s, const std::string& t) {
+ Status RenameFile(const std::string& s, const std::string& t) override {
return target_->RenameFile(s, t);
}
- Status LockFile(const std::string& f, FileLock** l) {
+ Status LockFile(const std::string& f, FileLock** l) override {
return target_->LockFile(f, l);
}
- Status UnlockFile(FileLock* l) { return target_->UnlockFile(l); }
- void Schedule(void (*f)(void*), void* a) {
+ Status UnlockFile(FileLock* l) override { return target_->UnlockFile(l); }
+ void Schedule(void (*f)(void*), void* a) override {
return target_->Schedule(f, a);
}
- void StartThread(void (*f)(void*), void* a) {
+ void StartThread(void (*f)(void*), void* a) override {
return target_->StartThread(f, a);
}
- virtual Status GetTestDirectory(std::string* path) {
+ Status GetTestDirectory(std::string* path) override {
return target_->GetTestDirectory(path);
}
- virtual Status NewLogger(const std::string& fname, Logger** result) {
+ Status NewLogger(const std::string& fname, Logger** result) override {
return target_->NewLogger(fname, result);
}
- uint64_t NowMicros() {
- return target_->NowMicros();
- }
- void SleepForMicroseconds(int micros) {
+ uint64_t NowMicros() override { return target_->NowMicros(); }
+ void SleepForMicroseconds(int micros) override {
target_->SleepForMicroseconds(micros);
}
+
private:
Env* target_;
};
} // namespace leveldb
+// Redefine DeleteFile if necessary.
+#if defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED)
+#if defined(UNICODE)
+#define DeleteFile DeleteFileW
+#else
+#define DeleteFile DeleteFileA
+#endif // defined(UNICODE)
+#endif // defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED)
+
#endif // STORAGE_LEVELDB_INCLUDE_ENV_H_
diff --git a/src/leveldb/include/leveldb/export.h b/src/leveldb/include/leveldb/export.h
new file mode 100644
index 0000000000..6ba9b183da
--- /dev/null
+++ b/src/leveldb/include/leveldb/export.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2017 The LevelDB Authors. All rights reserved.
+// 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.
+
+#ifndef STORAGE_LEVELDB_INCLUDE_EXPORT_H_
+#define STORAGE_LEVELDB_INCLUDE_EXPORT_H_
+
+#if !defined(LEVELDB_EXPORT)
+
+#if defined(LEVELDB_SHARED_LIBRARY)
+#if defined(_WIN32)
+
+#if defined(LEVELDB_COMPILE_LIBRARY)
+#define LEVELDB_EXPORT __declspec(dllexport)
+#else
+#define LEVELDB_EXPORT __declspec(dllimport)
+#endif // defined(LEVELDB_COMPILE_LIBRARY)
+
+#else // defined(_WIN32)
+#if defined(LEVELDB_COMPILE_LIBRARY)
+#define LEVELDB_EXPORT __attribute__((visibility("default")))
+#else
+#define LEVELDB_EXPORT
+#endif
+#endif // defined(_WIN32)
+
+#else // defined(LEVELDB_SHARED_LIBRARY)
+#define LEVELDB_EXPORT
+#endif
+
+#endif // !defined(LEVELDB_EXPORT)
+
+#endif // STORAGE_LEVELDB_INCLUDE_EXPORT_H_
diff --git a/src/leveldb/include/leveldb/filter_policy.h b/src/leveldb/include/leveldb/filter_policy.h
index 1fba08001f..49c8eda776 100644
--- a/src/leveldb/include/leveldb/filter_policy.h
+++ b/src/leveldb/include/leveldb/filter_policy.h
@@ -18,11 +18,13 @@
#include <string>
+#include "leveldb/export.h"
+
namespace leveldb {
class Slice;
-class FilterPolicy {
+class LEVELDB_EXPORT FilterPolicy {
public:
virtual ~FilterPolicy();
@@ -38,8 +40,8 @@ class FilterPolicy {
//
// Warning: do not change the initial contents of *dst. Instead,
// append the newly constructed filter to *dst.
- virtual void CreateFilter(const Slice* keys, int n, std::string* dst)
- const = 0;
+ virtual void CreateFilter(const Slice* keys, int n,
+ std::string* dst) const = 0;
// "filter" contains the data appended by a preceding call to
// CreateFilter() on this class. This method must return true if
@@ -63,8 +65,8 @@ class FilterPolicy {
// ignores trailing spaces, it would be incorrect to use a
// FilterPolicy (like NewBloomFilterPolicy) that does not ignore
// trailing spaces in keys.
-extern const FilterPolicy* NewBloomFilterPolicy(int bits_per_key);
+LEVELDB_EXPORT const FilterPolicy* NewBloomFilterPolicy(int bits_per_key);
-}
+} // namespace leveldb
#endif // STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_
diff --git a/src/leveldb/include/leveldb/iterator.h b/src/leveldb/include/leveldb/iterator.h
index da631ed9d8..bb9a5df8f5 100644
--- a/src/leveldb/include/leveldb/iterator.h
+++ b/src/leveldb/include/leveldb/iterator.h
@@ -15,14 +15,19 @@
#ifndef STORAGE_LEVELDB_INCLUDE_ITERATOR_H_
#define STORAGE_LEVELDB_INCLUDE_ITERATOR_H_
+#include "leveldb/export.h"
#include "leveldb/slice.h"
#include "leveldb/status.h"
namespace leveldb {
-class Iterator {
+class LEVELDB_EXPORT Iterator {
public:
Iterator();
+
+ Iterator(const Iterator&) = delete;
+ Iterator& operator=(const Iterator&) = delete;
+
virtual ~Iterator();
// An iterator is either positioned at a key/value pair, or
@@ -72,28 +77,35 @@ class Iterator {
//
// Note that unlike all of the preceding methods, this method is
// not abstract and therefore clients should not override it.
- typedef void (*CleanupFunction)(void* arg1, void* arg2);
+ using CleanupFunction = void (*)(void* arg1, void* arg2);
void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
private:
- struct Cleanup {
+ // Cleanup functions are stored in a single-linked list.
+ // The list's head node is inlined in the iterator.
+ struct CleanupNode {
+ // True if the node is not used. Only head nodes might be unused.
+ bool IsEmpty() const { return function == nullptr; }
+ // Invokes the cleanup function.
+ void Run() {
+ assert(function != nullptr);
+ (*function)(arg1, arg2);
+ }
+
+ // The head node is used if the function pointer is not null.
CleanupFunction function;
void* arg1;
void* arg2;
- Cleanup* next;
+ CleanupNode* next;
};
- Cleanup cleanup_;
-
- // No copying allowed
- Iterator(const Iterator&);
- void operator=(const Iterator&);
+ CleanupNode cleanup_head_;
};
// Return an empty iterator (yields nothing).
-extern Iterator* NewEmptyIterator();
+LEVELDB_EXPORT Iterator* NewEmptyIterator();
// Return an empty iterator with the specified status.
-extern Iterator* NewErrorIterator(const Status& status);
+LEVELDB_EXPORT Iterator* NewErrorIterator(const Status& status);
} // namespace leveldb
diff --git a/src/leveldb/include/leveldb/options.h b/src/leveldb/include/leveldb/options.h
index 976e38122a..b7487726bc 100644
--- a/src/leveldb/include/leveldb/options.h
+++ b/src/leveldb/include/leveldb/options.h
@@ -7,6 +7,8 @@
#include <stddef.h>
+#include "leveldb/export.h"
+
namespace leveldb {
class Cache;
@@ -23,12 +25,15 @@ class Snapshot;
enum CompressionType {
// NOTE: do not change the values of existing entries, as these are
// part of the persistent format on disk.
- kNoCompression = 0x0,
+ kNoCompression = 0x0,
kSnappyCompression = 0x1
};
// Options to control the behavior of a database (passed to DB::Open)
-struct Options {
+struct LEVELDB_EXPORT Options {
+ // Create an Options object with default values for all fields.
+ Options();
+
// -------------------
// Parameters that affect behavior
@@ -41,20 +46,17 @@ struct Options {
const Comparator* comparator;
// If true, the database will be created if it is missing.
- // Default: false
- bool create_if_missing;
+ bool create_if_missing = false;
// If true, an error is raised if the database already exists.
- // Default: false
- bool error_if_exists;
+ bool error_if_exists = false;
// If true, the implementation will do aggressive checking of the
// data it is processing and will stop early if it detects any
// errors. This may have unforeseen ramifications: for example, a
// corruption of one DB entry may cause a large number of entries to
// become unreadable or for the entire DB to become unopenable.
- // Default: false
- bool paranoid_checks;
+ bool paranoid_checks = false;
// Use the specified object to interact with the environment,
// e.g. to read/write files, schedule background work, etc.
@@ -62,10 +64,9 @@ struct Options {
Env* env;
// Any internal progress/error information generated by the db will
- // be written to info_log if it is non-NULL, or to a file stored
- // in the same directory as the DB contents if info_log is NULL.
- // Default: NULL
- Logger* info_log;
+ // be written to info_log if it is non-null, or to a file stored
+ // in the same directory as the DB contents if info_log is null.
+ Logger* info_log = nullptr;
// -------------------
// Parameters that affect performance
@@ -78,39 +79,30 @@ struct Options {
// so you may wish to adjust this parameter to control memory usage.
// Also, a larger write buffer will result in a longer recovery time
// the next time the database is opened.
- //
- // Default: 4MB
- size_t write_buffer_size;
+ size_t write_buffer_size = 4 * 1024 * 1024;
// Number of open files that can be used by the DB. You may need to
// increase this if your database has a large working set (budget
// one open file per 2MB of working set).
- //
- // Default: 1000
- int max_open_files;
+ int max_open_files = 1000;
// Control over blocks (user data is stored in a set of blocks, and
// a block is the unit of reading from disk).
- // If non-NULL, use the specified cache for blocks.
- // If NULL, leveldb will automatically create and use an 8MB internal cache.
- // Default: NULL
- Cache* block_cache;
+ // If non-null, use the specified cache for blocks.
+ // If null, leveldb will automatically create and use an 8MB internal cache.
+ Cache* block_cache = nullptr;
// Approximate size of user data packed per block. Note that the
// block size specified here corresponds to uncompressed data. The
// actual size of the unit read from disk may be smaller if
// compression is enabled. This parameter can be changed dynamically.
- //
- // Default: 4K
- size_t block_size;
+ size_t block_size = 4 * 1024;
// Number of keys between restart points for delta encoding of keys.
// This parameter can be changed dynamically. Most clients should
// leave this parameter alone.
- //
- // Default: 16
- int block_restart_interval;
+ int block_restart_interval = 16;
// Leveldb will write up to this amount of bytes to a file before
// switching to a new one.
@@ -120,9 +112,7 @@ struct Options {
// compactions and hence longer latency/performance hiccups.
// Another reason to increase this parameter might be when you are
// initially populating a large database.
- //
- // Default: 2MB
- size_t max_file_size;
+ size_t max_file_size = 2 * 1024 * 1024;
// Compress blocks using the specified compression algorithm. This
// parameter can be changed dynamically.
@@ -138,53 +128,43 @@ struct Options {
// worth switching to kNoCompression. Even if the input data is
// incompressible, the kSnappyCompression implementation will
// efficiently detect that and will switch to uncompressed mode.
- CompressionType compression;
+ CompressionType compression = kSnappyCompression;
// EXPERIMENTAL: If true, append to existing MANIFEST and log files
// when a database is opened. This can significantly speed up open.
//
// Default: currently false, but may become true later.
- bool reuse_logs;
+ bool reuse_logs = false;
- // If non-NULL, use the specified filter policy to reduce disk reads.
+ // If non-null, use the specified filter policy to reduce disk reads.
// Many applications will benefit from passing the result of
// NewBloomFilterPolicy() here.
- //
- // Default: NULL
- const FilterPolicy* filter_policy;
-
- // Create an Options object with default values for all fields.
- Options();
+ const FilterPolicy* filter_policy = nullptr;
};
// Options that control read operations
-struct ReadOptions {
+struct LEVELDB_EXPORT ReadOptions {
+ ReadOptions() = default;
+
// If true, all data read from underlying storage will be
// verified against corresponding checksums.
- // Default: false
- bool verify_checksums;
+ bool verify_checksums = false;
// Should the data read for this iteration be cached in memory?
// Callers may wish to set this field to false for bulk scans.
- // Default: true
- bool fill_cache;
+ bool fill_cache = true;
- // If "snapshot" is non-NULL, read as of the supplied snapshot
+ // If "snapshot" is non-null, read as of the supplied snapshot
// (which must belong to the DB that is being read and which must
- // not have been released). If "snapshot" is NULL, use an implicit
+ // not have been released). If "snapshot" is null, use an implicit
// snapshot of the state at the beginning of this read operation.
- // Default: NULL
- const Snapshot* snapshot;
-
- ReadOptions()
- : verify_checksums(false),
- fill_cache(true),
- snapshot(NULL) {
- }
+ const Snapshot* snapshot = nullptr;
};
// Options that control write operations
-struct WriteOptions {
+struct LEVELDB_EXPORT WriteOptions {
+ WriteOptions() = default;
+
// If true, the write will be flushed from the operating system
// buffer cache (by calling WritableFile::Sync()) before the write
// is considered complete. If this flag is true, writes will be
@@ -199,13 +179,7 @@ struct WriteOptions {
// crash semantics as the "write()" system call. A DB write
// with sync==true has similar crash semantics to a "write()"
// system call followed by "fsync()".
- //
- // Default: false
- bool sync;
-
- WriteOptions()
- : sync(false) {
- }
+ bool sync = false;
};
} // namespace leveldb
diff --git a/src/leveldb/include/leveldb/slice.h b/src/leveldb/include/leveldb/slice.h
index bc367986f7..2df417dc31 100644
--- a/src/leveldb/include/leveldb/slice.h
+++ b/src/leveldb/include/leveldb/slice.h
@@ -18,23 +18,30 @@
#include <assert.h>
#include <stddef.h>
#include <string.h>
+
#include <string>
+#include "leveldb/export.h"
+
namespace leveldb {
-class Slice {
+class LEVELDB_EXPORT Slice {
public:
// Create an empty slice.
- Slice() : data_(""), size_(0) { }
+ Slice() : data_(""), size_(0) {}
// Create a slice that refers to d[0,n-1].
- Slice(const char* d, size_t n) : data_(d), size_(n) { }
+ Slice(const char* d, size_t n) : data_(d), size_(n) {}
// Create a slice that refers to the contents of "s"
- Slice(const std::string& s) : data_(s.data()), size_(s.size()) { }
+ Slice(const std::string& s) : data_(s.data()), size_(s.size()) {}
// Create a slice that refers to s[0,strlen(s)-1]
- Slice(const char* s) : data_(s), size_(strlen(s)) { }
+ Slice(const char* s) : data_(s), size_(strlen(s)) {}
+
+ // Intentionally copyable.
+ Slice(const Slice&) = default;
+ Slice& operator=(const Slice&) = default;
// Return a pointer to the beginning of the referenced data
const char* data() const { return data_; }
@@ -53,7 +60,10 @@ class Slice {
}
// Change this slice to refer to an empty array
- void clear() { data_ = ""; size_ = 0; }
+ void clear() {
+ data_ = "";
+ size_ = 0;
+ }
// Drop the first "n" bytes from this slice.
void remove_prefix(size_t n) {
@@ -73,15 +83,12 @@ class Slice {
// Return true iff "x" is a prefix of "*this"
bool starts_with(const Slice& x) const {
- return ((size_ >= x.size_) &&
- (memcmp(data_, x.data_, x.size_) == 0));
+ return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0));
}
private:
const char* data_;
size_t size_;
-
- // Intentionally copyable
};
inline bool operator==(const Slice& x, const Slice& y) {
@@ -89,21 +96,20 @@ inline bool operator==(const Slice& x, const Slice& y) {
(memcmp(x.data(), y.data(), x.size()) == 0));
}
-inline bool operator!=(const Slice& x, const Slice& y) {
- return !(x == y);
-}
+inline bool operator!=(const Slice& x, const Slice& y) { return !(x == y); }
inline int Slice::compare(const Slice& b) const {
const size_t min_len = (size_ < b.size_) ? size_ : b.size_;
int r = memcmp(data_, b.data_, min_len);
if (r == 0) {
- if (size_ < b.size_) r = -1;
- else if (size_ > b.size_) r = +1;
+ if (size_ < b.size_)
+ r = -1;
+ else if (size_ > b.size_)
+ r = +1;
}
return r;
}
} // namespace leveldb
-
#endif // STORAGE_LEVELDB_INCLUDE_SLICE_H_
diff --git a/src/leveldb/include/leveldb/status.h b/src/leveldb/include/leveldb/status.h
index d9575f9753..e3273144e4 100644
--- a/src/leveldb/include/leveldb/status.h
+++ b/src/leveldb/include/leveldb/status.h
@@ -13,20 +13,25 @@
#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_
#define STORAGE_LEVELDB_INCLUDE_STATUS_H_
+#include <algorithm>
#include <string>
+
+#include "leveldb/export.h"
#include "leveldb/slice.h"
namespace leveldb {
-class Status {
+class LEVELDB_EXPORT Status {
public:
// Create a success status.
- Status() : state_(NULL) { }
+ Status() noexcept : state_(nullptr) {}
~Status() { delete[] state_; }
- // Copy the specified status.
- Status(const Status& s);
- void operator=(const Status& s);
+ Status(const Status& rhs);
+ Status& operator=(const Status& rhs);
+
+ Status(Status&& rhs) noexcept : state_(rhs.state_) { rhs.state_ = nullptr; }
+ Status& operator=(Status&& rhs) noexcept;
// Return a success status.
static Status OK() { return Status(); }
@@ -49,7 +54,7 @@ class Status {
}
// Returns true iff the status indicates success.
- bool ok() const { return (state_ == NULL); }
+ bool ok() const { return (state_ == nullptr); }
// Returns true iff the status indicates a NotFound error.
bool IsNotFound() const { return code() == kNotFound; }
@@ -71,13 +76,6 @@ class Status {
std::string ToString() const;
private:
- // OK status has a NULL state_. Otherwise, state_ is a new[] array
- // of the following form:
- // state_[0..3] == length of message
- // state_[4] == code
- // state_[5..] == message
- const char* state_;
-
enum Code {
kOk = 0,
kNotFound = 1,
@@ -88,23 +86,35 @@ class Status {
};
Code code() const {
- return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
+ return (state_ == nullptr) ? kOk : static_cast<Code>(state_[4]);
}
Status(Code code, const Slice& msg, const Slice& msg2);
static const char* CopyState(const char* s);
+
+ // OK status has a null state_. Otherwise, state_ is a new[] array
+ // of the following form:
+ // state_[0..3] == length of message
+ // state_[4] == code
+ // state_[5..] == message
+ const char* state_;
};
-inline Status::Status(const Status& s) {
- state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
+inline Status::Status(const Status& rhs) {
+ state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_);
}
-inline void Status::operator=(const Status& s) {
- // The following condition catches both aliasing (when this == &s),
- // and the common case where both s and *this are ok.
- if (state_ != s.state_) {
+inline Status& Status::operator=(const Status& rhs) {
+ // The following condition catches both aliasing (when this == &rhs),
+ // and the common case where both rhs and *this are ok.
+ if (state_ != rhs.state_) {
delete[] state_;
- state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
+ state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_);
}
+ return *this;
+}
+inline Status& Status::operator=(Status&& rhs) noexcept {
+ std::swap(state_, rhs.state_);
+ return *this;
}
} // namespace leveldb
diff --git a/src/leveldb/include/leveldb/table.h b/src/leveldb/include/leveldb/table.h
index a9746c3f5e..25c6013116 100644
--- a/src/leveldb/include/leveldb/table.h
+++ b/src/leveldb/include/leveldb/table.h
@@ -6,6 +6,8 @@
#define STORAGE_LEVELDB_INCLUDE_TABLE_H_
#include <stdint.h>
+
+#include "leveldb/export.h"
#include "leveldb/iterator.h"
namespace leveldb {
@@ -21,7 +23,7 @@ class TableCache;
// A Table is a sorted map from strings to strings. Tables are
// immutable and persistent. A Table may be safely accessed from
// multiple threads without external synchronization.
-class Table {
+class LEVELDB_EXPORT Table {
public:
// Attempt to open the table that is stored in bytes [0..file_size)
// of "file", and read the metadata entries necessary to allow
@@ -30,15 +32,16 @@ class Table {
// If successful, returns ok and sets "*table" to the newly opened
// table. The client should delete "*table" when no longer needed.
// If there was an error while initializing the table, sets "*table"
- // to NULL and returns a non-ok status. Does not take ownership of
+ // to nullptr and returns a non-ok status. Does not take ownership of
// "*source", but the client must ensure that "source" remains live
// for the duration of the returned table's lifetime.
//
// *file must remain live while this Table is in use.
- static Status Open(const Options& options,
- RandomAccessFile* file,
- uint64_t file_size,
- Table** table);
+ static Status Open(const Options& options, RandomAccessFile* file,
+ uint64_t file_size, Table** table);
+
+ Table(const Table&) = delete;
+ Table& operator=(const Table&) = delete;
~Table();
@@ -56,28 +59,24 @@ class Table {
uint64_t ApproximateOffsetOf(const Slice& key) const;
private:
+ friend class TableCache;
struct Rep;
- Rep* rep_;
- explicit Table(Rep* rep) { rep_ = rep; }
static Iterator* BlockReader(void*, const ReadOptions&, const Slice&);
+ explicit Table(Rep* rep) : rep_(rep) {}
+
// Calls (*handle_result)(arg, ...) with the entry found after a call
// to Seek(key). May not make such a call if filter policy says
// that key is not present.
- friend class TableCache;
- Status InternalGet(
- const ReadOptions&, const Slice& key,
- void* arg,
- void (*handle_result)(void* arg, const Slice& k, const Slice& v));
-
+ Status InternalGet(const ReadOptions&, const Slice& key, void* arg,
+ void (*handle_result)(void* arg, const Slice& k,
+ const Slice& v));
void ReadMeta(const Footer& footer);
void ReadFilter(const Slice& filter_handle_value);
- // No copying allowed
- Table(const Table&);
- void operator=(const Table&);
+ Rep* const rep_;
};
} // namespace leveldb
diff --git a/src/leveldb/include/leveldb/table_builder.h b/src/leveldb/include/leveldb/table_builder.h
index 5fd1dc71f1..7d8896bb89 100644
--- a/src/leveldb/include/leveldb/table_builder.h
+++ b/src/leveldb/include/leveldb/table_builder.h
@@ -14,6 +14,8 @@
#define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_
#include <stdint.h>
+
+#include "leveldb/export.h"
#include "leveldb/options.h"
#include "leveldb/status.h"
@@ -23,13 +25,16 @@ class BlockBuilder;
class BlockHandle;
class WritableFile;
-class TableBuilder {
+class LEVELDB_EXPORT TableBuilder {
public:
// Create a builder that will store the contents of the table it is
// building in *file. Does not close the file. It is up to the
// caller to close the file after calling Finish().
TableBuilder(const Options& options, WritableFile* file);
+ TableBuilder(const TableBuilder&) = delete;
+ TableBuilder& operator=(const TableBuilder&) = delete;
+
// REQUIRES: Either Finish() or Abandon() has been called.
~TableBuilder();
@@ -81,10 +86,6 @@ class TableBuilder {
struct Rep;
Rep* rep_;
-
- // No copying allowed
- TableBuilder(const TableBuilder&);
- void operator=(const TableBuilder&);
};
} // namespace leveldb
diff --git a/src/leveldb/include/leveldb/write_batch.h b/src/leveldb/include/leveldb/write_batch.h
index ee9aab68e0..94d4115fed 100644
--- a/src/leveldb/include/leveldb/write_batch.h
+++ b/src/leveldb/include/leveldb/write_batch.h
@@ -22,15 +22,29 @@
#define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_
#include <string>
+
+#include "leveldb/export.h"
#include "leveldb/status.h"
namespace leveldb {
class Slice;
-class WriteBatch {
+class LEVELDB_EXPORT WriteBatch {
public:
+ class LEVELDB_EXPORT Handler {
+ public:
+ virtual ~Handler();
+ virtual void Put(const Slice& key, const Slice& value) = 0;
+ virtual void Delete(const Slice& key) = 0;
+ };
+
WriteBatch();
+
+ // Intentionally copyable.
+ WriteBatch(const WriteBatch&) = default;
+ WriteBatch& operator=(const WriteBatch&) = default;
+
~WriteBatch();
// Store the mapping "key->value" in the database.
@@ -42,21 +56,26 @@ class WriteBatch {
// Clear all updates buffered in this batch.
void Clear();
+ // The size of the database changes caused by this batch.
+ //
+ // This number is tied to implementation details, and may change across
+ // releases. It is intended for LevelDB usage metrics.
+ size_t ApproximateSize() const;
+
+ // Copies the operations in "source" to this batch.
+ //
+ // This runs in O(source size) time. However, the constant factor is better
+ // than calling Iterate() over the source batch with a Handler that replicates
+ // the operations into this batch.
+ void Append(const WriteBatch& source);
+
// Support for iterating over the contents of a batch.
- class Handler {
- public:
- virtual ~Handler();
- virtual void Put(const Slice& key, const Slice& value) = 0;
- virtual void Delete(const Slice& key) = 0;
- };
Status Iterate(Handler* handler) const;
private:
friend class WriteBatchInternal;
std::string rep_; // See comment in write_batch.cc for the format of rep_
-
- // Intentionally copyable
};
} // namespace leveldb
diff --git a/src/leveldb/issues/issue178_test.cc b/src/leveldb/issues/issue178_test.cc
index 1b1cf8bb28..d50ffeb9d4 100644
--- a/src/leveldb/issues/issue178_test.cc
+++ b/src/leveldb/issues/issue178_test.cc
@@ -3,9 +3,9 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
// Test for issue 178: a manual compaction causes deleted data to reappear.
+#include <cstdlib>
#include <iostream>
#include <sstream>
-#include <cstdlib>
#include "leveldb/db.h"
#include "leveldb/write_batch.h"
@@ -21,11 +21,9 @@ std::string Key1(int i) {
return buf;
}
-std::string Key2(int i) {
- return Key1(i) + "_xxx";
-}
+std::string Key2(int i) { return Key1(i) + "_xxx"; }
-class Issue178 { };
+class Issue178 {};
TEST(Issue178, Test) {
// Get rid of any state from an old run.
@@ -87,6 +85,4 @@ TEST(Issue178, Test) {
} // anonymous namespace
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/issues/issue200_test.cc b/src/leveldb/issues/issue200_test.cc
index 1cec79f443..877b2afc47 100644
--- a/src/leveldb/issues/issue200_test.cc
+++ b/src/leveldb/issues/issue200_test.cc
@@ -11,14 +11,14 @@
namespace leveldb {
-class Issue200 { };
+class Issue200 {};
TEST(Issue200, Test) {
// Get rid of any state from an old run.
std::string dbpath = test::TmpDir() + "/leveldb_issue200_test";
DestroyDB(dbpath, Options());
- DB *db;
+ DB* db;
Options options;
options.create_if_missing = true;
ASSERT_OK(DB::Open(options, dbpath, &db));
@@ -31,7 +31,7 @@ TEST(Issue200, Test) {
ASSERT_OK(db->Put(write_options, "5", "f"));
ReadOptions read_options;
- Iterator *iter = db->NewIterator(read_options);
+ Iterator* iter = db->NewIterator(read_options);
// Add an element that should not be reflected in the iterator.
ASSERT_OK(db->Put(write_options, "25", "cd"));
@@ -54,6 +54,4 @@ TEST(Issue200, Test) {
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/issues/issue320_test.cc b/src/leveldb/issues/issue320_test.cc
new file mode 100644
index 0000000000..c5fcbfc6e7
--- /dev/null
+++ b/src/leveldb/issues/issue320_test.cc
@@ -0,0 +1,128 @@
+// Copyright (c) 2019 The LevelDB Authors. All rights reserved.
+// 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.
+
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "leveldb/db.h"
+#include "leveldb/write_batch.h"
+#include "util/testharness.h"
+
+namespace leveldb {
+
+namespace {
+
+// Creates a random number in the range of [0, max).
+int GenerateRandomNumber(int max) { return std::rand() % max; }
+
+std::string CreateRandomString(int32_t index) {
+ static const size_t len = 1024;
+ char bytes[len];
+ size_t i = 0;
+ while (i < 8) {
+ bytes[i] = 'a' + ((index >> (4 * i)) & 0xf);
+ ++i;
+ }
+ while (i < sizeof(bytes)) {
+ bytes[i] = 'a' + GenerateRandomNumber(26);
+ ++i;
+ }
+ return std::string(bytes, sizeof(bytes));
+}
+
+} // namespace
+
+class Issue320 {};
+
+TEST(Issue320, Test) {
+ std::srand(0);
+
+ bool delete_before_put = false;
+ bool keep_snapshots = true;
+
+ std::vector<std::unique_ptr<std::pair<std::string, std::string>>> test_map(
+ 10000);
+ std::vector<Snapshot const*> snapshots(100, nullptr);
+
+ DB* db;
+ Options options;
+ options.create_if_missing = true;
+
+ std::string dbpath = test::TmpDir() + "/leveldb_issue320_test";
+ ASSERT_OK(DB::Open(options, dbpath, &db));
+
+ uint32_t target_size = 10000;
+ uint32_t num_items = 0;
+ uint32_t count = 0;
+ std::string key;
+ std::string value, old_value;
+
+ WriteOptions writeOptions;
+ ReadOptions readOptions;
+ while (count < 200000) {
+ if ((++count % 1000) == 0) {
+ std::cout << "count: " << count << std::endl;
+ }
+
+ int index = GenerateRandomNumber(test_map.size());
+ WriteBatch batch;
+
+ if (test_map[index] == nullptr) {
+ num_items++;
+ test_map[index].reset(new std::pair<std::string, std::string>(
+ CreateRandomString(index), CreateRandomString(index)));
+ batch.Put(test_map[index]->first, test_map[index]->second);
+ } else {
+ ASSERT_OK(db->Get(readOptions, test_map[index]->first, &old_value));
+ if (old_value != test_map[index]->second) {
+ std::cout << "ERROR incorrect value returned by Get" << std::endl;
+ std::cout << " count=" << count << std::endl;
+ std::cout << " old value=" << old_value << std::endl;
+ std::cout << " test_map[index]->second=" << test_map[index]->second
+ << std::endl;
+ std::cout << " test_map[index]->first=" << test_map[index]->first
+ << std::endl;
+ std::cout << " index=" << index << std::endl;
+ ASSERT_EQ(old_value, test_map[index]->second);
+ }
+
+ if (num_items >= target_size && GenerateRandomNumber(100) > 30) {
+ batch.Delete(test_map[index]->first);
+ test_map[index] = nullptr;
+ --num_items;
+ } else {
+ test_map[index]->second = CreateRandomString(index);
+ if (delete_before_put) batch.Delete(test_map[index]->first);
+ batch.Put(test_map[index]->first, test_map[index]->second);
+ }
+ }
+
+ ASSERT_OK(db->Write(writeOptions, &batch));
+
+ if (keep_snapshots && GenerateRandomNumber(10) == 0) {
+ int i = GenerateRandomNumber(snapshots.size());
+ if (snapshots[i] != nullptr) {
+ db->ReleaseSnapshot(snapshots[i]);
+ }
+ snapshots[i] = db->GetSnapshot();
+ }
+ }
+
+ for (Snapshot const* snapshot : snapshots) {
+ if (snapshot) {
+ db->ReleaseSnapshot(snapshot);
+ }
+ }
+
+ delete db;
+ DestroyDB(dbpath, options);
+}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/port/README b/src/leveldb/port/README.md
index 422563e25c..8b171532e1 100644
--- a/src/leveldb/port/README
+++ b/src/leveldb/port/README.md
@@ -5,6 +5,6 @@ Code in the rest of the package includes "port.h" from this directory.
"port.h" in turn includes a platform specific "port_<platform>.h" file
that provides the platform specific implementation.
-See port_posix.h for an example of what must be provided in a platform
+See port_stdcxx.h for an example of what must be provided in a platform
specific header file.
diff --git a/src/leveldb/port/atomic_pointer.h b/src/leveldb/port/atomic_pointer.h
deleted file mode 100644
index d79a02230d..0000000000
--- a/src/leveldb/port/atomic_pointer.h
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
-// 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.
-
-// AtomicPointer provides storage for a lock-free pointer.
-// Platform-dependent implementation of AtomicPointer:
-// - If the platform provides a cheap barrier, we use it with raw pointers
-// - If <atomic> is present (on newer versions of gcc, it is), we use
-// a <atomic>-based AtomicPointer. However we prefer the memory
-// barrier based version, because at least on a gcc 4.4 32-bit build
-// on linux, we have encountered a buggy <atomic> implementation.
-// Also, some <atomic> implementations are much slower than a memory-barrier
-// based implementation (~16ns for <atomic> based acquire-load vs. ~1ns for
-// a barrier based acquire-load).
-// This code is based on atomicops-internals-* in Google's perftools:
-// http://code.google.com/p/google-perftools/source/browse/#svn%2Ftrunk%2Fsrc%2Fbase
-
-#ifndef PORT_ATOMIC_POINTER_H_
-#define PORT_ATOMIC_POINTER_H_
-
-#include <stdint.h>
-#ifdef LEVELDB_ATOMIC_PRESENT
-#include <atomic>
-#endif
-#ifdef OS_WIN
-#include <windows.h>
-#endif
-#ifdef OS_MACOSX
-#include <libkern/OSAtomic.h>
-#endif
-
-#if defined(_M_X64) || defined(__x86_64__)
-#define ARCH_CPU_X86_FAMILY 1
-#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
-#define ARCH_CPU_X86_FAMILY 1
-#elif defined(__ARMEL__)
-#define ARCH_CPU_ARM_FAMILY 1
-#elif defined(__aarch64__)
-#define ARCH_CPU_ARM64_FAMILY 1
-#elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__)
-#define ARCH_CPU_PPC_FAMILY 1
-#elif defined(__mips__)
-#define ARCH_CPU_MIPS_FAMILY 1
-#endif
-
-namespace leveldb {
-namespace port {
-
-// AtomicPointer based on <cstdatomic> if available
-#if defined(LEVELDB_ATOMIC_PRESENT)
-class AtomicPointer {
- private:
- std::atomic<void*> rep_;
- public:
- AtomicPointer() { }
- explicit AtomicPointer(void* v) : rep_(v) { }
- inline void* Acquire_Load() const {
- return rep_.load(std::memory_order_acquire);
- }
- inline void Release_Store(void* v) {
- rep_.store(v, std::memory_order_release);
- }
- inline void* NoBarrier_Load() const {
- return rep_.load(std::memory_order_relaxed);
- }
- inline void NoBarrier_Store(void* v) {
- rep_.store(v, std::memory_order_relaxed);
- }
-};
-
-#else
-
-// Define MemoryBarrier() if available
-// Windows on x86
-#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
-// windows.h already provides a MemoryBarrier(void) macro
-// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx
-#define LEVELDB_HAVE_MEMORY_BARRIER
-
-// Mac OS
-#elif defined(OS_MACOSX)
-inline void MemoryBarrier() {
- OSMemoryBarrier();
-}
-#define LEVELDB_HAVE_MEMORY_BARRIER
-
-// Gcc on x86
-#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__)
-inline void MemoryBarrier() {
- // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
- // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
- __asm__ __volatile__("" : : : "memory");
-}
-#define LEVELDB_HAVE_MEMORY_BARRIER
-
-// Sun Studio
-#elif defined(ARCH_CPU_X86_FAMILY) && defined(__SUNPRO_CC)
-inline void MemoryBarrier() {
- // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
- // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
- asm volatile("" : : : "memory");
-}
-#define LEVELDB_HAVE_MEMORY_BARRIER
-
-// ARM Linux
-#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__)
-typedef void (*LinuxKernelMemoryBarrierFunc)(void);
-// The Linux ARM kernel provides a highly optimized device-specific memory
-// barrier function at a fixed memory address that is mapped in every
-// user-level process.
-//
-// This beats using CPU-specific instructions which are, on single-core
-// devices, un-necessary and very costly (e.g. ARMv7-A "dmb" takes more
-// than 180ns on a Cortex-A8 like the one on a Nexus One). Benchmarking
-// shows that the extra function call cost is completely negligible on
-// multi-core devices.
-//
-inline void MemoryBarrier() {
- (*(LinuxKernelMemoryBarrierFunc)0xffff0fa0)();
-}
-#define LEVELDB_HAVE_MEMORY_BARRIER
-
-// ARM64
-#elif defined(ARCH_CPU_ARM64_FAMILY)
-inline void MemoryBarrier() {
- asm volatile("dmb sy" : : : "memory");
-}
-#define LEVELDB_HAVE_MEMORY_BARRIER
-
-// PPC
-#elif defined(ARCH_CPU_PPC_FAMILY) && defined(__GNUC__)
-inline void MemoryBarrier() {
- // TODO for some powerpc expert: is there a cheaper suitable variant?
- // Perhaps by having separate barriers for acquire and release ops.
- asm volatile("sync" : : : "memory");
-}
-#define LEVELDB_HAVE_MEMORY_BARRIER
-
-// MIPS
-#elif defined(ARCH_CPU_MIPS_FAMILY) && defined(__GNUC__)
-inline void MemoryBarrier() {
- __asm__ __volatile__("sync" : : : "memory");
-}
-#define LEVELDB_HAVE_MEMORY_BARRIER
-
-#endif
-
-// AtomicPointer built using platform-specific MemoryBarrier()
-#if defined(LEVELDB_HAVE_MEMORY_BARRIER)
-class AtomicPointer {
- private:
- void* rep_;
- public:
- AtomicPointer() { }
- explicit AtomicPointer(void* p) : rep_(p) {}
- inline void* NoBarrier_Load() const { return rep_; }
- inline void NoBarrier_Store(void* v) { rep_ = v; }
- inline void* Acquire_Load() const {
- void* result = rep_;
- MemoryBarrier();
- return result;
- }
- inline void Release_Store(void* v) {
- MemoryBarrier();
- rep_ = v;
- }
-};
-
-// Atomic pointer based on sparc memory barriers
-#elif defined(__sparcv9) && defined(__GNUC__)
-class AtomicPointer {
- private:
- void* rep_;
- public:
- AtomicPointer() { }
- explicit AtomicPointer(void* v) : rep_(v) { }
- inline void* Acquire_Load() const {
- void* val;
- __asm__ __volatile__ (
- "ldx [%[rep_]], %[val] \n\t"
- "membar #LoadLoad|#LoadStore \n\t"
- : [val] "=r" (val)
- : [rep_] "r" (&rep_)
- : "memory");
- return val;
- }
- inline void Release_Store(void* v) {
- __asm__ __volatile__ (
- "membar #LoadStore|#StoreStore \n\t"
- "stx %[v], [%[rep_]] \n\t"
- :
- : [rep_] "r" (&rep_), [v] "r" (v)
- : "memory");
- }
- inline void* NoBarrier_Load() const { return rep_; }
- inline void NoBarrier_Store(void* v) { rep_ = v; }
-};
-
-// Atomic pointer based on ia64 acq/rel
-#elif defined(__ia64) && defined(__GNUC__)
-class AtomicPointer {
- private:
- void* rep_;
- public:
- AtomicPointer() { }
- explicit AtomicPointer(void* v) : rep_(v) { }
- inline void* Acquire_Load() const {
- void* val ;
- __asm__ __volatile__ (
- "ld8.acq %[val] = [%[rep_]] \n\t"
- : [val] "=r" (val)
- : [rep_] "r" (&rep_)
- : "memory"
- );
- return val;
- }
- inline void Release_Store(void* v) {
- __asm__ __volatile__ (
- "st8.rel [%[rep_]] = %[v] \n\t"
- :
- : [rep_] "r" (&rep_), [v] "r" (v)
- : "memory"
- );
- }
- inline void* NoBarrier_Load() const { return rep_; }
- inline void NoBarrier_Store(void* v) { rep_ = v; }
-};
-
-// We have neither MemoryBarrier(), nor <atomic>
-#else
-#error Please implement AtomicPointer for this platform.
-
-#endif
-#endif
-
-#undef LEVELDB_HAVE_MEMORY_BARRIER
-#undef ARCH_CPU_X86_FAMILY
-#undef ARCH_CPU_ARM_FAMILY
-#undef ARCH_CPU_ARM64_FAMILY
-#undef ARCH_CPU_PPC_FAMILY
-
-} // namespace port
-} // namespace leveldb
-
-#endif // PORT_ATOMIC_POINTER_H_
diff --git a/src/leveldb/port/port.h b/src/leveldb/port/port.h
index 4baafa8e22..4b247f74f9 100644
--- a/src/leveldb/port/port.h
+++ b/src/leveldb/port/port.h
@@ -10,12 +10,10 @@
// Include the appropriate platform specific file below. If you are
// porting to a new platform, see "port_example.h" for documentation
// of what the new port_<platform>.h file must provide.
-#if defined(LEVELDB_PLATFORM_POSIX)
-# include "port/port_posix.h"
+#if defined(LEVELDB_PLATFORM_POSIX) || defined(LEVELDB_PLATFORM_WINDOWS)
+#include "port/port_stdcxx.h"
#elif defined(LEVELDB_PLATFORM_CHROMIUM)
-# include "port/port_chromium.h"
-#elif defined(LEVELDB_PLATFORM_WINDOWS)
-# include "port/port_win.h"
+#include "port/port_chromium.h"
#endif
#endif // STORAGE_LEVELDB_PORT_PORT_H_
diff --git a/src/leveldb/port/port_config.h.in b/src/leveldb/port/port_config.h.in
new file mode 100644
index 0000000000..21273153a3
--- /dev/null
+++ b/src/leveldb/port/port_config.h.in
@@ -0,0 +1,39 @@
+// Copyright 2017 The LevelDB Authors. All rights reserved.
+// 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.
+
+#ifndef STORAGE_LEVELDB_PORT_PORT_CONFIG_H_
+#define STORAGE_LEVELDB_PORT_PORT_CONFIG_H_
+
+// Define to 1 if you have a definition for fdatasync() in <unistd.h>.
+#if !defined(HAVE_FDATASYNC)
+#cmakedefine01 HAVE_FDATASYNC
+#endif // !defined(HAVE_FDATASYNC)
+
+// Define to 1 if you have a definition for F_FULLFSYNC in <fcntl.h>.
+#if !defined(HAVE_FULLFSYNC)
+#cmakedefine01 HAVE_FULLFSYNC
+#endif // !defined(HAVE_FULLFSYNC)
+
+// Define to 1 if you have a definition for O_CLOEXEC in <fcntl.h>.
+#if !defined(HAVE_O_CLOEXEC)
+#cmakedefine01 HAVE_O_CLOEXEC
+#endif // !defined(HAVE_O_CLOEXEC)
+
+// Define to 1 if you have Google CRC32C.
+#if !defined(HAVE_CRC32C)
+#cmakedefine01 HAVE_CRC32C
+#endif // !defined(HAVE_CRC32C)
+
+// Define to 1 if you have Google Snappy.
+#if !defined(HAVE_SNAPPY)
+#cmakedefine01 HAVE_SNAPPY
+#endif // !defined(HAVE_SNAPPY)
+
+// Define to 1 if your processor stores words with the most significant byte
+// first (like Motorola and SPARC, unlike Intel and VAX).
+#if !defined(LEVELDB_IS_BIG_ENDIAN)
+#cmakedefine01 LEVELDB_IS_BIG_ENDIAN
+#endif // !defined(LEVELDB_IS_BIG_ENDIAN)
+
+#endif // STORAGE_LEVELDB_PORT_PORT_CONFIG_H_ \ No newline at end of file
diff --git a/src/leveldb/port/port_example.h b/src/leveldb/port/port_example.h
index 5b1d027de5..1a8fca24b3 100644
--- a/src/leveldb/port/port_example.h
+++ b/src/leveldb/port/port_example.h
@@ -10,6 +10,8 @@
#ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_
#define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_
+#include "port/thread_annotations.h"
+
namespace leveldb {
namespace port {
@@ -23,23 +25,23 @@ static const bool kLittleEndian = true /* or some other expression */;
// ------------------ Threading -------------------
// A Mutex represents an exclusive lock.
-class Mutex {
+class LOCKABLE Mutex {
public:
Mutex();
~Mutex();
// Lock the mutex. Waits until other lockers have exited.
// Will deadlock if the mutex is already locked by this thread.
- void Lock();
+ void Lock() EXCLUSIVE_LOCK_FUNCTION();
// Unlock the mutex.
// REQUIRES: This mutex was locked by this thread.
- void Unlock();
+ void Unlock() UNLOCK_FUNCTION();
// Optionally crash if this thread does not hold this mutex.
// The implementation must be fast, especially if NDEBUG is
// defined. The implementation is allowed to skip all checks.
- void AssertHeld();
+ void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
};
class CondVar {
@@ -60,57 +62,18 @@ class CondVar {
void SignallAll();
};
-// Thread-safe initialization.
-// Used as follows:
-// static port::OnceType init_control = LEVELDB_ONCE_INIT;
-// static void Initializer() { ... do something ...; }
-// ...
-// port::InitOnce(&init_control, &Initializer);
-typedef intptr_t OnceType;
-#define LEVELDB_ONCE_INIT 0
-extern void InitOnce(port::OnceType*, void (*initializer)());
-
-// A type that holds a pointer that can be read or written atomically
-// (i.e., without word-tearing.)
-class AtomicPointer {
- private:
- intptr_t rep_;
- public:
- // Initialize to arbitrary value
- AtomicPointer();
-
- // Initialize to hold v
- explicit AtomicPointer(void* v) : rep_(v) { }
-
- // Read and return the stored pointer with the guarantee that no
- // later memory access (read or write) by this thread can be
- // reordered ahead of this read.
- void* Acquire_Load() const;
-
- // Set v as the stored pointer with the guarantee that no earlier
- // memory access (read or write) by this thread can be reordered
- // after this store.
- void Release_Store(void* v);
-
- // Read the stored pointer with no ordering guarantees.
- void* NoBarrier_Load() const;
-
- // Set va as the stored pointer with no ordering guarantees.
- void NoBarrier_Store(void* v);
-};
-
// ------------------ Compression -------------------
// Store the snappy compression of "input[0,input_length-1]" in *output.
// Returns false if snappy is not supported by this port.
-extern bool Snappy_Compress(const char* input, size_t input_length,
- std::string* output);
+bool Snappy_Compress(const char* input, size_t input_length,
+ std::string* output);
// If input[0,input_length-1] looks like a valid snappy compressed
// buffer, store the size of the uncompressed data in *result and
// return true. Else return false.
-extern bool Snappy_GetUncompressedLength(const char* input, size_t length,
- size_t* result);
+bool Snappy_GetUncompressedLength(const char* input, size_t length,
+ size_t* result);
// Attempt to snappy uncompress input[0,input_length-1] into *output.
// Returns true if successful, false if the input is invalid lightweight
@@ -119,19 +82,15 @@ extern bool Snappy_GetUncompressedLength(const char* input, size_t length,
// REQUIRES: at least the first "n" bytes of output[] must be writable
// where "n" is the result of a successful call to
// Snappy_GetUncompressedLength.
-extern bool Snappy_Uncompress(const char* input_data, size_t input_length,
- char* output);
+bool Snappy_Uncompress(const char* input_data, size_t input_length,
+ char* output);
// ------------------ Miscellaneous -------------------
// If heap profiling is not supported, returns false.
// Else repeatedly calls (*func)(arg, data, n) and then returns true.
// The concatenation of all "data[0,n-1]" fragments is the heap profile.
-extern bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg);
-
-// Determine whether a working accelerated crc32 implementation exists
-// Returns true if AcceleratedCRC32C is safe to call
-bool HasAcceleratedCRC32C();
+bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg);
// Extend the CRC to include the first n bytes of buf.
//
diff --git a/src/leveldb/port/port_posix.cc b/src/leveldb/port/port_posix.cc
deleted file mode 100644
index ec39e92195..0000000000
--- a/src/leveldb/port/port_posix.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
-// 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.
-
-#include "port/port_posix.h"
-
-#include <cstdlib>
-#include <stdio.h>
-#include <string.h>
-
-#if (defined(__x86_64__) || defined(__i386__)) && defined(__GNUC__)
-#include <cpuid.h>
-#endif
-
-namespace leveldb {
-namespace port {
-
-static void PthreadCall(const char* label, int result) {
- if (result != 0) {
- fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
- abort();
- }
-}
-
-Mutex::Mutex() { PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL)); }
-
-Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); }
-
-void Mutex::Lock() { PthreadCall("lock", pthread_mutex_lock(&mu_)); }
-
-void Mutex::Unlock() { PthreadCall("unlock", pthread_mutex_unlock(&mu_)); }
-
-CondVar::CondVar(Mutex* mu)
- : mu_(mu) {
- PthreadCall("init cv", pthread_cond_init(&cv_, NULL));
-}
-
-CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); }
-
-void CondVar::Wait() {
- PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_));
-}
-
-void CondVar::Signal() {
- PthreadCall("signal", pthread_cond_signal(&cv_));
-}
-
-void CondVar::SignalAll() {
- PthreadCall("broadcast", pthread_cond_broadcast(&cv_));
-}
-
-void InitOnce(OnceType* once, void (*initializer)()) {
- PthreadCall("once", pthread_once(once, initializer));
-}
-
-bool HasAcceleratedCRC32C() {
-#if (defined(__x86_64__) || defined(__i386__)) && defined(__GNUC__)
- unsigned int eax, ebx, ecx, edx;
- __get_cpuid(1, &eax, &ebx, &ecx, &edx);
- return (ecx & (1 << 20)) != 0;
-#else
- return false;
-#endif
-}
-
-} // namespace port
-} // namespace leveldb
diff --git a/src/leveldb/port/port_posix.h b/src/leveldb/port/port_posix.h
deleted file mode 100644
index d85fa5d63f..0000000000
--- a/src/leveldb/port/port_posix.h
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
-// 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.
-//
-// See port_example.h for documentation for the following types/functions.
-
-#ifndef STORAGE_LEVELDB_PORT_PORT_POSIX_H_
-#define STORAGE_LEVELDB_PORT_PORT_POSIX_H_
-
-#undef PLATFORM_IS_LITTLE_ENDIAN
-#if defined(OS_MACOSX)
- #include <machine/endian.h>
- #if defined(__DARWIN_LITTLE_ENDIAN) && defined(__DARWIN_BYTE_ORDER)
- #define PLATFORM_IS_LITTLE_ENDIAN \
- (__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN)
- #endif
-#elif defined(OS_SOLARIS)
- #include <sys/isa_defs.h>
- #ifdef _LITTLE_ENDIAN
- #define PLATFORM_IS_LITTLE_ENDIAN true
- #else
- #define PLATFORM_IS_LITTLE_ENDIAN false
- #endif
-#elif defined(OS_FREEBSD) || defined(OS_OPENBSD) ||\
- defined(OS_NETBSD) || defined(OS_DRAGONFLYBSD)
- #include <sys/types.h>
- #include <sys/endian.h>
- #define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
-#elif defined(OS_HPUX)
- #define PLATFORM_IS_LITTLE_ENDIAN false
-#elif defined(OS_ANDROID)
- // Due to a bug in the NDK x86 <sys/endian.h> definition,
- // _BYTE_ORDER must be used instead of __BYTE_ORDER on Android.
- // See http://code.google.com/p/android/issues/detail?id=39824
- #include <endian.h>
- #define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
-#else
- #include <endian.h>
-#endif
-
-#include <pthread.h>
-#ifdef SNAPPY
-#include <snappy.h>
-#endif
-#include <stdint.h>
-#include <string>
-#include "port/atomic_pointer.h"
-
-#ifndef PLATFORM_IS_LITTLE_ENDIAN
-#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
-#endif
-
-#if defined(OS_MACOSX) || defined(OS_SOLARIS) || defined(OS_FREEBSD) ||\
- defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) ||\
- defined(OS_ANDROID) || defined(OS_HPUX) || defined(CYGWIN)
-// Use fread/fwrite/fflush on platforms without _unlocked variants
-#define fread_unlocked fread
-#define fwrite_unlocked fwrite
-#define fflush_unlocked fflush
-#endif
-
-#if defined(OS_FREEBSD) ||\
- defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD)
-// Use fsync() on platforms without fdatasync()
-#define fdatasync fsync
-#endif
-
-#if defined(OS_MACOSX)
-#define fdatasync(fd) fcntl(fd, F_FULLFSYNC, 0)
-#endif
-
-#if defined(OS_ANDROID) && __ANDROID_API__ < 9
-// fdatasync() was only introduced in API level 9 on Android. Use fsync()
-// when targetting older platforms.
-#define fdatasync fsync
-#endif
-
-namespace leveldb {
-namespace port {
-
-static const bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN;
-#undef PLATFORM_IS_LITTLE_ENDIAN
-
-class CondVar;
-
-class Mutex {
- public:
- Mutex();
- ~Mutex();
-
- void Lock();
- void Unlock();
- void AssertHeld() { }
-
- private:
- friend class CondVar;
- pthread_mutex_t mu_;
-
- // No copying
- Mutex(const Mutex&);
- void operator=(const Mutex&);
-};
-
-class CondVar {
- public:
- explicit CondVar(Mutex* mu);
- ~CondVar();
- void Wait();
- void Signal();
- void SignalAll();
- private:
- pthread_cond_t cv_;
- Mutex* mu_;
-};
-
-typedef pthread_once_t OnceType;
-#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT
-extern void InitOnce(OnceType* once, void (*initializer)());
-
-inline bool Snappy_Compress(const char* input, size_t length,
- ::std::string* output) {
-#ifdef SNAPPY
- output->resize(snappy::MaxCompressedLength(length));
- size_t outlen;
- snappy::RawCompress(input, length, &(*output)[0], &outlen);
- output->resize(outlen);
- return true;
-#endif
-
- return false;
-}
-
-inline bool Snappy_GetUncompressedLength(const char* input, size_t length,
- size_t* result) {
-#ifdef SNAPPY
- return snappy::GetUncompressedLength(input, length, result);
-#else
- return false;
-#endif
-}
-
-inline bool Snappy_Uncompress(const char* input, size_t length,
- char* output) {
-#ifdef SNAPPY
- return snappy::RawUncompress(input, length, output);
-#else
- return false;
-#endif
-}
-
-inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
- return false;
-}
-
-bool HasAcceleratedCRC32C();
-uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size);
-
-} // namespace port
-} // namespace leveldb
-
-#endif // STORAGE_LEVELDB_PORT_PORT_POSIX_H_
diff --git a/src/leveldb/port/port_posix_sse.cc b/src/leveldb/port/port_posix_sse.cc
deleted file mode 100644
index 2d49c21dd8..0000000000
--- a/src/leveldb/port/port_posix_sse.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2016 The LevelDB Authors. All rights reserved.
-// 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.
-//
-// A portable implementation of crc32c, optimized to handle
-// four bytes at a time.
-//
-// In a separate source file to allow this accelerated CRC32C function to be
-// compiled with the appropriate compiler flags to enable x86 SSE 4.2
-// instructions.
-
-#include <stdint.h>
-#include <string.h>
-#include "port/port.h"
-
-#if defined(LEVELDB_PLATFORM_POSIX_SSE)
-
-#if defined(_MSC_VER)
-#include <intrin.h>
-#elif defined(__GNUC__) && defined(__SSE4_2__)
-#include <nmmintrin.h>
-#endif
-
-#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
-
-namespace leveldb {
-namespace port {
-
-#if defined(LEVELDB_PLATFORM_POSIX_SSE)
-
-// Used to fetch a naturally-aligned 32-bit word in little endian byte-order
-static inline uint32_t LE_LOAD32(const uint8_t *p) {
- // SSE is x86 only, so ensured that |p| is always little-endian.
- uint32_t word;
- memcpy(&word, p, sizeof(word));
- return word;
-}
-
-#if defined(_M_X64) || defined(__x86_64__) // LE_LOAD64 is only used on x64.
-
-// Used to fetch a naturally-aligned 64-bit word in little endian byte-order
-static inline uint64_t LE_LOAD64(const uint8_t *p) {
- uint64_t dword;
- memcpy(&dword, p, sizeof(dword));
- return dword;
-}
-
-#endif // defined(_M_X64) || defined(__x86_64__)
-
-#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
-
-// For further improvements see Intel publication at:
-// http://download.intel.com/design/intarch/papers/323405.pdf
-uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) {
-#if !defined(LEVELDB_PLATFORM_POSIX_SSE)
- return 0;
-#else
-
- const uint8_t *p = reinterpret_cast<const uint8_t *>(buf);
- const uint8_t *e = p + size;
- uint32_t l = crc ^ 0xffffffffu;
-
-#define STEP1 do { \
- l = _mm_crc32_u8(l, *p++); \
-} while (0)
-#define STEP4 do { \
- l = _mm_crc32_u32(l, LE_LOAD32(p)); \
- p += 4; \
-} while (0)
-#define STEP8 do { \
- l = _mm_crc32_u64(l, LE_LOAD64(p)); \
- p += 8; \
-} while (0)
-
- if (size > 16) {
- // Process unaligned bytes
- for (unsigned int i = reinterpret_cast<uintptr_t>(p) % 8; i; --i) {
- STEP1;
- }
-
- // _mm_crc32_u64 is only available on x64.
-#if defined(_M_X64) || defined(__x86_64__)
- // Process 8 bytes at a time
- while ((e-p) >= 8) {
- STEP8;
- }
- // Process 4 bytes at a time
- if ((e-p) >= 4) {
- STEP4;
- }
-#else // !(defined(_M_X64) || defined(__x86_64__))
- // Process 4 bytes at a time
- while ((e-p) >= 4) {
- STEP4;
- }
-#endif // defined(_M_X64) || defined(__x86_64__)
- }
- // Process the last few bytes
- while (p != e) {
- STEP1;
- }
-#undef STEP8
-#undef STEP4
-#undef STEP1
- return l ^ 0xffffffffu;
-#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
-}
-
-} // namespace port
-} // namespace leveldb
diff --git a/src/leveldb/port/port_stdcxx.h b/src/leveldb/port/port_stdcxx.h
new file mode 100644
index 0000000000..e9cb0e53af
--- /dev/null
+++ b/src/leveldb/port/port_stdcxx.h
@@ -0,0 +1,153 @@
+// Copyright (c) 2018 The LevelDB Authors. All rights reserved.
+// 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.
+
+#ifndef STORAGE_LEVELDB_PORT_PORT_STDCXX_H_
+#define STORAGE_LEVELDB_PORT_PORT_STDCXX_H_
+
+// port/port_config.h availability is automatically detected via __has_include
+// in newer compilers. If LEVELDB_HAS_PORT_CONFIG_H is defined, it overrides the
+// configuration detection.
+#if defined(LEVELDB_HAS_PORT_CONFIG_H)
+
+#if LEVELDB_HAS_PORT_CONFIG_H
+#include "port/port_config.h"
+#endif // LEVELDB_HAS_PORT_CONFIG_H
+
+#elif defined(__has_include)
+
+#if __has_include("port/port_config.h")
+#include "port/port_config.h"
+#endif // __has_include("port/port_config.h")
+
+#endif // defined(LEVELDB_HAS_PORT_CONFIG_H)
+
+#if HAVE_CRC32C
+#include <crc32c/crc32c.h>
+#endif // HAVE_CRC32C
+#if HAVE_SNAPPY
+#include <snappy.h>
+#endif // HAVE_SNAPPY
+
+#include <cassert>
+#include <condition_variable> // NOLINT
+#include <cstddef>
+#include <cstdint>
+#include <mutex> // NOLINT
+#include <string>
+
+#include "port/thread_annotations.h"
+
+namespace leveldb {
+namespace port {
+
+static const bool kLittleEndian = !LEVELDB_IS_BIG_ENDIAN;
+
+class CondVar;
+
+// Thinly wraps std::mutex.
+class LOCKABLE Mutex {
+ public:
+ Mutex() = default;
+ ~Mutex() = default;
+
+ Mutex(const Mutex&) = delete;
+ Mutex& operator=(const Mutex&) = delete;
+
+ void Lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.lock(); }
+ void Unlock() UNLOCK_FUNCTION() { mu_.unlock(); }
+ void AssertHeld() ASSERT_EXCLUSIVE_LOCK() {}
+
+ private:
+ friend class CondVar;
+ std::mutex mu_;
+};
+
+// Thinly wraps std::condition_variable.
+class CondVar {
+ public:
+ explicit CondVar(Mutex* mu) : mu_(mu) { assert(mu != nullptr); }
+ ~CondVar() = default;
+
+ CondVar(const CondVar&) = delete;
+ CondVar& operator=(const CondVar&) = delete;
+
+ void Wait() {
+ std::unique_lock<std::mutex> lock(mu_->mu_, std::adopt_lock);
+ cv_.wait(lock);
+ lock.release();
+ }
+ void Signal() { cv_.notify_one(); }
+ void SignalAll() { cv_.notify_all(); }
+
+ private:
+ std::condition_variable cv_;
+ Mutex* const mu_;
+};
+
+inline bool Snappy_Compress(const char* input, size_t length,
+ std::string* output) {
+#if HAVE_SNAPPY
+ output->resize(snappy::MaxCompressedLength(length));
+ size_t outlen;
+ snappy::RawCompress(input, length, &(*output)[0], &outlen);
+ output->resize(outlen);
+ return true;
+#else
+ // Silence compiler warnings about unused arguments.
+ (void)input;
+ (void)length;
+ (void)output;
+#endif // HAVE_SNAPPY
+
+ return false;
+}
+
+inline bool Snappy_GetUncompressedLength(const char* input, size_t length,
+ size_t* result) {
+#if HAVE_SNAPPY
+ return snappy::GetUncompressedLength(input, length, result);
+#else
+ // Silence compiler warnings about unused arguments.
+ (void)input;
+ (void)length;
+ (void)result;
+ return false;
+#endif // HAVE_SNAPPY
+}
+
+inline bool Snappy_Uncompress(const char* input, size_t length, char* output) {
+#if HAVE_SNAPPY
+ return snappy::RawUncompress(input, length, output);
+#else
+ // Silence compiler warnings about unused arguments.
+ (void)input;
+ (void)length;
+ (void)output;
+ return false;
+#endif // HAVE_SNAPPY
+}
+
+inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
+ // Silence compiler warnings about unused arguments.
+ (void)func;
+ (void)arg;
+ return false;
+}
+
+inline uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) {
+#if HAVE_CRC32C
+ return ::crc32c::Extend(crc, reinterpret_cast<const uint8_t*>(buf), size);
+#else
+ // Silence compiler warnings about unused arguments.
+ (void)crc;
+ (void)buf;
+ (void)size;
+ return 0;
+#endif // HAVE_CRC32C
+}
+
+} // namespace port
+} // namespace leveldb
+
+#endif // STORAGE_LEVELDB_PORT_PORT_STDCXX_H_
diff --git a/src/leveldb/port/port_win.cc b/src/leveldb/port/port_win.cc
deleted file mode 100644
index 1be9e8d5b0..0000000000
--- a/src/leveldb/port/port_win.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-// LevelDB Copyright (c) 2011 The LevelDB Authors. All rights reserved.
-// 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.
-//
-// See port_example.h for documentation for the following types/functions.
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the University of California, Berkeley nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
-// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#include "port/port_win.h"
-
-#include <windows.h>
-#include <cassert>
-#include <intrin.h>
-
-namespace leveldb {
-namespace port {
-
-Mutex::Mutex() :
- cs_(NULL) {
- assert(!cs_);
- cs_ = static_cast<void *>(new CRITICAL_SECTION());
- ::InitializeCriticalSection(static_cast<CRITICAL_SECTION *>(cs_));
- assert(cs_);
-}
-
-Mutex::~Mutex() {
- assert(cs_);
- ::DeleteCriticalSection(static_cast<CRITICAL_SECTION *>(cs_));
- delete static_cast<CRITICAL_SECTION *>(cs_);
- cs_ = NULL;
- assert(!cs_);
-}
-
-void Mutex::Lock() {
- assert(cs_);
- ::EnterCriticalSection(static_cast<CRITICAL_SECTION *>(cs_));
-}
-
-void Mutex::Unlock() {
- assert(cs_);
- ::LeaveCriticalSection(static_cast<CRITICAL_SECTION *>(cs_));
-}
-
-void Mutex::AssertHeld() {
- assert(cs_);
- assert(1);
-}
-
-CondVar::CondVar(Mutex* mu) :
- waiting_(0),
- mu_(mu),
- sem1_(::CreateSemaphore(NULL, 0, 10000, NULL)),
- sem2_(::CreateSemaphore(NULL, 0, 10000, NULL)) {
- assert(mu_);
-}
-
-CondVar::~CondVar() {
- ::CloseHandle(sem1_);
- ::CloseHandle(sem2_);
-}
-
-void CondVar::Wait() {
- mu_->AssertHeld();
-
- wait_mtx_.Lock();
- ++waiting_;
- wait_mtx_.Unlock();
-
- mu_->Unlock();
-
- // initiate handshake
- ::WaitForSingleObject(sem1_, INFINITE);
- ::ReleaseSemaphore(sem2_, 1, NULL);
- mu_->Lock();
-}
-
-void CondVar::Signal() {
- wait_mtx_.Lock();
- if (waiting_ > 0) {
- --waiting_;
-
- // finalize handshake
- ::ReleaseSemaphore(sem1_, 1, NULL);
- ::WaitForSingleObject(sem2_, INFINITE);
- }
- wait_mtx_.Unlock();
-}
-
-void CondVar::SignalAll() {
- wait_mtx_.Lock();
- ::ReleaseSemaphore(sem1_, waiting_, NULL);
- while(waiting_ > 0) {
- --waiting_;
- ::WaitForSingleObject(sem2_, INFINITE);
- }
- wait_mtx_.Unlock();
-}
-
-AtomicPointer::AtomicPointer(void* v) {
- Release_Store(v);
-}
-
-void InitOnce(OnceType* once, void (*initializer)()) {
- once->InitOnce(initializer);
-}
-
-void* AtomicPointer::Acquire_Load() const {
- void * p = NULL;
- InterlockedExchangePointer(&p, rep_);
- return p;
-}
-
-void AtomicPointer::Release_Store(void* v) {
- InterlockedExchangePointer(&rep_, v);
-}
-
-void* AtomicPointer::NoBarrier_Load() const {
- return rep_;
-}
-
-void AtomicPointer::NoBarrier_Store(void* v) {
- rep_ = v;
-}
-
-bool HasAcceleratedCRC32C() {
-#if defined(__x86_64__) || defined(__i386__)
- int cpu_info[4];
- __cpuid(cpu_info, 1);
- return (cpu_info[2] & (1 << 20)) != 0;
-#else
- return false;
-#endif
-}
-
-}
-}
diff --git a/src/leveldb/port/port_win.h b/src/leveldb/port/port_win.h
deleted file mode 100644
index 989c15cd91..0000000000
--- a/src/leveldb/port/port_win.h
+++ /dev/null
@@ -1,184 +0,0 @@
-// LevelDB Copyright (c) 2011 The LevelDB Authors. All rights reserved.
-// 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.
-//
-// See port_example.h for documentation for the following types/functions.
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the University of California, Berkeley nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
-// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#ifndef STORAGE_LEVELDB_PORT_PORT_WIN_H_
-#define STORAGE_LEVELDB_PORT_PORT_WIN_H_
-
-#ifdef _MSC_VER
-#if !(_MSC_VER >= 1900)
-#define snprintf _snprintf
-#endif
-#define close _close
-#define fread_unlocked _fread_nolock
-#ifdef _WIN64
-#define ssize_t int64_t
-#else
-#define ssize_t int32_t
-#endif
-#endif
-
-#include <string>
-#include <stdint.h>
-#ifdef SNAPPY
-#include <snappy.h>
-#endif
-
-namespace leveldb {
-namespace port {
-
-// Windows is little endian (for now :p)
-static const bool kLittleEndian = true;
-
-class CondVar;
-
-class Mutex {
- public:
- Mutex();
- ~Mutex();
-
- void Lock();
- void Unlock();
- void AssertHeld();
-
- private:
- friend class CondVar;
- // critical sections are more efficient than mutexes
- // but they are not recursive and can only be used to synchronize threads within the same process
- // we use opaque void * to avoid including windows.h in port_win.h
- void * cs_;
-
- // No copying
- Mutex(const Mutex&);
- void operator=(const Mutex&);
-};
-
-// the Win32 API offers a dependable condition variable mechanism, but only starting with
-// Windows 2008 and Vista
-// no matter what we will implement our own condition variable with a semaphore
-// implementation as described in a paper written by Andrew D. Birrell in 2003
-class CondVar {
- public:
- explicit CondVar(Mutex* mu);
- ~CondVar();
- void Wait();
- void Signal();
- void SignalAll();
- private:
- Mutex* mu_;
-
- Mutex wait_mtx_;
- long waiting_;
-
- void * sem1_;
- void * sem2_;
-
-
-};
-
-class OnceType {
-public:
-// OnceType() : init_(false) {}
- OnceType(const OnceType &once) : init_(once.init_) {}
- OnceType(bool f) : init_(f) {}
- void InitOnce(void (*initializer)()) {
- mutex_.Lock();
- if (!init_) {
- init_ = true;
- initializer();
- }
- mutex_.Unlock();
- }
-
-private:
- bool init_;
- Mutex mutex_;
-};
-
-#define LEVELDB_ONCE_INIT false
-extern void InitOnce(port::OnceType*, void (*initializer)());
-
-// Storage for a lock-free pointer
-class AtomicPointer {
- private:
- void * rep_;
- public:
- AtomicPointer() : rep_(NULL) { }
- explicit AtomicPointer(void* v);
- void* Acquire_Load() const;
-
- void Release_Store(void* v);
-
- void* NoBarrier_Load() const;
-
- void NoBarrier_Store(void* v);
-};
-
-inline bool Snappy_Compress(const char* input, size_t length,
- ::std::string* output) {
-#ifdef SNAPPY
- output->resize(snappy::MaxCompressedLength(length));
- size_t outlen;
- snappy::RawCompress(input, length, &(*output)[0], &outlen);
- output->resize(outlen);
- return true;
-#endif
-
- return false;
-}
-
-inline bool Snappy_GetUncompressedLength(const char* input, size_t length,
- size_t* result) {
-#ifdef SNAPPY
- return snappy::GetUncompressedLength(input, length, result);
-#else
- return false;
-#endif
-}
-
-inline bool Snappy_Uncompress(const char* input, size_t length,
- char* output) {
-#ifdef SNAPPY
- return snappy::RawUncompress(input, length, output);
-#else
- return false;
-#endif
-}
-
-inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
- return false;
-}
-
-bool HasAcceleratedCRC32C();
-uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size);
-
-}
-}
-
-#endif // STORAGE_LEVELDB_PORT_PORT_WIN_H_
diff --git a/src/leveldb/port/thread_annotations.h b/src/leveldb/port/thread_annotations.h
index 9470ef587c..1547df908f 100644
--- a/src/leveldb/port/thread_annotations.h
+++ b/src/leveldb/port/thread_annotations.h
@@ -5,56 +5,104 @@
#ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_
#define STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_
-// Some environments provide custom macros to aid in static thread-safety
-// analysis. Provide empty definitions of such macros unless they are already
-// defined.
+// Use Clang's thread safety analysis annotations when available. In other
+// environments, the macros receive empty definitions.
+// Usage documentation: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
+
+#if !defined(THREAD_ANNOTATION_ATTRIBUTE__)
+
+#if defined(__clang__)
+
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
+#else
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
+#endif
+
+#endif // !defined(THREAD_ANNOTATION_ATTRIBUTE__)
+
+#ifndef GUARDED_BY
+#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
+#endif
+
+#ifndef PT_GUARDED_BY
+#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
+#endif
+
+#ifndef ACQUIRED_AFTER
+#define ACQUIRED_AFTER(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+#endif
+
+#ifndef ACQUIRED_BEFORE
+#define ACQUIRED_BEFORE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
+#endif
#ifndef EXCLUSIVE_LOCKS_REQUIRED
-#define EXCLUSIVE_LOCKS_REQUIRED(...)
+#define EXCLUSIVE_LOCKS_REQUIRED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
#endif
#ifndef SHARED_LOCKS_REQUIRED
-#define SHARED_LOCKS_REQUIRED(...)
+#define SHARED_LOCKS_REQUIRED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
#endif
#ifndef LOCKS_EXCLUDED
-#define LOCKS_EXCLUDED(...)
+#define LOCKS_EXCLUDED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
#endif
#ifndef LOCK_RETURNED
-#define LOCK_RETURNED(x)
+#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
#endif
#ifndef LOCKABLE
-#define LOCKABLE
+#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable)
#endif
#ifndef SCOPED_LOCKABLE
-#define SCOPED_LOCKABLE
+#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
#endif
#ifndef EXCLUSIVE_LOCK_FUNCTION
-#define EXCLUSIVE_LOCK_FUNCTION(...)
+#define EXCLUSIVE_LOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
#endif
#ifndef SHARED_LOCK_FUNCTION
-#define SHARED_LOCK_FUNCTION(...)
+#define SHARED_LOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
#endif
#ifndef EXCLUSIVE_TRYLOCK_FUNCTION
-#define EXCLUSIVE_TRYLOCK_FUNCTION(...)
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
#endif
#ifndef SHARED_TRYLOCK_FUNCTION
-#define SHARED_TRYLOCK_FUNCTION(...)
+#define SHARED_TRYLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
#endif
#ifndef UNLOCK_FUNCTION
-#define UNLOCK_FUNCTION(...)
+#define UNLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
#endif
#ifndef NO_THREAD_SAFETY_ANALYSIS
-#define NO_THREAD_SAFETY_ANALYSIS
+#define NO_THREAD_SAFETY_ANALYSIS \
+ THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
+#endif
+
+#ifndef ASSERT_EXCLUSIVE_LOCK
+#define ASSERT_EXCLUSIVE_LOCK(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
+#endif
+
+#ifndef ASSERT_SHARED_LOCK
+#define ASSERT_SHARED_LOCK(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
#endif
#endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_
diff --git a/src/leveldb/port/win/stdint.h b/src/leveldb/port/win/stdint.h
deleted file mode 100644
index 39edd0db13..0000000000
--- a/src/leveldb/port/win/stdint.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
-// 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.
-
-// MSVC didn't ship with this file until the 2010 version.
-
-#ifndef STORAGE_LEVELDB_PORT_WIN_STDINT_H_
-#define STORAGE_LEVELDB_PORT_WIN_STDINT_H_
-
-#if !defined(_MSC_VER)
-#error This file should only be included when compiling with MSVC.
-#endif
-
-// Define C99 equivalent types.
-typedef signed char int8_t;
-typedef signed short int16_t;
-typedef signed int int32_t;
-typedef signed long long int64_t;
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long uint64_t;
-
-#endif // STORAGE_LEVELDB_PORT_WIN_STDINT_H_
diff --git a/src/leveldb/table/block.cc b/src/leveldb/table/block.cc
index 43e402c9c0..2fe89eaa45 100644
--- a/src/leveldb/table/block.cc
+++ b/src/leveldb/table/block.cc
@@ -6,8 +6,10 @@
#include "table/block.h"
-#include <vector>
#include <algorithm>
+#include <cstdint>
+#include <vector>
+
#include "leveldb/comparator.h"
#include "table/format.h"
#include "util/coding.h"
@@ -27,7 +29,7 @@ Block::Block(const BlockContents& contents)
if (size_ < sizeof(uint32_t)) {
size_ = 0; // Error marker
} else {
- size_t max_restarts_allowed = (size_-sizeof(uint32_t)) / sizeof(uint32_t);
+ size_t max_restarts_allowed = (size_ - sizeof(uint32_t)) / sizeof(uint32_t);
if (NumRestarts() > max_restarts_allowed) {
// The size is too small for NumRestarts()
size_ = 0;
@@ -48,27 +50,26 @@ Block::~Block() {
// and the length of the value in "*shared", "*non_shared", and
// "*value_length", respectively. Will not dereference past "limit".
//
-// If any errors are detected, returns NULL. Otherwise, returns a
+// If any errors are detected, returns nullptr. Otherwise, returns a
// pointer to the key delta (just past the three decoded values).
static inline const char* DecodeEntry(const char* p, const char* limit,
- uint32_t* shared,
- uint32_t* non_shared,
+ uint32_t* shared, uint32_t* non_shared,
uint32_t* value_length) {
- if (limit - p < 3) return NULL;
- *shared = reinterpret_cast<const unsigned char*>(p)[0];
- *non_shared = reinterpret_cast<const unsigned char*>(p)[1];
- *value_length = reinterpret_cast<const unsigned char*>(p)[2];
+ if (limit - p < 3) return nullptr;
+ *shared = reinterpret_cast<const uint8_t*>(p)[0];
+ *non_shared = reinterpret_cast<const uint8_t*>(p)[1];
+ *value_length = reinterpret_cast<const uint8_t*>(p)[2];
if ((*shared | *non_shared | *value_length) < 128) {
// Fast path: all three values are encoded in one byte each
p += 3;
} else {
- if ((p = GetVarint32Ptr(p, limit, shared)) == NULL) return NULL;
- if ((p = GetVarint32Ptr(p, limit, non_shared)) == NULL) return NULL;
- if ((p = GetVarint32Ptr(p, limit, value_length)) == NULL) return NULL;
+ if ((p = GetVarint32Ptr(p, limit, shared)) == nullptr) return nullptr;
+ if ((p = GetVarint32Ptr(p, limit, non_shared)) == nullptr) return nullptr;
+ if ((p = GetVarint32Ptr(p, limit, value_length)) == nullptr) return nullptr;
}
if (static_cast<uint32_t>(limit - p) < (*non_shared + *value_length)) {
- return NULL;
+ return nullptr;
}
return p;
}
@@ -76,9 +77,9 @@ static inline const char* DecodeEntry(const char* p, const char* limit,
class Block::Iter : public Iterator {
private:
const Comparator* const comparator_;
- const char* const data_; // underlying block contents
- uint32_t const restarts_; // Offset of restart array (list of fixed32)
- uint32_t const num_restarts_; // Number of uint32_t entries in restart array
+ const char* const data_; // underlying block contents
+ uint32_t const restarts_; // Offset of restart array (list of fixed32)
+ uint32_t const num_restarts_; // Number of uint32_t entries in restart array
// current_ is offset in data_ of current entry. >= restarts_ if !Valid
uint32_t current_;
@@ -112,9 +113,7 @@ class Block::Iter : public Iterator {
}
public:
- Iter(const Comparator* comparator,
- const char* data,
- uint32_t restarts,
+ Iter(const Comparator* comparator, const char* data, uint32_t restarts,
uint32_t num_restarts)
: comparator_(comparator),
data_(data),
@@ -125,23 +124,23 @@ class Block::Iter : public Iterator {
assert(num_restarts_ > 0);
}
- virtual bool Valid() const { return current_ < restarts_; }
- virtual Status status() const { return status_; }
- virtual Slice key() const {
+ bool Valid() const override { return current_ < restarts_; }
+ Status status() const override { return status_; }
+ Slice key() const override {
assert(Valid());
return key_;
}
- virtual Slice value() const {
+ Slice value() const override {
assert(Valid());
return value_;
}
- virtual void Next() {
+ void Next() override {
assert(Valid());
ParseNextKey();
}
- virtual void Prev() {
+ void Prev() override {
assert(Valid());
// Scan backwards to a restart point before current_
@@ -162,7 +161,7 @@ class Block::Iter : public Iterator {
} while (ParseNextKey() && NextEntryOffset() < original);
}
- virtual void Seek(const Slice& target) {
+ void Seek(const Slice& target) override {
// Binary search in restart array to find the last restart point
// with a key < target
uint32_t left = 0;
@@ -171,10 +170,10 @@ class Block::Iter : public Iterator {
uint32_t mid = (left + right + 1) / 2;
uint32_t region_offset = GetRestartPoint(mid);
uint32_t shared, non_shared, value_length;
- const char* key_ptr = DecodeEntry(data_ + region_offset,
- data_ + restarts_,
- &shared, &non_shared, &value_length);
- if (key_ptr == NULL || (shared != 0)) {
+ const char* key_ptr =
+ DecodeEntry(data_ + region_offset, data_ + restarts_, &shared,
+ &non_shared, &value_length);
+ if (key_ptr == nullptr || (shared != 0)) {
CorruptionError();
return;
}
@@ -202,12 +201,12 @@ class Block::Iter : public Iterator {
}
}
- virtual void SeekToFirst() {
+ void SeekToFirst() override {
SeekToRestartPoint(0);
ParseNextKey();
}
- virtual void SeekToLast() {
+ void SeekToLast() override {
SeekToRestartPoint(num_restarts_ - 1);
while (ParseNextKey() && NextEntryOffset() < restarts_) {
// Keep skipping
@@ -237,7 +236,7 @@ class Block::Iter : public Iterator {
// Decode next entry
uint32_t shared, non_shared, value_length;
p = DecodeEntry(p, limit, &shared, &non_shared, &value_length);
- if (p == NULL || key_.size() < shared) {
+ if (p == nullptr || key_.size() < shared) {
CorruptionError();
return false;
} else {
@@ -253,7 +252,7 @@ class Block::Iter : public Iterator {
}
};
-Iterator* Block::NewIterator(const Comparator* cmp) {
+Iterator* Block::NewIterator(const Comparator* comparator) {
if (size_ < sizeof(uint32_t)) {
return NewErrorIterator(Status::Corruption("bad block contents"));
}
@@ -261,7 +260,7 @@ Iterator* Block::NewIterator(const Comparator* cmp) {
if (num_restarts == 0) {
return NewEmptyIterator();
} else {
- return new Iter(cmp, data_, restart_offset_, num_restarts);
+ return new Iter(comparator, data_, restart_offset_, num_restarts);
}
}
diff --git a/src/leveldb/table/block.h b/src/leveldb/table/block.h
index 2493eb9f9f..c8f1f7b436 100644
--- a/src/leveldb/table/block.h
+++ b/src/leveldb/table/block.h
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
+
#include "leveldb/iterator.h"
namespace leveldb {
@@ -19,24 +20,23 @@ class Block {
// Initialize the block with the specified contents.
explicit Block(const BlockContents& contents);
+ Block(const Block&) = delete;
+ Block& operator=(const Block&) = delete;
+
~Block();
size_t size() const { return size_; }
Iterator* NewIterator(const Comparator* comparator);
private:
+ class Iter;
+
uint32_t NumRestarts() const;
const char* data_;
size_t size_;
- uint32_t restart_offset_; // Offset in data_ of restart array
- bool owned_; // Block owns data_[]
-
- // No copying allowed
- Block(const Block&);
- void operator=(const Block&);
-
- class Iter;
+ uint32_t restart_offset_; // Offset in data_ of restart array
+ bool owned_; // Block owns data_[]
};
} // namespace leveldb
diff --git a/src/leveldb/table/block_builder.cc b/src/leveldb/table/block_builder.cc
index db660cd07c..919cff5c93 100644
--- a/src/leveldb/table/block_builder.cc
+++ b/src/leveldb/table/block_builder.cc
@@ -28,36 +28,35 @@
#include "table/block_builder.h"
-#include <algorithm>
#include <assert.h>
+
+#include <algorithm>
+
#include "leveldb/comparator.h"
-#include "leveldb/table_builder.h"
+#include "leveldb/options.h"
#include "util/coding.h"
namespace leveldb {
BlockBuilder::BlockBuilder(const Options* options)
- : options_(options),
- restarts_(),
- counter_(0),
- finished_(false) {
+ : options_(options), restarts_(), counter_(0), finished_(false) {
assert(options->block_restart_interval >= 1);
- restarts_.push_back(0); // First restart point is at offset 0
+ restarts_.push_back(0); // First restart point is at offset 0
}
void BlockBuilder::Reset() {
buffer_.clear();
restarts_.clear();
- restarts_.push_back(0); // First restart point is at offset 0
+ restarts_.push_back(0); // First restart point is at offset 0
counter_ = 0;
finished_ = false;
last_key_.clear();
}
size_t BlockBuilder::CurrentSizeEstimate() const {
- return (buffer_.size() + // Raw data buffer
- restarts_.size() * sizeof(uint32_t) + // Restart array
- sizeof(uint32_t)); // Restart array length
+ return (buffer_.size() + // Raw data buffer
+ restarts_.size() * sizeof(uint32_t) + // Restart array
+ sizeof(uint32_t)); // Restart array length
}
Slice BlockBuilder::Finish() {
@@ -74,7 +73,7 @@ void BlockBuilder::Add(const Slice& key, const Slice& value) {
Slice last_key_piece(last_key_);
assert(!finished_);
assert(counter_ <= options_->block_restart_interval);
- assert(buffer_.empty() // No values yet?
+ assert(buffer_.empty() // No values yet?
|| options_->comparator->Compare(key, last_key_piece) > 0);
size_t shared = 0;
if (counter_ < options_->block_restart_interval) {
diff --git a/src/leveldb/table/block_builder.h b/src/leveldb/table/block_builder.h
index 4fbcb33972..f91f5e6d47 100644
--- a/src/leveldb/table/block_builder.h
+++ b/src/leveldb/table/block_builder.h
@@ -5,9 +5,10 @@
#ifndef STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
#define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
+#include <stdint.h>
+
#include <vector>
-#include <stdint.h>
#include "leveldb/slice.h"
namespace leveldb {
@@ -18,6 +19,9 @@ class BlockBuilder {
public:
explicit BlockBuilder(const Options* options);
+ BlockBuilder(const BlockBuilder&) = delete;
+ BlockBuilder& operator=(const BlockBuilder&) = delete;
+
// Reset the contents as if the BlockBuilder was just constructed.
void Reset();
@@ -35,21 +39,15 @@ class BlockBuilder {
size_t CurrentSizeEstimate() const;
// Return true iff no entries have been added since the last Reset()
- bool empty() const {
- return buffer_.empty();
- }
+ bool empty() const { return buffer_.empty(); }
private:
- const Options* options_;
- std::string buffer_; // Destination buffer
- std::vector<uint32_t> restarts_; // Restart points
- int counter_; // Number of entries emitted since restart
- bool finished_; // Has Finish() been called?
- std::string last_key_;
-
- // No copying allowed
- BlockBuilder(const BlockBuilder&);
- void operator=(const BlockBuilder&);
+ const Options* options_;
+ std::string buffer_; // Destination buffer
+ std::vector<uint32_t> restarts_; // Restart points
+ int counter_; // Number of entries emitted since restart
+ bool finished_; // Has Finish() been called?
+ std::string last_key_;
};
} // namespace leveldb
diff --git a/src/leveldb/table/filter_block.cc b/src/leveldb/table/filter_block.cc
index 1ed5134170..09ec0094bd 100644
--- a/src/leveldb/table/filter_block.cc
+++ b/src/leveldb/table/filter_block.cc
@@ -16,8 +16,7 @@ static const size_t kFilterBaseLg = 11;
static const size_t kFilterBase = 1 << kFilterBaseLg;
FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy)
- : policy_(policy) {
-}
+ : policy_(policy) {}
void FilterBlockBuilder::StartBlock(uint64_t block_offset) {
uint64_t filter_index = (block_offset / kFilterBase);
@@ -62,7 +61,7 @@ void FilterBlockBuilder::GenerateFilter() {
tmp_keys_.resize(num_keys);
for (size_t i = 0; i < num_keys; i++) {
const char* base = keys_.data() + start_[i];
- size_t length = start_[i+1] - start_[i];
+ size_t length = start_[i + 1] - start_[i];
tmp_keys_[i] = Slice(base, length);
}
@@ -77,14 +76,10 @@ void FilterBlockBuilder::GenerateFilter() {
FilterBlockReader::FilterBlockReader(const FilterPolicy* policy,
const Slice& contents)
- : policy_(policy),
- data_(NULL),
- offset_(NULL),
- num_(0),
- base_lg_(0) {
+ : policy_(policy), data_(nullptr), offset_(nullptr), num_(0), base_lg_(0) {
size_t n = contents.size();
if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array
- base_lg_ = contents[n-1];
+ base_lg_ = contents[n - 1];
uint32_t last_word = DecodeFixed32(contents.data() + n - 5);
if (last_word > n - 5) return;
data_ = contents.data();
@@ -95,8 +90,8 @@ FilterBlockReader::FilterBlockReader(const FilterPolicy* policy,
bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) {
uint64_t index = block_offset >> base_lg_;
if (index < num_) {
- uint32_t start = DecodeFixed32(offset_ + index*4);
- uint32_t limit = DecodeFixed32(offset_ + index*4 + 4);
+ uint32_t start = DecodeFixed32(offset_ + index * 4);
+ uint32_t limit = DecodeFixed32(offset_ + index * 4 + 4);
if (start <= limit && limit <= static_cast<size_t>(offset_ - data_)) {
Slice filter = Slice(data_ + start, limit - start);
return policy_->KeyMayMatch(key, filter);
@@ -108,4 +103,4 @@ bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) {
return true; // Errors are treated as potential matches
}
-}
+} // namespace leveldb
diff --git a/src/leveldb/table/filter_block.h b/src/leveldb/table/filter_block.h
index c67d010bd1..73b5399249 100644
--- a/src/leveldb/table/filter_block.h
+++ b/src/leveldb/table/filter_block.h
@@ -11,8 +11,10 @@
#include <stddef.h>
#include <stdint.h>
+
#include <string>
#include <vector>
+
#include "leveldb/slice.h"
#include "util/hash.h"
@@ -30,6 +32,9 @@ class FilterBlockBuilder {
public:
explicit FilterBlockBuilder(const FilterPolicy*);
+ FilterBlockBuilder(const FilterBlockBuilder&) = delete;
+ FilterBlockBuilder& operator=(const FilterBlockBuilder&) = delete;
+
void StartBlock(uint64_t block_offset);
void AddKey(const Slice& key);
Slice Finish();
@@ -38,20 +43,16 @@ class FilterBlockBuilder {
void GenerateFilter();
const FilterPolicy* policy_;
- std::string keys_; // Flattened key contents
- std::vector<size_t> start_; // Starting index in keys_ of each key
- std::string result_; // Filter data computed so far
- std::vector<Slice> tmp_keys_; // policy_->CreateFilter() argument
+ std::string keys_; // Flattened key contents
+ std::vector<size_t> start_; // Starting index in keys_ of each key
+ std::string result_; // Filter data computed so far
+ std::vector<Slice> tmp_keys_; // policy_->CreateFilter() argument
std::vector<uint32_t> filter_offsets_;
-
- // No copying allowed
- FilterBlockBuilder(const FilterBlockBuilder&);
- void operator=(const FilterBlockBuilder&);
};
class FilterBlockReader {
public:
- // REQUIRES: "contents" and *policy must stay live while *this is live.
+ // REQUIRES: "contents" and *policy must stay live while *this is live.
FilterBlockReader(const FilterPolicy* policy, const Slice& contents);
bool KeyMayMatch(uint64_t block_offset, const Slice& key);
@@ -63,6 +64,6 @@ class FilterBlockReader {
size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file)
};
-}
+} // namespace leveldb
#endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_
diff --git a/src/leveldb/table/filter_block_test.cc b/src/leveldb/table/filter_block_test.cc
index 8c4a4741f2..8b33bbdd18 100644
--- a/src/leveldb/table/filter_block_test.cc
+++ b/src/leveldb/table/filter_block_test.cc
@@ -16,18 +16,16 @@ namespace leveldb {
// For testing: emit an array with one hash value per key
class TestHashFilter : public FilterPolicy {
public:
- virtual const char* Name() const {
- return "TestHashFilter";
- }
+ const char* Name() const override { return "TestHashFilter"; }
- virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
+ void CreateFilter(const Slice* keys, int n, std::string* dst) const override {
for (int i = 0; i < n; i++) {
uint32_t h = Hash(keys[i].data(), keys[i].size(), 1);
PutFixed32(dst, h);
}
}
- virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const {
+ bool KeyMayMatch(const Slice& key, const Slice& filter) const override {
uint32_t h = Hash(key.data(), key.size(), 1);
for (size_t i = 0; i + 4 <= filter.size(); i += 4) {
if (h == DecodeFixed32(filter.data() + i)) {
@@ -69,8 +67,8 @@ TEST(FilterBlockTest, SingleChunk) {
ASSERT_TRUE(reader.KeyMayMatch(100, "box"));
ASSERT_TRUE(reader.KeyMayMatch(100, "hello"));
ASSERT_TRUE(reader.KeyMayMatch(100, "foo"));
- ASSERT_TRUE(! reader.KeyMayMatch(100, "missing"));
- ASSERT_TRUE(! reader.KeyMayMatch(100, "other"));
+ ASSERT_TRUE(!reader.KeyMayMatch(100, "missing"));
+ ASSERT_TRUE(!reader.KeyMayMatch(100, "other"));
}
TEST(FilterBlockTest, MultiChunk) {
@@ -99,30 +97,28 @@ TEST(FilterBlockTest, MultiChunk) {
// Check first filter
ASSERT_TRUE(reader.KeyMayMatch(0, "foo"));
ASSERT_TRUE(reader.KeyMayMatch(2000, "bar"));
- ASSERT_TRUE(! reader.KeyMayMatch(0, "box"));
- ASSERT_TRUE(! reader.KeyMayMatch(0, "hello"));
+ ASSERT_TRUE(!reader.KeyMayMatch(0, "box"));
+ ASSERT_TRUE(!reader.KeyMayMatch(0, "hello"));
// Check second filter
ASSERT_TRUE(reader.KeyMayMatch(3100, "box"));
- ASSERT_TRUE(! reader.KeyMayMatch(3100, "foo"));
- ASSERT_TRUE(! reader.KeyMayMatch(3100, "bar"));
- ASSERT_TRUE(! reader.KeyMayMatch(3100, "hello"));
+ ASSERT_TRUE(!reader.KeyMayMatch(3100, "foo"));
+ ASSERT_TRUE(!reader.KeyMayMatch(3100, "bar"));
+ ASSERT_TRUE(!reader.KeyMayMatch(3100, "hello"));
// Check third filter (empty)
- ASSERT_TRUE(! reader.KeyMayMatch(4100, "foo"));
- ASSERT_TRUE(! reader.KeyMayMatch(4100, "bar"));
- ASSERT_TRUE(! reader.KeyMayMatch(4100, "box"));
- ASSERT_TRUE(! reader.KeyMayMatch(4100, "hello"));
+ ASSERT_TRUE(!reader.KeyMayMatch(4100, "foo"));
+ ASSERT_TRUE(!reader.KeyMayMatch(4100, "bar"));
+ ASSERT_TRUE(!reader.KeyMayMatch(4100, "box"));
+ ASSERT_TRUE(!reader.KeyMayMatch(4100, "hello"));
// Check last filter
ASSERT_TRUE(reader.KeyMayMatch(9000, "box"));
ASSERT_TRUE(reader.KeyMayMatch(9000, "hello"));
- ASSERT_TRUE(! reader.KeyMayMatch(9000, "foo"));
- ASSERT_TRUE(! reader.KeyMayMatch(9000, "bar"));
+ ASSERT_TRUE(!reader.KeyMayMatch(9000, "foo"));
+ ASSERT_TRUE(!reader.KeyMayMatch(9000, "bar"));
}
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/table/format.cc b/src/leveldb/table/format.cc
index 285e1c0de3..a3d67de2e4 100644
--- a/src/leveldb/table/format.cc
+++ b/src/leveldb/table/format.cc
@@ -21,8 +21,7 @@ void BlockHandle::EncodeTo(std::string* dst) const {
}
Status BlockHandle::DecodeFrom(Slice* input) {
- if (GetVarint64(input, &offset_) &&
- GetVarint64(input, &size_)) {
+ if (GetVarint64(input, &offset_) && GetVarint64(input, &size_)) {
return Status::OK();
} else {
return Status::Corruption("bad block handle");
@@ -62,10 +61,8 @@ Status Footer::DecodeFrom(Slice* input) {
return result;
}
-Status ReadBlock(RandomAccessFile* file,
- const ReadOptions& options,
- const BlockHandle& handle,
- BlockContents* result) {
+Status ReadBlock(RandomAccessFile* file, const ReadOptions& options,
+ const BlockHandle& handle, BlockContents* result) {
result->data = Slice();
result->cachable = false;
result->heap_allocated = false;
@@ -86,7 +83,7 @@ Status ReadBlock(RandomAccessFile* file,
}
// Check the crc of the type and the block contents
- const char* data = contents.data(); // Pointer to where Read put the data
+ const char* data = contents.data(); // Pointer to where Read put the data
if (options.verify_checksums) {
const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1));
const uint32_t actual = crc32c::Value(data, n + 1);
diff --git a/src/leveldb/table/format.h b/src/leveldb/table/format.h
index 6c0b80c017..e49dfdc047 100644
--- a/src/leveldb/table/format.h
+++ b/src/leveldb/table/format.h
@@ -5,8 +5,10 @@
#ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_
#define STORAGE_LEVELDB_TABLE_FORMAT_H_
-#include <string>
#include <stdint.h>
+
+#include <string>
+
#include "leveldb/slice.h"
#include "leveldb/status.h"
#include "leveldb/table_builder.h"
@@ -21,6 +23,9 @@ struct ReadOptions;
// block or a meta block.
class BlockHandle {
public:
+ // Maximum encoding length of a BlockHandle
+ enum { kMaxEncodedLength = 10 + 10 };
+
BlockHandle();
// The offset of the block in the file.
@@ -34,9 +39,6 @@ class BlockHandle {
void EncodeTo(std::string* dst) const;
Status DecodeFrom(Slice* input);
- // Maximum encoding length of a BlockHandle
- enum { kMaxEncodedLength = 10 + 10 };
-
private:
uint64_t offset_;
uint64_t size_;
@@ -46,30 +48,24 @@ class BlockHandle {
// end of every table file.
class Footer {
public:
- Footer() { }
+ // Encoded length of a Footer. Note that the serialization of a
+ // Footer will always occupy exactly this many bytes. It consists
+ // of two block handles and a magic number.
+ enum { kEncodedLength = 2 * BlockHandle::kMaxEncodedLength + 8 };
+
+ Footer() = default;
// The block handle for the metaindex block of the table
const BlockHandle& metaindex_handle() const { return metaindex_handle_; }
void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; }
// The block handle for the index block of the table
- const BlockHandle& index_handle() const {
- return index_handle_;
- }
- void set_index_handle(const BlockHandle& h) {
- index_handle_ = h;
- }
+ const BlockHandle& index_handle() const { return index_handle_; }
+ void set_index_handle(const BlockHandle& h) { index_handle_ = h; }
void EncodeTo(std::string* dst) const;
Status DecodeFrom(Slice* input);
- // Encoded length of a Footer. Note that the serialization of a
- // Footer will always occupy exactly this many bytes. It consists
- // of two block handles and a magic number.
- enum {
- kEncodedLength = 2*BlockHandle::kMaxEncodedLength + 8
- };
-
private:
BlockHandle metaindex_handle_;
BlockHandle index_handle_;
@@ -91,17 +87,13 @@ struct BlockContents {
// Read the block identified by "handle" from "file". On failure
// return non-OK. On success fill *result and return OK.
-extern Status ReadBlock(RandomAccessFile* file,
- const ReadOptions& options,
- const BlockHandle& handle,
- BlockContents* result);
+Status ReadBlock(RandomAccessFile* file, const ReadOptions& options,
+ const BlockHandle& handle, BlockContents* result);
// Implementation details follow. Clients should ignore,
inline BlockHandle::BlockHandle()
- : offset_(~static_cast<uint64_t>(0)),
- size_(~static_cast<uint64_t>(0)) {
-}
+ : offset_(~static_cast<uint64_t>(0)), size_(~static_cast<uint64_t>(0)) {}
} // namespace leveldb
diff --git a/src/leveldb/table/iterator.cc b/src/leveldb/table/iterator.cc
index 3d1c87fdec..dfef083d4d 100644
--- a/src/leveldb/table/iterator.cc
+++ b/src/leveldb/table/iterator.cc
@@ -7,58 +7,67 @@
namespace leveldb {
Iterator::Iterator() {
- cleanup_.function = NULL;
- cleanup_.next = NULL;
+ cleanup_head_.function = nullptr;
+ cleanup_head_.next = nullptr;
}
Iterator::~Iterator() {
- if (cleanup_.function != NULL) {
- (*cleanup_.function)(cleanup_.arg1, cleanup_.arg2);
- for (Cleanup* c = cleanup_.next; c != NULL; ) {
- (*c->function)(c->arg1, c->arg2);
- Cleanup* next = c->next;
- delete c;
- c = next;
+ if (!cleanup_head_.IsEmpty()) {
+ cleanup_head_.Run();
+ for (CleanupNode* node = cleanup_head_.next; node != nullptr;) {
+ node->Run();
+ CleanupNode* next_node = node->next;
+ delete node;
+ node = next_node;
}
}
}
void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) {
- assert(func != NULL);
- Cleanup* c;
- if (cleanup_.function == NULL) {
- c = &cleanup_;
+ assert(func != nullptr);
+ CleanupNode* node;
+ if (cleanup_head_.IsEmpty()) {
+ node = &cleanup_head_;
} else {
- c = new Cleanup;
- c->next = cleanup_.next;
- cleanup_.next = c;
+ node = new CleanupNode();
+ node->next = cleanup_head_.next;
+ cleanup_head_.next = node;
}
- c->function = func;
- c->arg1 = arg1;
- c->arg2 = arg2;
+ node->function = func;
+ node->arg1 = arg1;
+ node->arg2 = arg2;
}
namespace {
+
class EmptyIterator : public Iterator {
public:
- EmptyIterator(const Status& s) : status_(s) { }
- virtual bool Valid() const { return false; }
- virtual void Seek(const Slice& target) { }
- virtual void SeekToFirst() { }
- virtual void SeekToLast() { }
- virtual void Next() { assert(false); }
- virtual void Prev() { assert(false); }
- Slice key() const { assert(false); return Slice(); }
- Slice value() const { assert(false); return Slice(); }
- virtual Status status() const { return status_; }
+ EmptyIterator(const Status& s) : status_(s) {}
+ ~EmptyIterator() override = default;
+
+ bool Valid() const override { return false; }
+ void Seek(const Slice& target) override {}
+ void SeekToFirst() override {}
+ void SeekToLast() override {}
+ void Next() override { assert(false); }
+ void Prev() override { assert(false); }
+ Slice key() const override {
+ assert(false);
+ return Slice();
+ }
+ Slice value() const override {
+ assert(false);
+ return Slice();
+ }
+ Status status() const override { return status_; }
+
private:
Status status_;
};
-} // namespace
-Iterator* NewEmptyIterator() {
- return new EmptyIterator(Status::OK());
-}
+} // anonymous namespace
+
+Iterator* NewEmptyIterator() { return new EmptyIterator(Status::OK()); }
Iterator* NewErrorIterator(const Status& status) {
return new EmptyIterator(status);
diff --git a/src/leveldb/table/iterator_wrapper.h b/src/leveldb/table/iterator_wrapper.h
index f410c3fabe..c230572529 100644
--- a/src/leveldb/table/iterator_wrapper.h
+++ b/src/leveldb/table/iterator_wrapper.h
@@ -16,10 +16,8 @@ namespace leveldb {
// cache locality.
class IteratorWrapper {
public:
- IteratorWrapper(): iter_(NULL), valid_(false) { }
- explicit IteratorWrapper(Iterator* iter): iter_(NULL) {
- Set(iter);
- }
+ IteratorWrapper() : iter_(nullptr), valid_(false) {}
+ explicit IteratorWrapper(Iterator* iter) : iter_(nullptr) { Set(iter); }
~IteratorWrapper() { delete iter_; }
Iterator* iter() const { return iter_; }
@@ -28,25 +26,53 @@ class IteratorWrapper {
void Set(Iterator* iter) {
delete iter_;
iter_ = iter;
- if (iter_ == NULL) {
+ if (iter_ == nullptr) {
valid_ = false;
} else {
Update();
}
}
-
// Iterator interface methods
- bool Valid() const { return valid_; }
- Slice key() const { assert(Valid()); return key_; }
- Slice value() const { assert(Valid()); return iter_->value(); }
- // Methods below require iter() != NULL
- Status status() const { assert(iter_); return iter_->status(); }
- void Next() { assert(iter_); iter_->Next(); Update(); }
- void Prev() { assert(iter_); iter_->Prev(); Update(); }
- void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); }
- void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); }
- void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); }
+ bool Valid() const { return valid_; }
+ Slice key() const {
+ assert(Valid());
+ return key_;
+ }
+ Slice value() const {
+ assert(Valid());
+ return iter_->value();
+ }
+ // Methods below require iter() != nullptr
+ Status status() const {
+ assert(iter_);
+ return iter_->status();
+ }
+ void Next() {
+ assert(iter_);
+ iter_->Next();
+ Update();
+ }
+ void Prev() {
+ assert(iter_);
+ iter_->Prev();
+ Update();
+ }
+ void Seek(const Slice& k) {
+ assert(iter_);
+ iter_->Seek(k);
+ Update();
+ }
+ void SeekToFirst() {
+ assert(iter_);
+ iter_->SeekToFirst();
+ Update();
+ }
+ void SeekToLast() {
+ assert(iter_);
+ iter_->SeekToLast();
+ Update();
+ }
private:
void Update() {
diff --git a/src/leveldb/table/merger.cc b/src/leveldb/table/merger.cc
index 2dde4dc21f..76441b1cc2 100644
--- a/src/leveldb/table/merger.cc
+++ b/src/leveldb/table/merger.cc
@@ -17,22 +17,18 @@ class MergingIterator : public Iterator {
: comparator_(comparator),
children_(new IteratorWrapper[n]),
n_(n),
- current_(NULL),
+ current_(nullptr),
direction_(kForward) {
for (int i = 0; i < n; i++) {
children_[i].Set(children[i]);
}
}
- virtual ~MergingIterator() {
- delete[] children_;
- }
+ ~MergingIterator() override { delete[] children_; }
- virtual bool Valid() const {
- return (current_ != NULL);
- }
+ bool Valid() const override { return (current_ != nullptr); }
- virtual void SeekToFirst() {
+ void SeekToFirst() override {
for (int i = 0; i < n_; i++) {
children_[i].SeekToFirst();
}
@@ -40,7 +36,7 @@ class MergingIterator : public Iterator {
direction_ = kForward;
}
- virtual void SeekToLast() {
+ void SeekToLast() override {
for (int i = 0; i < n_; i++) {
children_[i].SeekToLast();
}
@@ -48,7 +44,7 @@ class MergingIterator : public Iterator {
direction_ = kReverse;
}
- virtual void Seek(const Slice& target) {
+ void Seek(const Slice& target) override {
for (int i = 0; i < n_; i++) {
children_[i].Seek(target);
}
@@ -56,7 +52,7 @@ class MergingIterator : public Iterator {
direction_ = kForward;
}
- virtual void Next() {
+ void Next() override {
assert(Valid());
// Ensure that all children are positioned after key().
@@ -82,7 +78,7 @@ class MergingIterator : public Iterator {
FindSmallest();
}
- virtual void Prev() {
+ void Prev() override {
assert(Valid());
// Ensure that all children are positioned before key().
@@ -111,17 +107,17 @@ class MergingIterator : public Iterator {
FindLargest();
}
- virtual Slice key() const {
+ Slice key() const override {
assert(Valid());
return current_->key();
}
- virtual Slice value() const {
+ Slice value() const override {
assert(Valid());
return current_->value();
}
- virtual Status status() const {
+ Status status() const override {
Status status;
for (int i = 0; i < n_; i++) {
status = children_[i].status();
@@ -133,6 +129,9 @@ class MergingIterator : public Iterator {
}
private:
+ // Which direction is the iterator moving?
+ enum Direction { kForward, kReverse };
+
void FindSmallest();
void FindLargest();
@@ -143,21 +142,15 @@ class MergingIterator : public Iterator {
IteratorWrapper* children_;
int n_;
IteratorWrapper* current_;
-
- // Which direction is the iterator moving?
- enum Direction {
- kForward,
- kReverse
- };
Direction direction_;
};
void MergingIterator::FindSmallest() {
- IteratorWrapper* smallest = NULL;
+ IteratorWrapper* smallest = nullptr;
for (int i = 0; i < n_; i++) {
IteratorWrapper* child = &children_[i];
if (child->Valid()) {
- if (smallest == NULL) {
+ if (smallest == nullptr) {
smallest = child;
} else if (comparator_->Compare(child->key(), smallest->key()) < 0) {
smallest = child;
@@ -168,11 +161,11 @@ void MergingIterator::FindSmallest() {
}
void MergingIterator::FindLargest() {
- IteratorWrapper* largest = NULL;
- for (int i = n_-1; i >= 0; i--) {
+ IteratorWrapper* largest = nullptr;
+ for (int i = n_ - 1; i >= 0; i--) {
IteratorWrapper* child = &children_[i];
if (child->Valid()) {
- if (largest == NULL) {
+ if (largest == nullptr) {
largest = child;
} else if (comparator_->Compare(child->key(), largest->key()) > 0) {
largest = child;
@@ -183,14 +176,15 @@ void MergingIterator::FindLargest() {
}
} // namespace
-Iterator* NewMergingIterator(const Comparator* cmp, Iterator** list, int n) {
+Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children,
+ int n) {
assert(n >= 0);
if (n == 0) {
return NewEmptyIterator();
} else if (n == 1) {
- return list[0];
+ return children[0];
} else {
- return new MergingIterator(cmp, list, n);
+ return new MergingIterator(comparator, children, n);
}
}
diff --git a/src/leveldb/table/merger.h b/src/leveldb/table/merger.h
index 91ddd80faa..41cedc5254 100644
--- a/src/leveldb/table/merger.h
+++ b/src/leveldb/table/merger.h
@@ -18,8 +18,8 @@ class Iterator;
// key is present in K child iterators, it will be yielded K times.
//
// REQUIRES: n >= 0
-extern Iterator* NewMergingIterator(
- const Comparator* comparator, Iterator** children, int n);
+Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children,
+ int n);
} // namespace leveldb
diff --git a/src/leveldb/table/table.cc b/src/leveldb/table/table.cc
index decf8082cc..b07bc88c7e 100644
--- a/src/leveldb/table/table.cc
+++ b/src/leveldb/table/table.cc
@@ -20,7 +20,7 @@ namespace leveldb {
struct Table::Rep {
~Rep() {
delete filter;
- delete [] filter_data;
+ delete[] filter_data;
delete index_block;
}
@@ -35,11 +35,9 @@ struct Table::Rep {
Block* index_block;
};
-Status Table::Open(const Options& options,
- RandomAccessFile* file,
- uint64_t size,
- Table** table) {
- *table = NULL;
+Status Table::Open(const Options& options, RandomAccessFile* file,
+ uint64_t size, Table** table) {
+ *table = nullptr;
if (size < Footer::kEncodedLength) {
return Status::Corruption("file is too short to be an sstable");
}
@@ -55,41 +53,36 @@ Status Table::Open(const Options& options,
if (!s.ok()) return s;
// Read the index block
- BlockContents contents;
- Block* index_block = NULL;
+ BlockContents index_block_contents;
if (s.ok()) {
ReadOptions opt;
if (options.paranoid_checks) {
opt.verify_checksums = true;
}
- s = ReadBlock(file, opt, footer.index_handle(), &contents);
- if (s.ok()) {
- index_block = new Block(contents);
- }
+ s = ReadBlock(file, opt, footer.index_handle(), &index_block_contents);
}
if (s.ok()) {
// We've successfully read the footer and the index block: we're
// ready to serve requests.
+ Block* index_block = new Block(index_block_contents);
Rep* rep = new Table::Rep;
rep->options = options;
rep->file = file;
rep->metaindex_handle = footer.metaindex_handle();
rep->index_block = index_block;
rep->cache_id = (options.block_cache ? options.block_cache->NewId() : 0);
- rep->filter_data = NULL;
- rep->filter = NULL;
+ rep->filter_data = nullptr;
+ rep->filter = nullptr;
*table = new Table(rep);
(*table)->ReadMeta(footer);
- } else {
- delete index_block;
}
return s;
}
void Table::ReadMeta(const Footer& footer) {
- if (rep_->options.filter_policy == NULL) {
+ if (rep_->options.filter_policy == nullptr) {
return; // Do not need any metadata
}
@@ -135,14 +128,12 @@ void Table::ReadFilter(const Slice& filter_handle_value) {
return;
}
if (block.heap_allocated) {
- rep_->filter_data = block.data.data(); // Will need to delete later
+ rep_->filter_data = block.data.data(); // Will need to delete later
}
rep_->filter = new FilterBlockReader(rep_->options.filter_policy, block.data);
}
-Table::~Table() {
- delete rep_;
-}
+Table::~Table() { delete rep_; }
static void DeleteBlock(void* arg, void* ignored) {
delete reinterpret_cast<Block*>(arg);
@@ -161,13 +152,12 @@ static void ReleaseBlock(void* arg, void* h) {
// Convert an index iterator value (i.e., an encoded BlockHandle)
// into an iterator over the contents of the corresponding block.
-Iterator* Table::BlockReader(void* arg,
- const ReadOptions& options,
+Iterator* Table::BlockReader(void* arg, const ReadOptions& options,
const Slice& index_value) {
Table* table = reinterpret_cast<Table*>(arg);
Cache* block_cache = table->rep_->options.block_cache;
- Block* block = NULL;
- Cache::Handle* cache_handle = NULL;
+ Block* block = nullptr;
+ Cache::Handle* cache_handle = nullptr;
BlockHandle handle;
Slice input = index_value;
@@ -177,21 +167,21 @@ Iterator* Table::BlockReader(void* arg,
if (s.ok()) {
BlockContents contents;
- if (block_cache != NULL) {
+ if (block_cache != nullptr) {
char cache_key_buffer[16];
EncodeFixed64(cache_key_buffer, table->rep_->cache_id);
- EncodeFixed64(cache_key_buffer+8, handle.offset());
+ EncodeFixed64(cache_key_buffer + 8, handle.offset());
Slice key(cache_key_buffer, sizeof(cache_key_buffer));
cache_handle = block_cache->Lookup(key);
- if (cache_handle != NULL) {
+ if (cache_handle != nullptr) {
block = reinterpret_cast<Block*>(block_cache->Value(cache_handle));
} else {
s = ReadBlock(table->rep_->file, options, handle, &contents);
if (s.ok()) {
block = new Block(contents);
if (contents.cachable && options.fill_cache) {
- cache_handle = block_cache->Insert(
- key, block, block->size(), &DeleteCachedBlock);
+ cache_handle = block_cache->Insert(key, block, block->size(),
+ &DeleteCachedBlock);
}
}
}
@@ -204,10 +194,10 @@ Iterator* Table::BlockReader(void* arg,
}
Iterator* iter;
- if (block != NULL) {
+ if (block != nullptr) {
iter = block->NewIterator(table->rep_->options.comparator);
- if (cache_handle == NULL) {
- iter->RegisterCleanup(&DeleteBlock, block, NULL);
+ if (cache_handle == nullptr) {
+ iter->RegisterCleanup(&DeleteBlock, block, nullptr);
} else {
iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle);
}
@@ -223,9 +213,9 @@ Iterator* Table::NewIterator(const ReadOptions& options) const {
&Table::BlockReader, const_cast<Table*>(this), options);
}
-Status Table::InternalGet(const ReadOptions& options, const Slice& k,
- void* arg,
- void (*saver)(void*, const Slice&, const Slice&)) {
+Status Table::InternalGet(const ReadOptions& options, const Slice& k, void* arg,
+ void (*handle_result)(void*, const Slice&,
+ const Slice&)) {
Status s;
Iterator* iiter = rep_->index_block->NewIterator(rep_->options.comparator);
iiter->Seek(k);
@@ -233,15 +223,14 @@ Status Table::InternalGet(const ReadOptions& options, const Slice& k,
Slice handle_value = iiter->value();
FilterBlockReader* filter = rep_->filter;
BlockHandle handle;
- if (filter != NULL &&
- handle.DecodeFrom(&handle_value).ok() &&
+ if (filter != nullptr && handle.DecodeFrom(&handle_value).ok() &&
!filter->KeyMayMatch(handle.offset(), k)) {
// Not found
} else {
Iterator* block_iter = BlockReader(this, options, iiter->value());
block_iter->Seek(k);
if (block_iter->Valid()) {
- (*saver)(arg, block_iter->key(), block_iter->value());
+ (*handle_result)(arg, block_iter->key(), block_iter->value());
}
s = block_iter->status();
delete block_iter;
@@ -254,7 +243,6 @@ Status Table::InternalGet(const ReadOptions& options, const Slice& k,
return s;
}
-
uint64_t Table::ApproximateOffsetOf(const Slice& key) const {
Iterator* index_iter =
rep_->index_block->NewIterator(rep_->options.comparator);
diff --git a/src/leveldb/table/table_builder.cc b/src/leveldb/table/table_builder.cc
index 62002c84f2..278febf94f 100644
--- a/src/leveldb/table/table_builder.cc
+++ b/src/leveldb/table/table_builder.cc
@@ -5,6 +5,7 @@
#include "leveldb/table_builder.h"
#include <assert.h>
+
#include "leveldb/comparator.h"
#include "leveldb/env.h"
#include "leveldb/filter_policy.h"
@@ -18,6 +19,22 @@
namespace leveldb {
struct TableBuilder::Rep {
+ Rep(const Options& opt, WritableFile* f)
+ : options(opt),
+ index_block_options(opt),
+ file(f),
+ offset(0),
+ data_block(&options),
+ index_block(&index_block_options),
+ num_entries(0),
+ closed(false),
+ filter_block(opt.filter_policy == nullptr
+ ? nullptr
+ : new FilterBlockBuilder(opt.filter_policy)),
+ pending_index_entry(false) {
+ index_block_options.block_restart_interval = 1;
+ }
+
Options options;
Options index_block_options;
WritableFile* file;
@@ -27,7 +44,7 @@ struct TableBuilder::Rep {
BlockBuilder index_block;
std::string last_key;
int64_t num_entries;
- bool closed; // Either Finish() or Abandon() has been called.
+ bool closed; // Either Finish() or Abandon() has been called.
FilterBlockBuilder* filter_block;
// We do not emit the index entry for a block until we have seen the
@@ -43,26 +60,11 @@ struct TableBuilder::Rep {
BlockHandle pending_handle; // Handle to add to index block
std::string compressed_output;
-
- Rep(const Options& opt, WritableFile* f)
- : options(opt),
- index_block_options(opt),
- file(f),
- offset(0),
- data_block(&options),
- index_block(&index_block_options),
- num_entries(0),
- closed(false),
- filter_block(opt.filter_policy == NULL ? NULL
- : new FilterBlockBuilder(opt.filter_policy)),
- pending_index_entry(false) {
- index_block_options.block_restart_interval = 1;
- }
};
TableBuilder::TableBuilder(const Options& options, WritableFile* file)
: rep_(new Rep(options, file)) {
- if (rep_->filter_block != NULL) {
+ if (rep_->filter_block != nullptr) {
rep_->filter_block->StartBlock(0);
}
}
@@ -106,7 +108,7 @@ void TableBuilder::Add(const Slice& key, const Slice& value) {
r->pending_index_entry = false;
}
- if (r->filter_block != NULL) {
+ if (r->filter_block != nullptr) {
r->filter_block->AddKey(key);
}
@@ -131,7 +133,7 @@ void TableBuilder::Flush() {
r->pending_index_entry = true;
r->status = r->file->Flush();
}
- if (r->filter_block != NULL) {
+ if (r->filter_block != nullptr) {
r->filter_block->StartBlock(r->offset);
}
}
@@ -173,8 +175,7 @@ void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) {
}
void TableBuilder::WriteRawBlock(const Slice& block_contents,
- CompressionType type,
- BlockHandle* handle) {
+ CompressionType type, BlockHandle* handle) {
Rep* r = rep_;
handle->set_offset(r->offset);
handle->set_size(block_contents.size());
@@ -184,7 +185,7 @@ void TableBuilder::WriteRawBlock(const Slice& block_contents,
trailer[0] = type;
uint32_t crc = crc32c::Value(block_contents.data(), block_contents.size());
crc = crc32c::Extend(crc, trailer, 1); // Extend crc to cover block type
- EncodeFixed32(trailer+1, crc32c::Mask(crc));
+ EncodeFixed32(trailer + 1, crc32c::Mask(crc));
r->status = r->file->Append(Slice(trailer, kBlockTrailerSize));
if (r->status.ok()) {
r->offset += block_contents.size() + kBlockTrailerSize;
@@ -192,9 +193,7 @@ void TableBuilder::WriteRawBlock(const Slice& block_contents,
}
}
-Status TableBuilder::status() const {
- return rep_->status;
-}
+Status TableBuilder::status() const { return rep_->status; }
Status TableBuilder::Finish() {
Rep* r = rep_;
@@ -205,7 +204,7 @@ Status TableBuilder::Finish() {
BlockHandle filter_block_handle, metaindex_block_handle, index_block_handle;
// Write filter block
- if (ok() && r->filter_block != NULL) {
+ if (ok() && r->filter_block != nullptr) {
WriteRawBlock(r->filter_block->Finish(), kNoCompression,
&filter_block_handle);
}
@@ -213,7 +212,7 @@ Status TableBuilder::Finish() {
// Write metaindex block
if (ok()) {
BlockBuilder meta_index_block(&r->options);
- if (r->filter_block != NULL) {
+ if (r->filter_block != nullptr) {
// Add mapping from "filter.Name" to location of filter data
std::string key = "filter.";
key.append(r->options.filter_policy->Name());
@@ -259,12 +258,8 @@ void TableBuilder::Abandon() {
r->closed = true;
}
-uint64_t TableBuilder::NumEntries() const {
- return rep_->num_entries;
-}
+uint64_t TableBuilder::NumEntries() const { return rep_->num_entries; }
-uint64_t TableBuilder::FileSize() const {
- return rep_->offset;
-}
+uint64_t TableBuilder::FileSize() const { return rep_->offset; }
} // namespace leveldb
diff --git a/src/leveldb/table/table_test.cc b/src/leveldb/table/table_test.cc
index abf6e246ff..17aaea2f9e 100644
--- a/src/leveldb/table/table_test.cc
+++ b/src/leveldb/table/table_test.cc
@@ -6,6 +6,7 @@
#include <map>
#include <string>
+
#include "db/dbformat.h"
#include "db/memtable.h"
#include "db/write_batch_internal.h"
@@ -27,8 +28,8 @@ namespace leveldb {
static std::string Reverse(const Slice& key) {
std::string str(key.ToString());
std::string rev("");
- for (std::string::reverse_iterator rit = str.rbegin();
- rit != str.rend(); ++rit) {
+ for (std::string::reverse_iterator rit = str.rbegin(); rit != str.rend();
+ ++rit) {
rev.push_back(*rit);
}
return rev;
@@ -37,24 +38,23 @@ static std::string Reverse(const Slice& key) {
namespace {
class ReverseKeyComparator : public Comparator {
public:
- virtual const char* Name() const {
+ const char* Name() const override {
return "leveldb.ReverseBytewiseComparator";
}
- virtual int Compare(const Slice& a, const Slice& b) const {
+ int Compare(const Slice& a, const Slice& b) const override {
return BytewiseComparator()->Compare(Reverse(a), Reverse(b));
}
- virtual void FindShortestSeparator(
- std::string* start,
- const Slice& limit) const {
+ void FindShortestSeparator(std::string* start,
+ const Slice& limit) const override {
std::string s = Reverse(*start);
std::string l = Reverse(limit);
BytewiseComparator()->FindShortestSeparator(&s, l);
*start = Reverse(s);
}
- virtual void FindShortSuccessor(std::string* key) const {
+ void FindShortSuccessor(std::string* key) const override {
std::string s = Reverse(*key);
BytewiseComparator()->FindShortSuccessor(&s);
*key = Reverse(s);
@@ -79,47 +79,46 @@ namespace {
struct STLLessThan {
const Comparator* cmp;
- STLLessThan() : cmp(BytewiseComparator()) { }
- STLLessThan(const Comparator* c) : cmp(c) { }
+ STLLessThan() : cmp(BytewiseComparator()) {}
+ STLLessThan(const Comparator* c) : cmp(c) {}
bool operator()(const std::string& a, const std::string& b) const {
return cmp->Compare(Slice(a), Slice(b)) < 0;
}
};
} // namespace
-class StringSink: public WritableFile {
+class StringSink : public WritableFile {
public:
- ~StringSink() { }
+ ~StringSink() override = default;
const std::string& contents() const { return contents_; }
- virtual Status Close() { return Status::OK(); }
- virtual Status Flush() { return Status::OK(); }
- virtual Status Sync() { return Status::OK(); }
+ Status Close() override { return Status::OK(); }
+ Status Flush() override { return Status::OK(); }
+ Status Sync() override { return Status::OK(); }
- virtual Status Append(const Slice& data) {
+ Status Append(const Slice& data) override {
contents_.append(data.data(), data.size());
return Status::OK();
}
+ std::string GetName() const override { return ""; }
private:
std::string contents_;
};
-
-class StringSource: public RandomAccessFile {
+class StringSource : public RandomAccessFile {
public:
StringSource(const Slice& contents)
- : contents_(contents.data(), contents.size()) {
- }
+ : contents_(contents.data(), contents.size()) {}
- virtual ~StringSource() { }
+ ~StringSource() override = default;
uint64_t Size() const { return contents_.size(); }
- virtual Status Read(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
- if (offset > contents_.size()) {
+ Status Read(uint64_t offset, size_t n, Slice* result,
+ char* scratch) const override {
+ if (offset >= contents_.size()) {
return Status::InvalidArgument("invalid Read offset");
}
if (offset + n > contents_.size()) {
@@ -130,6 +129,7 @@ class StringSource: public RandomAccessFile {
return Status::OK();
}
+ std::string GetName() const { return ""; }
private:
std::string contents_;
};
@@ -140,8 +140,8 @@ typedef std::map<std::string, std::string, STLLessThan> KVMap;
// BlockBuilder/TableBuilder and Block/Table.
class Constructor {
public:
- explicit Constructor(const Comparator* cmp) : data_(STLLessThan(cmp)) { }
- virtual ~Constructor() { }
+ explicit Constructor(const Comparator* cmp) : data_(STLLessThan(cmp)) {}
+ virtual ~Constructor() = default;
void Add(const std::string& key, const Slice& value) {
data_[key] = value.ToString();
@@ -150,15 +150,12 @@ class Constructor {
// Finish constructing the data structure with all the keys that have
// been added so far. Returns the keys in sorted order in "*keys"
// and stores the key/value pairs in "*kvmap"
- void Finish(const Options& options,
- std::vector<std::string>* keys,
+ void Finish(const Options& options, std::vector<std::string>* keys,
KVMap* kvmap) {
*kvmap = data_;
keys->clear();
- for (KVMap::const_iterator it = data_.begin();
- it != data_.end();
- ++it) {
- keys->push_back(it->first);
+ for (const auto& kvp : data_) {
+ keys->push_back(kvp.first);
}
data_.clear();
Status s = FinishImpl(options, *kvmap);
@@ -170,32 +167,26 @@ class Constructor {
virtual Iterator* NewIterator() const = 0;
- virtual const KVMap& data() { return data_; }
+ const KVMap& data() const { return data_; }
- virtual DB* db() const { return NULL; } // Overridden in DBConstructor
+ virtual DB* db() const { return nullptr; } // Overridden in DBConstructor
private:
KVMap data_;
};
-class BlockConstructor: public Constructor {
+class BlockConstructor : public Constructor {
public:
explicit BlockConstructor(const Comparator* cmp)
- : Constructor(cmp),
- comparator_(cmp),
- block_(NULL) { }
- ~BlockConstructor() {
+ : Constructor(cmp), comparator_(cmp), block_(nullptr) {}
+ ~BlockConstructor() override { delete block_; }
+ Status FinishImpl(const Options& options, const KVMap& data) override {
delete block_;
- }
- virtual Status FinishImpl(const Options& options, const KVMap& data) {
- delete block_;
- block_ = NULL;
+ block_ = nullptr;
BlockBuilder builder(&options);
- for (KVMap::const_iterator it = data.begin();
- it != data.end();
- ++it) {
- builder.Add(it->first, it->second);
+ for (const auto& kvp : data) {
+ builder.Add(kvp.first, kvp.second);
}
// Open the block
data_ = builder.Finish().ToString();
@@ -206,36 +197,30 @@ class BlockConstructor: public Constructor {
block_ = new Block(contents);
return Status::OK();
}
- virtual Iterator* NewIterator() const {
+ Iterator* NewIterator() const override {
return block_->NewIterator(comparator_);
}
private:
- const Comparator* comparator_;
+ const Comparator* const comparator_;
std::string data_;
Block* block_;
BlockConstructor();
};
-class TableConstructor: public Constructor {
+class TableConstructor : public Constructor {
public:
TableConstructor(const Comparator* cmp)
- : Constructor(cmp),
- source_(NULL), table_(NULL) {
- }
- ~TableConstructor() {
- Reset();
- }
- virtual Status FinishImpl(const Options& options, const KVMap& data) {
+ : Constructor(cmp), source_(nullptr), table_(nullptr) {}
+ ~TableConstructor() override { Reset(); }
+ Status FinishImpl(const Options& options, const KVMap& data) override {
Reset();
StringSink sink;
TableBuilder builder(options, &sink);
- for (KVMap::const_iterator it = data.begin();
- it != data.end();
- ++it) {
- builder.Add(it->first, it->second);
+ for (const auto& kvp : data) {
+ builder.Add(kvp.first, kvp.second);
ASSERT_TRUE(builder.status().ok());
}
Status s = builder.Finish();
@@ -250,7 +235,7 @@ class TableConstructor: public Constructor {
return Table::Open(table_options, source_, sink.contents().size(), &table_);
}
- virtual Iterator* NewIterator() const {
+ Iterator* NewIterator() const override {
return table_->NewIterator(ReadOptions());
}
@@ -262,8 +247,8 @@ class TableConstructor: public Constructor {
void Reset() {
delete table_;
delete source_;
- table_ = NULL;
- source_ = NULL;
+ table_ = nullptr;
+ source_ = nullptr;
}
StringSource* source_;
@@ -273,23 +258,28 @@ class TableConstructor: public Constructor {
};
// A helper class that converts internal format keys into user keys
-class KeyConvertingIterator: public Iterator {
+class KeyConvertingIterator : public Iterator {
public:
- explicit KeyConvertingIterator(Iterator* iter) : iter_(iter) { }
- virtual ~KeyConvertingIterator() { delete iter_; }
- virtual bool Valid() const { return iter_->Valid(); }
- virtual void Seek(const Slice& target) {
+ explicit KeyConvertingIterator(Iterator* iter) : iter_(iter) {}
+
+ KeyConvertingIterator(const KeyConvertingIterator&) = delete;
+ KeyConvertingIterator& operator=(const KeyConvertingIterator&) = delete;
+
+ ~KeyConvertingIterator() override { delete iter_; }
+
+ bool Valid() const override { return iter_->Valid(); }
+ void Seek(const Slice& target) override {
ParsedInternalKey ikey(target, kMaxSequenceNumber, kTypeValue);
std::string encoded;
AppendInternalKey(&encoded, ikey);
iter_->Seek(encoded);
}
- virtual void SeekToFirst() { iter_->SeekToFirst(); }
- virtual void SeekToLast() { iter_->SeekToLast(); }
- virtual void Next() { iter_->Next(); }
- virtual void Prev() { iter_->Prev(); }
+ void SeekToFirst() override { iter_->SeekToFirst(); }
+ void SeekToLast() override { iter_->SeekToLast(); }
+ void Next() override { iter_->Next(); }
+ void Prev() override { iter_->Prev(); }
- virtual Slice key() const {
+ Slice key() const override {
assert(Valid());
ParsedInternalKey key;
if (!ParseInternalKey(iter_->key(), &key)) {
@@ -299,82 +289,68 @@ class KeyConvertingIterator: public Iterator {
return key.user_key;
}
- virtual Slice value() const { return iter_->value(); }
- virtual Status status() const {
+ Slice value() const override { return iter_->value(); }
+ Status status() const override {
return status_.ok() ? iter_->status() : status_;
}
private:
mutable Status status_;
Iterator* iter_;
-
- // No copying allowed
- KeyConvertingIterator(const KeyConvertingIterator&);
- void operator=(const KeyConvertingIterator&);
};
-class MemTableConstructor: public Constructor {
+class MemTableConstructor : public Constructor {
public:
explicit MemTableConstructor(const Comparator* cmp)
- : Constructor(cmp),
- internal_comparator_(cmp) {
+ : Constructor(cmp), internal_comparator_(cmp) {
memtable_ = new MemTable(internal_comparator_);
memtable_->Ref();
}
- ~MemTableConstructor() {
- memtable_->Unref();
- }
- virtual Status FinishImpl(const Options& options, const KVMap& data) {
+ ~MemTableConstructor() override { memtable_->Unref(); }
+ Status FinishImpl(const Options& options, const KVMap& data) override {
memtable_->Unref();
memtable_ = new MemTable(internal_comparator_);
memtable_->Ref();
int seq = 1;
- for (KVMap::const_iterator it = data.begin();
- it != data.end();
- ++it) {
- memtable_->Add(seq, kTypeValue, it->first, it->second);
+ for (const auto& kvp : data) {
+ memtable_->Add(seq, kTypeValue, kvp.first, kvp.second);
seq++;
}
return Status::OK();
}
- virtual Iterator* NewIterator() const {
+ Iterator* NewIterator() const override {
return new KeyConvertingIterator(memtable_->NewIterator());
}
private:
- InternalKeyComparator internal_comparator_;
+ const InternalKeyComparator internal_comparator_;
MemTable* memtable_;
};
-class DBConstructor: public Constructor {
+class DBConstructor : public Constructor {
public:
explicit DBConstructor(const Comparator* cmp)
- : Constructor(cmp),
- comparator_(cmp) {
- db_ = NULL;
+ : Constructor(cmp), comparator_(cmp) {
+ db_ = nullptr;
NewDB();
}
- ~DBConstructor() {
- delete db_;
- }
- virtual Status FinishImpl(const Options& options, const KVMap& data) {
+ ~DBConstructor() override { delete db_; }
+ Status FinishImpl(const Options& options, const KVMap& data) override {
delete db_;
- db_ = NULL;
+ db_ = nullptr;
NewDB();
- for (KVMap::const_iterator it = data.begin();
- it != data.end();
- ++it) {
+ for (const auto& kvp : data) {
WriteBatch batch;
- batch.Put(it->first, it->second);
+ batch.Put(kvp.first, kvp.second);
ASSERT_TRUE(db_->Write(WriteOptions(), &batch).ok());
}
return Status::OK();
}
- virtual Iterator* NewIterator() const {
+ Iterator* NewIterator() const override {
return db_->NewIterator(ReadOptions());
}
- virtual DB* db() const { return db_; }
+ DB* db() const override { return db_; }
private:
void NewDB() {
@@ -392,16 +368,11 @@ class DBConstructor: public Constructor {
ASSERT_TRUE(status.ok()) << status.ToString();
}
- const Comparator* comparator_;
+ const Comparator* const comparator_;
DB* db_;
};
-enum TestType {
- TABLE_TEST,
- BLOCK_TEST,
- MEMTABLE_TEST,
- DB_TEST
-};
+enum TestType { TABLE_TEST, BLOCK_TEST, MEMTABLE_TEST, DB_TEST };
struct TestArgs {
TestType type;
@@ -410,37 +381,37 @@ struct TestArgs {
};
static const TestArgs kTestArgList[] = {
- { TABLE_TEST, false, 16 },
- { TABLE_TEST, false, 1 },
- { TABLE_TEST, false, 1024 },
- { TABLE_TEST, true, 16 },
- { TABLE_TEST, true, 1 },
- { TABLE_TEST, true, 1024 },
-
- { BLOCK_TEST, false, 16 },
- { BLOCK_TEST, false, 1 },
- { BLOCK_TEST, false, 1024 },
- { BLOCK_TEST, true, 16 },
- { BLOCK_TEST, true, 1 },
- { BLOCK_TEST, true, 1024 },
-
- // Restart interval does not matter for memtables
- { MEMTABLE_TEST, false, 16 },
- { MEMTABLE_TEST, true, 16 },
-
- // Do not bother with restart interval variations for DB
- { DB_TEST, false, 16 },
- { DB_TEST, true, 16 },
+ {TABLE_TEST, false, 16},
+ {TABLE_TEST, false, 1},
+ {TABLE_TEST, false, 1024},
+ {TABLE_TEST, true, 16},
+ {TABLE_TEST, true, 1},
+ {TABLE_TEST, true, 1024},
+
+ {BLOCK_TEST, false, 16},
+ {BLOCK_TEST, false, 1},
+ {BLOCK_TEST, false, 1024},
+ {BLOCK_TEST, true, 16},
+ {BLOCK_TEST, true, 1},
+ {BLOCK_TEST, true, 1024},
+
+ // Restart interval does not matter for memtables
+ {MEMTABLE_TEST, false, 16},
+ {MEMTABLE_TEST, true, 16},
+
+ // Do not bother with restart interval variations for DB
+ {DB_TEST, false, 16},
+ {DB_TEST, true, 16},
};
static const int kNumTestArgs = sizeof(kTestArgList) / sizeof(kTestArgList[0]);
class Harness {
public:
- Harness() : constructor_(NULL) { }
+ Harness() : constructor_(nullptr) {}
void Init(const TestArgs& args) {
delete constructor_;
- constructor_ = NULL;
+ constructor_ = nullptr;
options_ = Options();
options_.block_restart_interval = args.restart_interval;
@@ -466,9 +437,7 @@ class Harness {
}
}
- ~Harness() {
- delete constructor_;
- }
+ ~Harness() { delete constructor_; }
void Add(const std::string& key, const std::string& value) {
constructor_->Add(key, value);
@@ -490,8 +459,7 @@ class Harness {
ASSERT_TRUE(!iter->Valid());
iter->SeekToFirst();
for (KVMap::const_iterator model_iter = data.begin();
- model_iter != data.end();
- ++model_iter) {
+ model_iter != data.end(); ++model_iter) {
ASSERT_EQ(ToString(data, model_iter), ToString(iter));
iter->Next();
}
@@ -505,8 +473,7 @@ class Harness {
ASSERT_TRUE(!iter->Valid());
iter->SeekToLast();
for (KVMap::const_reverse_iterator model_iter = data.rbegin();
- model_iter != data.rend();
- ++model_iter) {
+ model_iter != data.rend(); ++model_iter) {
ASSERT_EQ(ToString(data, model_iter), ToString(iter));
iter->Prev();
}
@@ -514,8 +481,7 @@ class Harness {
delete iter;
}
- void TestRandomAccess(Random* rnd,
- const std::vector<std::string>& keys,
+ void TestRandomAccess(Random* rnd, const std::vector<std::string>& keys,
const KVMap& data) {
static const bool kVerbose = false;
Iterator* iter = constructor_->NewIterator();
@@ -546,8 +512,8 @@ class Harness {
case 2: {
std::string key = PickRandomKey(rnd, keys);
model_iter = data.lower_bound(key);
- if (kVerbose) fprintf(stderr, "Seek '%s'\n",
- EscapeString(key).c_str());
+ if (kVerbose)
+ fprintf(stderr, "Seek '%s'\n", EscapeString(key).c_str());
iter->Seek(Slice(key));
ASSERT_EQ(ToString(data, model_iter), ToString(iter));
break;
@@ -558,7 +524,7 @@ class Harness {
if (kVerbose) fprintf(stderr, "Prev\n");
iter->Prev();
if (model_iter == data.begin()) {
- model_iter = data.end(); // Wrap around to invalid value
+ model_iter = data.end(); // Wrap around to invalid value
} else {
--model_iter;
}
@@ -621,8 +587,8 @@ class Harness {
break;
case 1: {
// Attempt to return something smaller than an existing key
- if (result.size() > 0 && result[result.size()-1] > '\0') {
- result[result.size()-1]--;
+ if (!result.empty() && result[result.size() - 1] > '\0') {
+ result[result.size() - 1]--;
}
break;
}
@@ -636,7 +602,7 @@ class Harness {
}
}
- // Returns NULL if not running against a DB
+ // Returns nullptr if not running against a DB
DB* db() const { return constructor_->db(); }
private:
@@ -720,8 +686,8 @@ TEST(Harness, Randomized) {
for (int num_entries = 0; num_entries < 2000;
num_entries += (num_entries < 50 ? 1 : 200)) {
if ((num_entries % 10) == 0) {
- fprintf(stderr, "case %d of %d: num_entries = %d\n",
- (i + 1), int(kNumTestArgs), num_entries);
+ fprintf(stderr, "case %d of %d: num_entries = %d\n", (i + 1),
+ int(kNumTestArgs), num_entries);
}
for (int e = 0; e < num_entries; e++) {
std::string v;
@@ -735,7 +701,7 @@ TEST(Harness, Randomized) {
TEST(Harness, RandomizedLongDB) {
Random rnd(test::RandomSeed());
- TestArgs args = { DB_TEST, false, 16 };
+ TestArgs args = {DB_TEST, false, 16};
Init(args);
int num_entries = 100000;
for (int e = 0; e < num_entries; e++) {
@@ -757,7 +723,7 @@ TEST(Harness, RandomizedLongDB) {
ASSERT_GT(files, 0);
}
-class MemTableTest { };
+class MemTableTest {};
TEST(MemTableTest, Simple) {
InternalKeyComparator cmp(BytewiseComparator());
@@ -774,8 +740,7 @@ TEST(MemTableTest, Simple) {
Iterator* iter = memtable->NewIterator();
iter->SeekToFirst();
while (iter->Valid()) {
- fprintf(stderr, "key: '%s' -> '%s'\n",
- iter->key().ToString().c_str(),
+ fprintf(stderr, "key: '%s' -> '%s'\n", iter->key().ToString().c_str(),
iter->value().ToString().c_str());
iter->Next();
}
@@ -788,14 +753,13 @@ static bool Between(uint64_t val, uint64_t low, uint64_t high) {
bool result = (val >= low) && (val <= high);
if (!result) {
fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n",
- (unsigned long long)(val),
- (unsigned long long)(low),
+ (unsigned long long)(val), (unsigned long long)(low),
(unsigned long long)(high));
}
return result;
}
-class TableTest { };
+class TableTest {};
TEST(TableTest, ApproximateOffsetOfPlain) {
TableConstructor c(BytewiseComparator());
@@ -813,18 +777,17 @@ TEST(TableTest, ApproximateOffsetOfPlain) {
options.compression = kNoCompression;
c.Finish(options, &keys, &kvmap);
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0));
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0));
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01a"), 0, 0));
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0));
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 0, 0));
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 10000, 11000));
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0));
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0));
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01a"), 0, 0));
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0));
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 0, 0));
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 10000, 11000));
ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04a"), 210000, 211000));
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("k05"), 210000, 211000));
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("k06"), 510000, 511000));
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("k07"), 510000, 511000));
- ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 610000, 612000));
-
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k05"), 210000, 211000));
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k06"), 510000, 511000));
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k07"), 510000, 511000));
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 610000, 612000));
}
static bool SnappyCompressionSupported() {
@@ -855,7 +818,7 @@ TEST(TableTest, ApproximateOffsetOfCompressed) {
// Expected upper and lower bounds of space used by compressible strings.
static const int kSlop = 1000; // Compressor effectiveness varies.
- const int expected = 2500; // 10000 * compression ratio (0.25)
+ const int expected = 2500; // 10000 * compression ratio (0.25)
const int min_z = expected - kSlop;
const int max_z = expected + kSlop;
@@ -871,6 +834,4 @@ TEST(TableTest, ApproximateOffsetOfCompressed) {
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/table/two_level_iterator.cc b/src/leveldb/table/two_level_iterator.cc
index 7822ebab9c..144790dd97 100644
--- a/src/leveldb/table/two_level_iterator.cc
+++ b/src/leveldb/table/two_level_iterator.cc
@@ -15,38 +15,33 @@ namespace {
typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&);
-class TwoLevelIterator: public Iterator {
+class TwoLevelIterator : public Iterator {
public:
- TwoLevelIterator(
- Iterator* index_iter,
- BlockFunction block_function,
- void* arg,
- const ReadOptions& options);
-
- virtual ~TwoLevelIterator();
-
- virtual void Seek(const Slice& target);
- virtual void SeekToFirst();
- virtual void SeekToLast();
- virtual void Next();
- virtual void Prev();
-
- virtual bool Valid() const {
- return data_iter_.Valid();
- }
- virtual Slice key() const {
+ TwoLevelIterator(Iterator* index_iter, BlockFunction block_function,
+ void* arg, const ReadOptions& options);
+
+ ~TwoLevelIterator() override;
+
+ void Seek(const Slice& target) override;
+ void SeekToFirst() override;
+ void SeekToLast() override;
+ void Next() override;
+ void Prev() override;
+
+ bool Valid() const override { return data_iter_.Valid(); }
+ Slice key() const override {
assert(Valid());
return data_iter_.key();
}
- virtual Slice value() const {
+ Slice value() const override {
assert(Valid());
return data_iter_.value();
}
- virtual Status status() const {
+ Status status() const override {
// It'd be nice if status() returned a const Status& instead of a Status
if (!index_iter_.status().ok()) {
return index_iter_.status();
- } else if (data_iter_.iter() != NULL && !data_iter_.status().ok()) {
+ } else if (data_iter_.iter() != nullptr && !data_iter_.status().ok()) {
return data_iter_.status();
} else {
return status_;
@@ -67,45 +62,41 @@ class TwoLevelIterator: public Iterator {
const ReadOptions options_;
Status status_;
IteratorWrapper index_iter_;
- IteratorWrapper data_iter_; // May be NULL
- // If data_iter_ is non-NULL, then "data_block_handle_" holds the
+ IteratorWrapper data_iter_; // May be nullptr
+ // If data_iter_ is non-null, then "data_block_handle_" holds the
// "index_value" passed to block_function_ to create the data_iter_.
std::string data_block_handle_;
};
-TwoLevelIterator::TwoLevelIterator(
- Iterator* index_iter,
- BlockFunction block_function,
- void* arg,
- const ReadOptions& options)
+TwoLevelIterator::TwoLevelIterator(Iterator* index_iter,
+ BlockFunction block_function, void* arg,
+ const ReadOptions& options)
: block_function_(block_function),
arg_(arg),
options_(options),
index_iter_(index_iter),
- data_iter_(NULL) {
-}
+ data_iter_(nullptr) {}
-TwoLevelIterator::~TwoLevelIterator() {
-}
+TwoLevelIterator::~TwoLevelIterator() = default;
void TwoLevelIterator::Seek(const Slice& target) {
index_iter_.Seek(target);
InitDataBlock();
- if (data_iter_.iter() != NULL) data_iter_.Seek(target);
+ if (data_iter_.iter() != nullptr) data_iter_.Seek(target);
SkipEmptyDataBlocksForward();
}
void TwoLevelIterator::SeekToFirst() {
index_iter_.SeekToFirst();
InitDataBlock();
- if (data_iter_.iter() != NULL) data_iter_.SeekToFirst();
+ if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst();
SkipEmptyDataBlocksForward();
}
void TwoLevelIterator::SeekToLast() {
index_iter_.SeekToLast();
InitDataBlock();
- if (data_iter_.iter() != NULL) data_iter_.SeekToLast();
+ if (data_iter_.iter() != nullptr) data_iter_.SeekToLast();
SkipEmptyDataBlocksBackward();
}
@@ -121,44 +112,44 @@ void TwoLevelIterator::Prev() {
SkipEmptyDataBlocksBackward();
}
-
void TwoLevelIterator::SkipEmptyDataBlocksForward() {
- while (data_iter_.iter() == NULL || !data_iter_.Valid()) {
+ while (data_iter_.iter() == nullptr || !data_iter_.Valid()) {
// Move to next block
if (!index_iter_.Valid()) {
- SetDataIterator(NULL);
+ SetDataIterator(nullptr);
return;
}
index_iter_.Next();
InitDataBlock();
- if (data_iter_.iter() != NULL) data_iter_.SeekToFirst();
+ if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst();
}
}
void TwoLevelIterator::SkipEmptyDataBlocksBackward() {
- while (data_iter_.iter() == NULL || !data_iter_.Valid()) {
+ while (data_iter_.iter() == nullptr || !data_iter_.Valid()) {
// Move to next block
if (!index_iter_.Valid()) {
- SetDataIterator(NULL);
+ SetDataIterator(nullptr);
return;
}
index_iter_.Prev();
InitDataBlock();
- if (data_iter_.iter() != NULL) data_iter_.SeekToLast();
+ if (data_iter_.iter() != nullptr) data_iter_.SeekToLast();
}
}
void TwoLevelIterator::SetDataIterator(Iterator* data_iter) {
- if (data_iter_.iter() != NULL) SaveError(data_iter_.status());
+ if (data_iter_.iter() != nullptr) SaveError(data_iter_.status());
data_iter_.Set(data_iter);
}
void TwoLevelIterator::InitDataBlock() {
if (!index_iter_.Valid()) {
- SetDataIterator(NULL);
+ SetDataIterator(nullptr);
} else {
Slice handle = index_iter_.value();
- if (data_iter_.iter() != NULL && handle.compare(data_block_handle_) == 0) {
+ if (data_iter_.iter() != nullptr &&
+ handle.compare(data_block_handle_) == 0) {
// data_iter_ is already constructed with this iterator, so
// no need to change anything
} else {
@@ -171,11 +162,9 @@ void TwoLevelIterator::InitDataBlock() {
} // namespace
-Iterator* NewTwoLevelIterator(
- Iterator* index_iter,
- BlockFunction block_function,
- void* arg,
- const ReadOptions& options) {
+Iterator* NewTwoLevelIterator(Iterator* index_iter,
+ BlockFunction block_function, void* arg,
+ const ReadOptions& options) {
return new TwoLevelIterator(index_iter, block_function, arg, options);
}
diff --git a/src/leveldb/table/two_level_iterator.h b/src/leveldb/table/two_level_iterator.h
index 629ca34525..81ffe809ac 100644
--- a/src/leveldb/table/two_level_iterator.h
+++ b/src/leveldb/table/two_level_iterator.h
@@ -20,14 +20,11 @@ struct ReadOptions;
//
// Uses a supplied function to convert an index_iter value into
// an iterator over the contents of the corresponding block.
-extern Iterator* NewTwoLevelIterator(
+Iterator* NewTwoLevelIterator(
Iterator* index_iter,
- Iterator* (*block_function)(
- void* arg,
- const ReadOptions& options,
- const Slice& index_value),
- void* arg,
- const ReadOptions& options);
+ Iterator* (*block_function)(void* arg, const ReadOptions& options,
+ const Slice& index_value),
+ void* arg, const ReadOptions& options);
} // namespace leveldb
diff --git a/src/leveldb/util/arena.cc b/src/leveldb/util/arena.cc
index 74078213ee..46e3b2eb8f 100644
--- a/src/leveldb/util/arena.cc
+++ b/src/leveldb/util/arena.cc
@@ -3,16 +3,13 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "util/arena.h"
-#include <assert.h>
namespace leveldb {
static const int kBlockSize = 4096;
-Arena::Arena() : memory_usage_(0) {
- alloc_ptr_ = NULL; // First allocation will allocate a block
- alloc_bytes_remaining_ = 0;
-}
+Arena::Arena()
+ : alloc_ptr_(nullptr), alloc_bytes_remaining_(0), memory_usage_(0) {}
Arena::~Arena() {
for (size_t i = 0; i < blocks_.size(); i++) {
@@ -40,8 +37,9 @@ char* Arena::AllocateFallback(size_t bytes) {
char* Arena::AllocateAligned(size_t bytes) {
const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8;
- assert((align & (align-1)) == 0); // Pointer size should be a power of 2
- size_t current_mod = reinterpret_cast<uintptr_t>(alloc_ptr_) & (align-1);
+ static_assert((align & (align - 1)) == 0,
+ "Pointer size should be a power of 2");
+ size_t current_mod = reinterpret_cast<uintptr_t>(alloc_ptr_) & (align - 1);
size_t slop = (current_mod == 0 ? 0 : align - current_mod);
size_t needed = bytes + slop;
char* result;
@@ -53,15 +51,15 @@ char* Arena::AllocateAligned(size_t bytes) {
// AllocateFallback always returned aligned memory
result = AllocateFallback(bytes);
}
- assert((reinterpret_cast<uintptr_t>(result) & (align-1)) == 0);
+ assert((reinterpret_cast<uintptr_t>(result) & (align - 1)) == 0);
return result;
}
char* Arena::AllocateNewBlock(size_t block_bytes) {
char* result = new char[block_bytes];
blocks_.push_back(result);
- memory_usage_.NoBarrier_Store(
- reinterpret_cast<void*>(MemoryUsage() + block_bytes + sizeof(char*)));
+ memory_usage_.fetch_add(block_bytes + sizeof(char*),
+ std::memory_order_relaxed);
return result;
}
diff --git a/src/leveldb/util/arena.h b/src/leveldb/util/arena.h
index 48bab33741..68fc55d4dd 100644
--- a/src/leveldb/util/arena.h
+++ b/src/leveldb/util/arena.h
@@ -5,29 +5,33 @@
#ifndef STORAGE_LEVELDB_UTIL_ARENA_H_
#define STORAGE_LEVELDB_UTIL_ARENA_H_
+#include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <vector>
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
-#include "port/port.h"
namespace leveldb {
class Arena {
public:
Arena();
+
+ Arena(const Arena&) = delete;
+ Arena& operator=(const Arena&) = delete;
+
~Arena();
// Return a pointer to a newly allocated memory block of "bytes" bytes.
char* Allocate(size_t bytes);
- // Allocate memory with the normal alignment guarantees provided by malloc
+ // Allocate memory with the normal alignment guarantees provided by malloc.
char* AllocateAligned(size_t bytes);
// Returns an estimate of the total memory usage of data allocated
// by the arena.
size_t MemoryUsage() const {
- return reinterpret_cast<uintptr_t>(memory_usage_.NoBarrier_Load());
+ return memory_usage_.load(std::memory_order_relaxed);
}
private:
@@ -42,11 +46,10 @@ class Arena {
std::vector<char*> blocks_;
// Total memory usage of the arena.
- port::AtomicPointer memory_usage_;
-
- // No copying allowed
- Arena(const Arena&);
- void operator=(const Arena&);
+ //
+ // TODO(costan): This member is accessed via atomics, but the others are
+ // accessed without any locking. Is this OK?
+ std::atomic<size_t> memory_usage_;
};
inline char* Arena::Allocate(size_t bytes) {
diff --git a/src/leveldb/util/arena_test.cc b/src/leveldb/util/arena_test.cc
index 58e870ec44..e917228f42 100644
--- a/src/leveldb/util/arena_test.cc
+++ b/src/leveldb/util/arena_test.cc
@@ -9,14 +9,12 @@
namespace leveldb {
-class ArenaTest { };
+class ArenaTest {};
-TEST(ArenaTest, Empty) {
- Arena arena;
-}
+TEST(ArenaTest, Empty) { Arena arena; }
TEST(ArenaTest, Simple) {
- std::vector<std::pair<size_t, char*> > allocated;
+ std::vector<std::pair<size_t, char*>> allocated;
Arena arena;
const int N = 100000;
size_t bytes = 0;
@@ -26,8 +24,9 @@ TEST(ArenaTest, Simple) {
if (i % (N / 10) == 0) {
s = i;
} else {
- s = rnd.OneIn(4000) ? rnd.Uniform(6000) :
- (rnd.OneIn(10) ? rnd.Uniform(100) : rnd.Uniform(20));
+ s = rnd.OneIn(4000)
+ ? rnd.Uniform(6000)
+ : (rnd.OneIn(10) ? rnd.Uniform(100) : rnd.Uniform(20));
}
if (s == 0) {
// Our arena disallows size 0 allocations.
@@ -47,7 +46,7 @@ TEST(ArenaTest, Simple) {
bytes += s;
allocated.push_back(std::make_pair(s, r));
ASSERT_GE(arena.MemoryUsage(), bytes);
- if (i > N/10) {
+ if (i > N / 10) {
ASSERT_LE(arena.MemoryUsage(), bytes * 1.10);
}
}
@@ -63,6 +62,4 @@ TEST(ArenaTest, Simple) {
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/bloom.cc b/src/leveldb/util/bloom.cc
index bf3e4ca6e9..87547a7e62 100644
--- a/src/leveldb/util/bloom.cc
+++ b/src/leveldb/util/bloom.cc
@@ -15,24 +15,17 @@ static uint32_t BloomHash(const Slice& key) {
}
class BloomFilterPolicy : public FilterPolicy {
- private:
- size_t bits_per_key_;
- size_t k_;
-
public:
- explicit BloomFilterPolicy(int bits_per_key)
- : bits_per_key_(bits_per_key) {
+ explicit BloomFilterPolicy(int bits_per_key) : bits_per_key_(bits_per_key) {
// We intentionally round down to reduce probing cost a little bit
k_ = static_cast<size_t>(bits_per_key * 0.69); // 0.69 =~ ln(2)
if (k_ < 1) k_ = 1;
if (k_ > 30) k_ = 30;
}
- virtual const char* Name() const {
- return "leveldb.BuiltinBloomFilter2";
- }
+ const char* Name() const override { return "leveldb.BuiltinBloomFilter2"; }
- virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
+ void CreateFilter(const Slice* keys, int n, std::string* dst) const override {
// Compute bloom filter size (in both bits and bytes)
size_t bits = n * bits_per_key_;
@@ -54,13 +47,13 @@ class BloomFilterPolicy : public FilterPolicy {
const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
for (size_t j = 0; j < k_; j++) {
const uint32_t bitpos = h % bits;
- array[bitpos/8] |= (1 << (bitpos % 8));
+ array[bitpos / 8] |= (1 << (bitpos % 8));
h += delta;
}
}
}
- virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const {
+ bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const override {
const size_t len = bloom_filter.size();
if (len < 2) return false;
@@ -69,7 +62,7 @@ class BloomFilterPolicy : public FilterPolicy {
// Use the encoded k so that we can read filters generated by
// bloom filters created using different parameters.
- const size_t k = array[len-1];
+ const size_t k = array[len - 1];
if (k > 30) {
// Reserved for potentially new encodings for short bloom filters.
// Consider it a match.
@@ -80,13 +73,17 @@ class BloomFilterPolicy : public FilterPolicy {
const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
for (size_t j = 0; j < k; j++) {
const uint32_t bitpos = h % bits;
- if ((array[bitpos/8] & (1 << (bitpos % 8))) == 0) return false;
+ if ((array[bitpos / 8] & (1 << (bitpos % 8))) == 0) return false;
h += delta;
}
return true;
}
+
+ private:
+ size_t bits_per_key_;
+ size_t k_;
};
-}
+} // namespace
const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) {
return new BloomFilterPolicy(bits_per_key);
diff --git a/src/leveldb/util/bloom_test.cc b/src/leveldb/util/bloom_test.cc
index 1b87a2be3f..436daa9e99 100644
--- a/src/leveldb/util/bloom_test.cc
+++ b/src/leveldb/util/bloom_test.cc
@@ -19,26 +19,17 @@ static Slice Key(int i, char* buffer) {
}
class BloomTest {
- private:
- const FilterPolicy* policy_;
- std::string filter_;
- std::vector<std::string> keys_;
-
public:
- BloomTest() : policy_(NewBloomFilterPolicy(10)) { }
+ BloomTest() : policy_(NewBloomFilterPolicy(10)) {}
- ~BloomTest() {
- delete policy_;
- }
+ ~BloomTest() { delete policy_; }
void Reset() {
keys_.clear();
filter_.clear();
}
- void Add(const Slice& s) {
- keys_.push_back(s.ToString());
- }
+ void Add(const Slice& s) { keys_.push_back(s.ToString()); }
void Build() {
std::vector<Slice> key_slices;
@@ -52,16 +43,14 @@ class BloomTest {
if (kVerbose >= 2) DumpFilter();
}
- size_t FilterSize() const {
- return filter_.size();
- }
+ size_t FilterSize() const { return filter_.size(); }
void DumpFilter() {
fprintf(stderr, "F(");
- for (size_t i = 0; i+1 < filter_.size(); i++) {
+ for (size_t i = 0; i + 1 < filter_.size(); i++) {
const unsigned int c = static_cast<unsigned int>(filter_[i]);
for (int j = 0; j < 8; j++) {
- fprintf(stderr, "%c", (c & (1 <<j)) ? '1' : '.');
+ fprintf(stderr, "%c", (c & (1 << j)) ? '1' : '.');
}
}
fprintf(stderr, ")\n");
@@ -84,11 +73,16 @@ class BloomTest {
}
return result / 10000.0;
}
+
+ private:
+ const FilterPolicy* policy_;
+ std::string filter_;
+ std::vector<std::string> keys_;
};
TEST(BloomTest, EmptyFilter) {
- ASSERT_TRUE(! Matches("hello"));
- ASSERT_TRUE(! Matches("world"));
+ ASSERT_TRUE(!Matches("hello"));
+ ASSERT_TRUE(!Matches("world"));
}
TEST(BloomTest, Small) {
@@ -96,8 +90,8 @@ TEST(BloomTest, Small) {
Add("world");
ASSERT_TRUE(Matches("hello"));
ASSERT_TRUE(Matches("world"));
- ASSERT_TRUE(! Matches("x"));
- ASSERT_TRUE(! Matches("foo"));
+ ASSERT_TRUE(!Matches("x"));
+ ASSERT_TRUE(!Matches("foo"));
}
static int NextLength(int length) {
@@ -140,23 +134,23 @@ TEST(BloomTest, VaryingLengths) {
double rate = FalsePositiveRate();
if (kVerbose >= 1) {
fprintf(stderr, "False positives: %5.2f%% @ length = %6d ; bytes = %6d\n",
- rate*100.0, length, static_cast<int>(FilterSize()));
+ rate * 100.0, length, static_cast<int>(FilterSize()));
}
- ASSERT_LE(rate, 0.02); // Must not be over 2%
- if (rate > 0.0125) mediocre_filters++; // Allowed, but not too often
- else good_filters++;
+ ASSERT_LE(rate, 0.02); // Must not be over 2%
+ if (rate > 0.0125)
+ mediocre_filters++; // Allowed, but not too often
+ else
+ good_filters++;
}
if (kVerbose >= 1) {
- fprintf(stderr, "Filters: %d good, %d mediocre\n",
- good_filters, mediocre_filters);
+ fprintf(stderr, "Filters: %d good, %d mediocre\n", good_filters,
+ mediocre_filters);
}
- ASSERT_LE(mediocre_filters, good_filters/5);
+ ASSERT_LE(mediocre_filters, good_filters / 5);
}
// Different bits-per-byte
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/cache.cc b/src/leveldb/util/cache.cc
index ce46886171..12de306cad 100644
--- a/src/leveldb/util/cache.cc
+++ b/src/leveldb/util/cache.cc
@@ -8,13 +8,13 @@
#include "leveldb/cache.h"
#include "port/port.h"
+#include "port/thread_annotations.h"
#include "util/hash.h"
#include "util/mutexlock.h"
namespace leveldb {
-Cache::~Cache() {
-}
+Cache::~Cache() {}
namespace {
@@ -45,21 +45,19 @@ struct LRUHandle {
LRUHandle* next_hash;
LRUHandle* next;
LRUHandle* prev;
- size_t charge; // TODO(opt): Only allow uint32_t?
+ size_t charge; // TODO(opt): Only allow uint32_t?
size_t key_length;
- bool in_cache; // Whether entry is in the cache.
- uint32_t refs; // References, including cache reference, if present.
- uint32_t hash; // Hash of key(); used for fast sharding and comparisons
- char key_data[1]; // Beginning of key
+ bool in_cache; // Whether entry is in the cache.
+ uint32_t refs; // References, including cache reference, if present.
+ uint32_t hash; // Hash of key(); used for fast sharding and comparisons
+ char key_data[1]; // Beginning of key
Slice key() const {
- // For cheaper lookups, we allow a temporary Handle object
- // to store a pointer to a key in "value".
- if (next == this) {
- return *(reinterpret_cast<Slice*>(value));
- } else {
- return Slice(key_data, key_length);
- }
+ // next_ is only equal to this if the LRU handle is the list head of an
+ // empty list. List heads never have meaningful keys.
+ assert(next != this);
+
+ return Slice(key_data, key_length);
}
};
@@ -70,7 +68,7 @@ struct LRUHandle {
// 4.4.3's builtin hashtable.
class HandleTable {
public:
- HandleTable() : length_(0), elems_(0), list_(NULL) { Resize(); }
+ HandleTable() : length_(0), elems_(0), list_(nullptr) { Resize(); }
~HandleTable() { delete[] list_; }
LRUHandle* Lookup(const Slice& key, uint32_t hash) {
@@ -80,9 +78,9 @@ class HandleTable {
LRUHandle* Insert(LRUHandle* h) {
LRUHandle** ptr = FindPointer(h->key(), h->hash);
LRUHandle* old = *ptr;
- h->next_hash = (old == NULL ? NULL : old->next_hash);
+ h->next_hash = (old == nullptr ? nullptr : old->next_hash);
*ptr = h;
- if (old == NULL) {
+ if (old == nullptr) {
++elems_;
if (elems_ > length_) {
// Since each cache entry is fairly large, we aim for a small
@@ -96,7 +94,7 @@ class HandleTable {
LRUHandle* Remove(const Slice& key, uint32_t hash) {
LRUHandle** ptr = FindPointer(key, hash);
LRUHandle* result = *ptr;
- if (result != NULL) {
+ if (result != nullptr) {
*ptr = result->next_hash;
--elems_;
}
@@ -115,8 +113,7 @@ class HandleTable {
// pointer to the trailing slot in the corresponding linked list.
LRUHandle** FindPointer(const Slice& key, uint32_t hash) {
LRUHandle** ptr = &list_[hash & (length_ - 1)];
- while (*ptr != NULL &&
- ((*ptr)->hash != hash || key != (*ptr)->key())) {
+ while (*ptr != nullptr && ((*ptr)->hash != hash || key != (*ptr)->key())) {
ptr = &(*ptr)->next_hash;
}
return ptr;
@@ -132,7 +129,7 @@ class HandleTable {
uint32_t count = 0;
for (uint32_t i = 0; i < length_; i++) {
LRUHandle* h = list_[i];
- while (h != NULL) {
+ while (h != nullptr) {
LRUHandle* next = h->next_hash;
uint32_t hash = h->hash;
LRUHandle** ptr = &new_list[hash & (new_length - 1)];
@@ -159,8 +156,8 @@ class LRUCache {
void SetCapacity(size_t capacity) { capacity_ = capacity; }
// Like Cache methods, but with an extra "hash" parameter.
- Cache::Handle* Insert(const Slice& key, uint32_t hash,
- void* value, size_t charge,
+ Cache::Handle* Insert(const Slice& key, uint32_t hash, void* value,
+ size_t charge,
void (*deleter)(const Slice& key, void* value));
Cache::Handle* Lookup(const Slice& key, uint32_t hash);
void Release(Cache::Handle* handle);
@@ -173,32 +170,31 @@ class LRUCache {
private:
void LRU_Remove(LRUHandle* e);
- void LRU_Append(LRUHandle*list, LRUHandle* e);
+ void LRU_Append(LRUHandle* list, LRUHandle* e);
void Ref(LRUHandle* e);
void Unref(LRUHandle* e);
- bool FinishErase(LRUHandle* e);
+ bool FinishErase(LRUHandle* e) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Initialized before use.
size_t capacity_;
// mutex_ protects the following state.
mutable port::Mutex mutex_;
- size_t usage_;
+ size_t usage_ GUARDED_BY(mutex_);
// Dummy head of LRU list.
// lru.prev is newest entry, lru.next is oldest entry.
// Entries have refs==1 and in_cache==true.
- LRUHandle lru_;
+ LRUHandle lru_ GUARDED_BY(mutex_);
// Dummy head of in-use list.
// Entries are in use by clients, and have refs >= 2 and in_cache==true.
- LRUHandle in_use_;
+ LRUHandle in_use_ GUARDED_BY(mutex_);
- HandleTable table_;
+ HandleTable table_ GUARDED_BY(mutex_);
};
-LRUCache::LRUCache()
- : usage_(0) {
+LRUCache::LRUCache() : capacity_(0), usage_(0) {
// Make empty circular linked lists.
lru_.next = &lru_;
lru_.prev = &lru_;
@@ -208,7 +204,7 @@ LRUCache::LRUCache()
LRUCache::~LRUCache() {
assert(in_use_.next == &in_use_); // Error if caller has an unreleased handle
- for (LRUHandle* e = lru_.next; e != &lru_; ) {
+ for (LRUHandle* e = lru_.next; e != &lru_;) {
LRUHandle* next = e->next;
assert(e->in_cache);
e->in_cache = false;
@@ -229,11 +225,12 @@ void LRUCache::Ref(LRUHandle* e) {
void LRUCache::Unref(LRUHandle* e) {
assert(e->refs > 0);
e->refs--;
- if (e->refs == 0) { // Deallocate.
+ if (e->refs == 0) { // Deallocate.
assert(!e->in_cache);
(*e->deleter)(e->key(), e->value);
free(e);
- } else if (e->in_cache && e->refs == 1) { // No longer in use; move to lru_ list.
+ } else if (e->in_cache && e->refs == 1) {
+ // No longer in use; move to lru_ list.
LRU_Remove(e);
LRU_Append(&lru_, e);
}
@@ -255,7 +252,7 @@ void LRUCache::LRU_Append(LRUHandle* list, LRUHandle* e) {
Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) {
MutexLock l(&mutex_);
LRUHandle* e = table_.Lookup(key, hash);
- if (e != NULL) {
+ if (e != nullptr) {
Ref(e);
}
return reinterpret_cast<Cache::Handle*>(e);
@@ -266,13 +263,14 @@ void LRUCache::Release(Cache::Handle* handle) {
Unref(reinterpret_cast<LRUHandle*>(handle));
}
-Cache::Handle* LRUCache::Insert(
- const Slice& key, uint32_t hash, void* value, size_t charge,
- void (*deleter)(const Slice& key, void* value)) {
+Cache::Handle* LRUCache::Insert(const Slice& key, uint32_t hash, void* value,
+ size_t charge,
+ void (*deleter)(const Slice& key,
+ void* value)) {
MutexLock l(&mutex_);
- LRUHandle* e = reinterpret_cast<LRUHandle*>(
- malloc(sizeof(LRUHandle)-1 + key.size()));
+ LRUHandle* e =
+ reinterpret_cast<LRUHandle*>(malloc(sizeof(LRUHandle) - 1 + key.size()));
e->value = value;
e->deleter = deleter;
e->charge = charge;
@@ -288,8 +286,10 @@ Cache::Handle* LRUCache::Insert(
LRU_Append(&in_use_, e);
usage_ += charge;
FinishErase(table_.Insert(e));
- } // else don't cache. (Tests use capacity_==0 to turn off caching.)
-
+ } else { // don't cache. (capacity_==0 is supported and turns off caching.)
+ // next is read by key() in an assert, so it must be initialized
+ e->next = nullptr;
+ }
while (usage_ > capacity_ && lru_.next != &lru_) {
LRUHandle* old = lru_.next;
assert(old->refs == 1);
@@ -302,17 +302,17 @@ Cache::Handle* LRUCache::Insert(
return reinterpret_cast<Cache::Handle*>(e);
}
-// If e != NULL, finish removing *e from the cache; it has already been removed
-// from the hash table. Return whether e != NULL. Requires mutex_ held.
+// If e != nullptr, finish removing *e from the cache; it has already been
+// removed from the hash table. Return whether e != nullptr.
bool LRUCache::FinishErase(LRUHandle* e) {
- if (e != NULL) {
+ if (e != nullptr) {
assert(e->in_cache);
LRU_Remove(e);
e->in_cache = false;
usage_ -= e->charge;
Unref(e);
}
- return e != NULL;
+ return e != nullptr;
}
void LRUCache::Erase(const Slice& key, uint32_t hash) {
@@ -345,49 +345,46 @@ class ShardedLRUCache : public Cache {
return Hash(s.data(), s.size(), 0);
}
- static uint32_t Shard(uint32_t hash) {
- return hash >> (32 - kNumShardBits);
- }
+ static uint32_t Shard(uint32_t hash) { return hash >> (32 - kNumShardBits); }
public:
- explicit ShardedLRUCache(size_t capacity)
- : last_id_(0) {
+ explicit ShardedLRUCache(size_t capacity) : last_id_(0) {
const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards;
for (int s = 0; s < kNumShards; s++) {
shard_[s].SetCapacity(per_shard);
}
}
- virtual ~ShardedLRUCache() { }
- virtual Handle* Insert(const Slice& key, void* value, size_t charge,
- void (*deleter)(const Slice& key, void* value)) {
+ ~ShardedLRUCache() override {}
+ Handle* Insert(const Slice& key, void* value, size_t charge,
+ void (*deleter)(const Slice& key, void* value)) override {
const uint32_t hash = HashSlice(key);
return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter);
}
- virtual Handle* Lookup(const Slice& key) {
+ Handle* Lookup(const Slice& key) override {
const uint32_t hash = HashSlice(key);
return shard_[Shard(hash)].Lookup(key, hash);
}
- virtual void Release(Handle* handle) {
+ void Release(Handle* handle) override {
LRUHandle* h = reinterpret_cast<LRUHandle*>(handle);
shard_[Shard(h->hash)].Release(handle);
}
- virtual void Erase(const Slice& key) {
+ void Erase(const Slice& key) override {
const uint32_t hash = HashSlice(key);
shard_[Shard(hash)].Erase(key, hash);
}
- virtual void* Value(Handle* handle) {
+ void* Value(Handle* handle) override {
return reinterpret_cast<LRUHandle*>(handle)->value;
}
- virtual uint64_t NewId() {
+ uint64_t NewId() override {
MutexLock l(&id_mutex_);
return ++(last_id_);
}
- virtual void Prune() {
+ void Prune() override {
for (int s = 0; s < kNumShards; s++) {
shard_[s].Prune();
}
}
- virtual size_t TotalCharge() const {
+ size_t TotalCharge() const override {
size_t total = 0;
for (int s = 0; s < kNumShards; s++) {
total += shard_[s].TotalCharge();
@@ -398,8 +395,6 @@ class ShardedLRUCache : public Cache {
} // end anonymous namespace
-Cache* NewLRUCache(size_t capacity) {
- return new ShardedLRUCache(capacity);
-}
+Cache* NewLRUCache(size_t capacity) { return new ShardedLRUCache(capacity); }
} // namespace leveldb
diff --git a/src/leveldb/util/cache_test.cc b/src/leveldb/util/cache_test.cc
index 468f7a6425..974334b9f8 100644
--- a/src/leveldb/util/cache_test.cc
+++ b/src/leveldb/util/cache_test.cc
@@ -25,8 +25,6 @@ static int DecodeValue(void* v) { return reinterpret_cast<uintptr_t>(v); }
class CacheTest {
public:
- static CacheTest* current_;
-
static void Deleter(const Slice& key, void* v) {
current_->deleted_keys_.push_back(DecodeKey(key));
current_->deleted_values_.push_back(DecodeValue(v));
@@ -37,18 +35,14 @@ class CacheTest {
std::vector<int> deleted_values_;
Cache* cache_;
- CacheTest() : cache_(NewLRUCache(kCacheSize)) {
- current_ = this;
- }
+ CacheTest() : cache_(NewLRUCache(kCacheSize)) { current_ = this; }
- ~CacheTest() {
- delete cache_;
- }
+ ~CacheTest() { delete cache_; }
int Lookup(int key) {
Cache::Handle* handle = cache_->Lookup(EncodeKey(key));
- const int r = (handle == NULL) ? -1 : DecodeValue(cache_->Value(handle));
- if (handle != NULL) {
+ const int r = (handle == nullptr) ? -1 : DecodeValue(cache_->Value(handle));
+ if (handle != nullptr) {
cache_->Release(handle);
}
return r;
@@ -64,9 +58,9 @@ class CacheTest {
&CacheTest::Deleter);
}
- void Erase(int key) {
- cache_->Erase(EncodeKey(key));
- }
+ void Erase(int key) { cache_->Erase(EncodeKey(key)); }
+
+ static CacheTest* current_;
};
CacheTest* CacheTest::current_;
@@ -75,18 +69,18 @@ TEST(CacheTest, HitAndMiss) {
Insert(100, 101);
ASSERT_EQ(101, Lookup(100));
- ASSERT_EQ(-1, Lookup(200));
- ASSERT_EQ(-1, Lookup(300));
+ ASSERT_EQ(-1, Lookup(200));
+ ASSERT_EQ(-1, Lookup(300));
Insert(200, 201);
ASSERT_EQ(101, Lookup(100));
ASSERT_EQ(201, Lookup(200));
- ASSERT_EQ(-1, Lookup(300));
+ ASSERT_EQ(-1, Lookup(300));
Insert(100, 102);
ASSERT_EQ(102, Lookup(100));
ASSERT_EQ(201, Lookup(200));
- ASSERT_EQ(-1, Lookup(300));
+ ASSERT_EQ(-1, Lookup(300));
ASSERT_EQ(1, deleted_keys_.size());
ASSERT_EQ(100, deleted_keys_[0]);
@@ -100,14 +94,14 @@ TEST(CacheTest, Erase) {
Insert(100, 101);
Insert(200, 201);
Erase(100);
- ASSERT_EQ(-1, Lookup(100));
+ ASSERT_EQ(-1, Lookup(100));
ASSERT_EQ(201, Lookup(200));
ASSERT_EQ(1, deleted_keys_.size());
ASSERT_EQ(100, deleted_keys_[0]);
ASSERT_EQ(101, deleted_values_[0]);
Erase(100);
- ASSERT_EQ(-1, Lookup(100));
+ ASSERT_EQ(-1, Lookup(100));
ASSERT_EQ(201, Lookup(200));
ASSERT_EQ(1, deleted_keys_.size());
}
@@ -146,8 +140,8 @@ TEST(CacheTest, EvictionPolicy) {
// Frequently used entry must be kept around,
// as must things that are still in use.
for (int i = 0; i < kCacheSize + 100; i++) {
- Insert(1000+i, 2000+i);
- ASSERT_EQ(2000+i, Lookup(1000+i));
+ Insert(1000 + i, 2000 + i);
+ ASSERT_EQ(2000 + i, Lookup(1000 + i));
ASSERT_EQ(101, Lookup(100));
}
ASSERT_EQ(101, Lookup(100));
@@ -160,12 +154,12 @@ TEST(CacheTest, UseExceedsCacheSize) {
// Overfill the cache, keeping handles on all inserted entries.
std::vector<Cache::Handle*> h;
for (int i = 0; i < kCacheSize + 100; i++) {
- h.push_back(InsertAndReturnHandle(1000+i, 2000+i));
+ h.push_back(InsertAndReturnHandle(1000 + i, 2000 + i));
}
// Check that all the entries can be found in the cache.
for (int i = 0; i < h.size(); i++) {
- ASSERT_EQ(2000+i, Lookup(1000+i));
+ ASSERT_EQ(2000 + i, Lookup(1000 + i));
}
for (int i = 0; i < h.size(); i++) {
@@ -181,9 +175,9 @@ TEST(CacheTest, HeavyEntries) {
const int kHeavy = 10;
int added = 0;
int index = 0;
- while (added < 2*kCacheSize) {
+ while (added < 2 * kCacheSize) {
const int weight = (index & 1) ? kLight : kHeavy;
- Insert(index, 1000+index, weight);
+ Insert(index, 1000 + index, weight);
added += weight;
index++;
}
@@ -194,10 +188,10 @@ TEST(CacheTest, HeavyEntries) {
int r = Lookup(i);
if (r >= 0) {
cached_weight += weight;
- ASSERT_EQ(1000+i, r);
+ ASSERT_EQ(1000 + i, r);
}
}
- ASSERT_LE(cached_weight, kCacheSize + kCacheSize/10);
+ ASSERT_LE(cached_weight, kCacheSize + kCacheSize / 10);
}
TEST(CacheTest, NewId) {
@@ -219,8 +213,14 @@ TEST(CacheTest, Prune) {
ASSERT_EQ(-1, Lookup(2));
}
-} // namespace leveldb
+TEST(CacheTest, ZeroSizeCache) {
+ delete cache_;
+ cache_ = NewLRUCache(0);
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
+ Insert(1, 100);
+ ASSERT_EQ(-1, Lookup(1));
}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/coding.cc b/src/leveldb/util/coding.cc
index 21e3186d5d..df3fa10f0d 100644
--- a/src/leveldb/util/coding.cc
+++ b/src/leveldb/util/coding.cc
@@ -6,32 +6,6 @@
namespace leveldb {
-void EncodeFixed32(char* buf, uint32_t value) {
- if (port::kLittleEndian) {
- memcpy(buf, &value, sizeof(value));
- } else {
- buf[0] = value & 0xff;
- buf[1] = (value >> 8) & 0xff;
- buf[2] = (value >> 16) & 0xff;
- buf[3] = (value >> 24) & 0xff;
- }
-}
-
-void EncodeFixed64(char* buf, uint64_t value) {
- if (port::kLittleEndian) {
- memcpy(buf, &value, sizeof(value));
- } else {
- buf[0] = value & 0xff;
- buf[1] = (value >> 8) & 0xff;
- buf[2] = (value >> 16) & 0xff;
- buf[3] = (value >> 24) & 0xff;
- buf[4] = (value >> 32) & 0xff;
- buf[5] = (value >> 40) & 0xff;
- buf[6] = (value >> 48) & 0xff;
- buf[7] = (value >> 56) & 0xff;
- }
-}
-
void PutFixed32(std::string* dst, uint32_t value) {
char buf[sizeof(value)];
EncodeFixed32(buf, value);
@@ -46,28 +20,28 @@ void PutFixed64(std::string* dst, uint64_t value) {
char* EncodeVarint32(char* dst, uint32_t v) {
// Operate on characters as unsigneds
- unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(dst);
static const int B = 128;
- if (v < (1<<7)) {
+ if (v < (1 << 7)) {
*(ptr++) = v;
- } else if (v < (1<<14)) {
+ } else if (v < (1 << 14)) {
*(ptr++) = v | B;
- *(ptr++) = v>>7;
- } else if (v < (1<<21)) {
+ *(ptr++) = v >> 7;
+ } else if (v < (1 << 21)) {
*(ptr++) = v | B;
- *(ptr++) = (v>>7) | B;
- *(ptr++) = v>>14;
- } else if (v < (1<<28)) {
+ *(ptr++) = (v >> 7) | B;
+ *(ptr++) = v >> 14;
+ } else if (v < (1 << 28)) {
*(ptr++) = v | B;
- *(ptr++) = (v>>7) | B;
- *(ptr++) = (v>>14) | B;
- *(ptr++) = v>>21;
+ *(ptr++) = (v >> 7) | B;
+ *(ptr++) = (v >> 14) | B;
+ *(ptr++) = v >> 21;
} else {
*(ptr++) = v | B;
- *(ptr++) = (v>>7) | B;
- *(ptr++) = (v>>14) | B;
- *(ptr++) = (v>>21) | B;
- *(ptr++) = v>>28;
+ *(ptr++) = (v >> 7) | B;
+ *(ptr++) = (v >> 14) | B;
+ *(ptr++) = (v >> 21) | B;
+ *(ptr++) = v >> 28;
}
return reinterpret_cast<char*>(ptr);
}
@@ -80,12 +54,12 @@ void PutVarint32(std::string* dst, uint32_t v) {
char* EncodeVarint64(char* dst, uint64_t v) {
static const int B = 128;
- unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(dst);
while (v >= B) {
- *(ptr++) = (v & (B-1)) | B;
+ *(ptr++) = v | B;
v >>= 7;
}
- *(ptr++) = static_cast<unsigned char>(v);
+ *(ptr++) = static_cast<uint8_t>(v);
return reinterpret_cast<char*>(ptr);
}
@@ -109,12 +83,11 @@ int VarintLength(uint64_t v) {
return len;
}
-const char* GetVarint32PtrFallback(const char* p,
- const char* limit,
+const char* GetVarint32PtrFallback(const char* p, const char* limit,
uint32_t* value) {
uint32_t result = 0;
for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) {
- uint32_t byte = *(reinterpret_cast<const unsigned char*>(p));
+ uint32_t byte = *(reinterpret_cast<const uint8_t*>(p));
p++;
if (byte & 128) {
// More bytes are present
@@ -125,14 +98,14 @@ const char* GetVarint32PtrFallback(const char* p,
return reinterpret_cast<const char*>(p);
}
}
- return NULL;
+ return nullptr;
}
bool GetVarint32(Slice* input, uint32_t* value) {
const char* p = input->data();
const char* limit = p + input->size();
const char* q = GetVarint32Ptr(p, limit, value);
- if (q == NULL) {
+ if (q == nullptr) {
return false;
} else {
*input = Slice(q, limit - q);
@@ -143,7 +116,7 @@ bool GetVarint32(Slice* input, uint32_t* value) {
const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) {
uint64_t result = 0;
for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) {
- uint64_t byte = *(reinterpret_cast<const unsigned char*>(p));
+ uint64_t byte = *(reinterpret_cast<const uint8_t*>(p));
p++;
if (byte & 128) {
// More bytes are present
@@ -154,14 +127,14 @@ const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) {
return reinterpret_cast<const char*>(p);
}
}
- return NULL;
+ return nullptr;
}
bool GetVarint64(Slice* input, uint64_t* value) {
const char* p = input->data();
const char* limit = p + input->size();
const char* q = GetVarint64Ptr(p, limit, value);
- if (q == NULL) {
+ if (q == nullptr) {
return false;
} else {
*input = Slice(q, limit - q);
@@ -173,16 +146,15 @@ const char* GetLengthPrefixedSlice(const char* p, const char* limit,
Slice* result) {
uint32_t len;
p = GetVarint32Ptr(p, limit, &len);
- if (p == NULL) return NULL;
- if (p + len > limit) return NULL;
+ if (p == nullptr) return nullptr;
+ if (p + len > limit) return nullptr;
*result = Slice(p, len);
return p + len;
}
bool GetLengthPrefixedSlice(Slice* input, Slice* result) {
uint32_t len;
- if (GetVarint32(input, &len) &&
- input->size() >= len) {
+ if (GetVarint32(input, &len) && input->size() >= len) {
*result = Slice(input->data(), len);
input->remove_prefix(len);
return true;
diff --git a/src/leveldb/util/coding.h b/src/leveldb/util/coding.h
index 3993c4a755..1983ae7173 100644
--- a/src/leveldb/util/coding.h
+++ b/src/leveldb/util/coding.h
@@ -10,87 +10,147 @@
#ifndef STORAGE_LEVELDB_UTIL_CODING_H_
#define STORAGE_LEVELDB_UTIL_CODING_H_
-#include <stdint.h>
-#include <string.h>
+#include <cstdint>
+#include <cstring>
#include <string>
+
#include "leveldb/slice.h"
#include "port/port.h"
namespace leveldb {
// Standard Put... routines append to a string
-extern void PutFixed32(std::string* dst, uint32_t value);
-extern void PutFixed64(std::string* dst, uint64_t value);
-extern void PutVarint32(std::string* dst, uint32_t value);
-extern void PutVarint64(std::string* dst, uint64_t value);
-extern void PutLengthPrefixedSlice(std::string* dst, const Slice& value);
+void PutFixed32(std::string* dst, uint32_t value);
+void PutFixed64(std::string* dst, uint64_t value);
+void PutVarint32(std::string* dst, uint32_t value);
+void PutVarint64(std::string* dst, uint64_t value);
+void PutLengthPrefixedSlice(std::string* dst, const Slice& value);
// Standard Get... routines parse a value from the beginning of a Slice
// and advance the slice past the parsed value.
-extern bool GetVarint32(Slice* input, uint32_t* value);
-extern bool GetVarint64(Slice* input, uint64_t* value);
-extern bool GetLengthPrefixedSlice(Slice* input, Slice* result);
+bool GetVarint32(Slice* input, uint32_t* value);
+bool GetVarint64(Slice* input, uint64_t* value);
+bool GetLengthPrefixedSlice(Slice* input, Slice* result);
// Pointer-based variants of GetVarint... These either store a value
// in *v and return a pointer just past the parsed value, or return
-// NULL on error. These routines only look at bytes in the range
+// nullptr on error. These routines only look at bytes in the range
// [p..limit-1]
-extern const char* GetVarint32Ptr(const char* p,const char* limit, uint32_t* v);
-extern const char* GetVarint64Ptr(const char* p,const char* limit, uint64_t* v);
+const char* GetVarint32Ptr(const char* p, const char* limit, uint32_t* v);
+const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* v);
// Returns the length of the varint32 or varint64 encoding of "v"
-extern int VarintLength(uint64_t v);
+int VarintLength(uint64_t v);
// Lower-level versions of Put... that write directly into a character buffer
+// and return a pointer just past the last byte written.
// REQUIRES: dst has enough space for the value being written
-extern void EncodeFixed32(char* dst, uint32_t value);
-extern void EncodeFixed64(char* dst, uint64_t value);
+char* EncodeVarint32(char* dst, uint32_t value);
+char* EncodeVarint64(char* dst, uint64_t value);
+
+// TODO(costan): Remove port::kLittleEndian and the fast paths based on
+// std::memcpy when clang learns to optimize the generic code, as
+// described in https://bugs.llvm.org/show_bug.cgi?id=41761
+//
+// The platform-independent code in DecodeFixed{32,64}() gets optimized to mov
+// on x86 and ldr on ARM64, by both clang and gcc. However, only gcc optimizes
+// the platform-independent code in EncodeFixed{32,64}() to mov / str.
// Lower-level versions of Put... that write directly into a character buffer
-// and return a pointer just past the last byte written.
// REQUIRES: dst has enough space for the value being written
-extern char* EncodeVarint32(char* dst, uint32_t value);
-extern char* EncodeVarint64(char* dst, uint64_t value);
+
+inline void EncodeFixed32(char* dst, uint32_t value) {
+ uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst);
+
+ if (port::kLittleEndian) {
+ // Fast path for little-endian CPUs. All major compilers optimize this to a
+ // single mov (x86_64) / str (ARM) instruction.
+ std::memcpy(buffer, &value, sizeof(uint32_t));
+ return;
+ }
+
+ // Platform-independent code.
+ // Currently, only gcc optimizes this to a single mov / str instruction.
+ buffer[0] = static_cast<uint8_t>(value);
+ buffer[1] = static_cast<uint8_t>(value >> 8);
+ buffer[2] = static_cast<uint8_t>(value >> 16);
+ buffer[3] = static_cast<uint8_t>(value >> 24);
+}
+
+inline void EncodeFixed64(char* dst, uint64_t value) {
+ uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst);
+
+ if (port::kLittleEndian) {
+ // Fast path for little-endian CPUs. All major compilers optimize this to a
+ // single mov (x86_64) / str (ARM) instruction.
+ std::memcpy(buffer, &value, sizeof(uint64_t));
+ return;
+ }
+
+ // Platform-independent code.
+ // Currently, only gcc optimizes this to a single mov / str instruction.
+ buffer[0] = static_cast<uint8_t>(value);
+ buffer[1] = static_cast<uint8_t>(value >> 8);
+ buffer[2] = static_cast<uint8_t>(value >> 16);
+ buffer[3] = static_cast<uint8_t>(value >> 24);
+ buffer[4] = static_cast<uint8_t>(value >> 32);
+ buffer[5] = static_cast<uint8_t>(value >> 40);
+ buffer[6] = static_cast<uint8_t>(value >> 48);
+ buffer[7] = static_cast<uint8_t>(value >> 56);
+}
// Lower-level versions of Get... that read directly from a character buffer
// without any bounds checking.
inline uint32_t DecodeFixed32(const char* ptr) {
+ const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr);
+
if (port::kLittleEndian) {
- // Load the raw bytes
+ // Fast path for little-endian CPUs. All major compilers optimize this to a
+ // single mov (x86_64) / ldr (ARM) instruction.
uint32_t result;
- memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load
+ std::memcpy(&result, buffer, sizeof(uint32_t));
return result;
- } else {
- return ((static_cast<uint32_t>(static_cast<unsigned char>(ptr[0])))
- | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[1])) << 8)
- | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[2])) << 16)
- | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[3])) << 24));
}
+
+ // Platform-independent code.
+ // Clang and gcc optimize this to a single mov / ldr instruction.
+ return (static_cast<uint32_t>(buffer[0])) |
+ (static_cast<uint32_t>(buffer[1]) << 8) |
+ (static_cast<uint32_t>(buffer[2]) << 16) |
+ (static_cast<uint32_t>(buffer[3]) << 24);
}
inline uint64_t DecodeFixed64(const char* ptr) {
+ const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr);
+
if (port::kLittleEndian) {
- // Load the raw bytes
+ // Fast path for little-endian CPUs. All major compilers optimize this to a
+ // single mov (x86_64) / ldr (ARM) instruction.
uint64_t result;
- memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load
+ std::memcpy(&result, buffer, sizeof(uint64_t));
return result;
- } else {
- uint64_t lo = DecodeFixed32(ptr);
- uint64_t hi = DecodeFixed32(ptr + 4);
- return (hi << 32) | lo;
}
+
+ // Platform-independent code.
+ // Clang and gcc optimize this to a single mov / ldr instruction.
+ return (static_cast<uint64_t>(buffer[0])) |
+ (static_cast<uint64_t>(buffer[1]) << 8) |
+ (static_cast<uint64_t>(buffer[2]) << 16) |
+ (static_cast<uint64_t>(buffer[3]) << 24) |
+ (static_cast<uint64_t>(buffer[4]) << 32) |
+ (static_cast<uint64_t>(buffer[5]) << 40) |
+ (static_cast<uint64_t>(buffer[6]) << 48) |
+ (static_cast<uint64_t>(buffer[7]) << 56);
}
// Internal routine for use by fallback path of GetVarint32Ptr
-extern const char* GetVarint32PtrFallback(const char* p,
- const char* limit,
- uint32_t* value);
-inline const char* GetVarint32Ptr(const char* p,
- const char* limit,
+const char* GetVarint32PtrFallback(const char* p, const char* limit,
+ uint32_t* value);
+inline const char* GetVarint32Ptr(const char* p, const char* limit,
uint32_t* value) {
if (p < limit) {
- uint32_t result = *(reinterpret_cast<const unsigned char*>(p));
+ uint32_t result = *(reinterpret_cast<const uint8_t*>(p));
if ((result & 128) == 0) {
*value = result;
return p + 1;
diff --git a/src/leveldb/util/coding_test.cc b/src/leveldb/util/coding_test.cc
index 521541ea61..0d2a0c51f6 100644
--- a/src/leveldb/util/coding_test.cc
+++ b/src/leveldb/util/coding_test.cc
@@ -2,13 +2,14 @@
// 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.
-#include "util/coding.h"
+#include <vector>
+#include "util/coding.h"
#include "util/testharness.h"
namespace leveldb {
-class Coding { };
+class Coding {};
TEST(Coding, Fixed32) {
std::string s;
@@ -38,15 +39,15 @@ TEST(Coding, Fixed64) {
uint64_t v = static_cast<uint64_t>(1) << power;
uint64_t actual;
actual = DecodeFixed64(p);
- ASSERT_EQ(v-1, actual);
+ ASSERT_EQ(v - 1, actual);
p += sizeof(uint64_t);
actual = DecodeFixed64(p);
- ASSERT_EQ(v+0, actual);
+ ASSERT_EQ(v + 0, actual);
p += sizeof(uint64_t);
actual = DecodeFixed64(p);
- ASSERT_EQ(v+1, actual);
+ ASSERT_EQ(v + 1, actual);
p += sizeof(uint64_t);
}
}
@@ -88,7 +89,7 @@ TEST(Coding, Varint32) {
uint32_t actual;
const char* start = p;
p = GetVarint32Ptr(p, limit, &actual);
- ASSERT_TRUE(p != NULL);
+ ASSERT_TRUE(p != nullptr);
ASSERT_EQ(expected, actual);
ASSERT_EQ(VarintLength(actual), p - start);
}
@@ -107,8 +108,8 @@ TEST(Coding, Varint64) {
// Test values near powers of two
const uint64_t power = 1ull << k;
values.push_back(power);
- values.push_back(power-1);
- values.push_back(power+1);
+ values.push_back(power - 1);
+ values.push_back(power + 1);
}
std::string s;
@@ -123,19 +124,18 @@ TEST(Coding, Varint64) {
uint64_t actual;
const char* start = p;
p = GetVarint64Ptr(p, limit, &actual);
- ASSERT_TRUE(p != NULL);
+ ASSERT_TRUE(p != nullptr);
ASSERT_EQ(values[i], actual);
ASSERT_EQ(VarintLength(actual), p - start);
}
ASSERT_EQ(p, limit);
-
}
TEST(Coding, Varint32Overflow) {
uint32_t result;
std::string input("\x81\x82\x83\x84\x85\x11");
- ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(), &result)
- == NULL);
+ ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(),
+ &result) == nullptr);
}
TEST(Coding, Varint32Truncation) {
@@ -144,17 +144,18 @@ TEST(Coding, Varint32Truncation) {
PutVarint32(&s, large_value);
uint32_t result;
for (size_t len = 0; len < s.size() - 1; len++) {
- ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == NULL);
+ ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == nullptr);
}
- ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) != NULL);
+ ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) !=
+ nullptr);
ASSERT_EQ(large_value, result);
}
TEST(Coding, Varint64Overflow) {
uint64_t result;
std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11");
- ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(), &result)
- == NULL);
+ ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(),
+ &result) == nullptr);
}
TEST(Coding, Varint64Truncation) {
@@ -163,9 +164,10 @@ TEST(Coding, Varint64Truncation) {
PutVarint64(&s, large_value);
uint64_t result;
for (size_t len = 0; len < s.size() - 1; len++) {
- ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == NULL);
+ ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == nullptr);
}
- ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) != NULL);
+ ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) !=
+ nullptr);
ASSERT_EQ(large_value, result);
}
@@ -191,6 +193,4 @@ TEST(Coding, Strings) {
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/comparator.cc b/src/leveldb/util/comparator.cc
index 4b7b5724ef..c5766e9462 100644
--- a/src/leveldb/util/comparator.cc
+++ b/src/leveldb/util/comparator.cc
@@ -2,33 +2,34 @@
// 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.
-#include <algorithm>
-#include <stdint.h>
#include "leveldb/comparator.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <string>
+#include <type_traits>
+
#include "leveldb/slice.h"
-#include "port/port.h"
#include "util/logging.h"
+#include "util/no_destructor.h"
namespace leveldb {
-Comparator::~Comparator() { }
+Comparator::~Comparator() = default;
namespace {
class BytewiseComparatorImpl : public Comparator {
public:
- BytewiseComparatorImpl() { }
+ BytewiseComparatorImpl() = default;
- virtual const char* Name() const {
- return "leveldb.BytewiseComparator";
- }
+ const char* Name() const override { return "leveldb.BytewiseComparator"; }
- virtual int Compare(const Slice& a, const Slice& b) const {
+ int Compare(const Slice& a, const Slice& b) const override {
return a.compare(b);
}
- virtual void FindShortestSeparator(
- std::string* start,
- const Slice& limit) const {
+ void FindShortestSeparator(std::string* start,
+ const Slice& limit) const override {
// Find length of common prefix
size_t min_length = std::min(start->size(), limit.size());
size_t diff_index = 0;
@@ -50,14 +51,14 @@ class BytewiseComparatorImpl : public Comparator {
}
}
- virtual void FindShortSuccessor(std::string* key) const {
+ void FindShortSuccessor(std::string* key) const override {
// Find first character that can be incremented
size_t n = key->size();
for (size_t i = 0; i < n; i++) {
const uint8_t byte = (*key)[i];
if (byte != static_cast<uint8_t>(0xff)) {
(*key)[i] = byte + 1;
- key->resize(i+1);
+ key->resize(i + 1);
return;
}
}
@@ -66,16 +67,9 @@ class BytewiseComparatorImpl : public Comparator {
};
} // namespace
-static port::OnceType once = LEVELDB_ONCE_INIT;
-static const Comparator* bytewise;
-
-static void InitModule() {
- bytewise = new BytewiseComparatorImpl;
-}
-
const Comparator* BytewiseComparator() {
- port::InitOnce(&once, InitModule);
- return bytewise;
+ static NoDestructor<BytewiseComparatorImpl> singleton;
+ return singleton.get();
}
} // namespace leveldb
diff --git a/src/leveldb/util/crc32c.cc b/src/leveldb/util/crc32c.cc
index b3f40eeeed..c2e61f7dba 100644
--- a/src/leveldb/util/crc32c.cc
+++ b/src/leveldb/util/crc32c.cc
@@ -2,11 +2,11 @@
// 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.
//
-// A portable implementation of crc32c, optimized to handle
-// four bytes at a time.
+// A portable implementation of crc32c.
#include "util/crc32c.h"
+#include <stddef.h>
#include <stdint.h>
#include "port/port.h"
@@ -15,283 +15,256 @@
namespace leveldb {
namespace crc32c {
-static const uint32_t table0_[256] = {
- 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
- 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
- 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
- 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
- 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
- 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
- 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
- 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
- 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
- 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
- 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
- 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
- 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
- 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
- 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
- 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
- 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
- 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
- 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
- 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
- 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
- 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
- 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
- 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
- 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
- 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
- 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
- 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
- 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
- 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
- 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
- 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
- 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
- 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
- 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
- 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
- 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
- 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
- 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
- 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
- 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
- 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
- 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
- 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
- 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
- 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
- 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
- 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
- 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
- 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
- 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
- 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
- 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
- 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
- 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
- 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
- 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
- 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
- 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
- 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
- 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
- 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
- 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
- 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351
-};
-static const uint32_t table1_[256] = {
- 0x00000000, 0x13a29877, 0x274530ee, 0x34e7a899,
- 0x4e8a61dc, 0x5d28f9ab, 0x69cf5132, 0x7a6dc945,
- 0x9d14c3b8, 0x8eb65bcf, 0xba51f356, 0xa9f36b21,
- 0xd39ea264, 0xc03c3a13, 0xf4db928a, 0xe7790afd,
- 0x3fc5f181, 0x2c6769f6, 0x1880c16f, 0x0b225918,
- 0x714f905d, 0x62ed082a, 0x560aa0b3, 0x45a838c4,
- 0xa2d13239, 0xb173aa4e, 0x859402d7, 0x96369aa0,
- 0xec5b53e5, 0xfff9cb92, 0xcb1e630b, 0xd8bcfb7c,
- 0x7f8be302, 0x6c297b75, 0x58ced3ec, 0x4b6c4b9b,
- 0x310182de, 0x22a31aa9, 0x1644b230, 0x05e62a47,
- 0xe29f20ba, 0xf13db8cd, 0xc5da1054, 0xd6788823,
- 0xac154166, 0xbfb7d911, 0x8b507188, 0x98f2e9ff,
- 0x404e1283, 0x53ec8af4, 0x670b226d, 0x74a9ba1a,
- 0x0ec4735f, 0x1d66eb28, 0x298143b1, 0x3a23dbc6,
- 0xdd5ad13b, 0xcef8494c, 0xfa1fe1d5, 0xe9bd79a2,
- 0x93d0b0e7, 0x80722890, 0xb4958009, 0xa737187e,
- 0xff17c604, 0xecb55e73, 0xd852f6ea, 0xcbf06e9d,
- 0xb19da7d8, 0xa23f3faf, 0x96d89736, 0x857a0f41,
- 0x620305bc, 0x71a19dcb, 0x45463552, 0x56e4ad25,
- 0x2c896460, 0x3f2bfc17, 0x0bcc548e, 0x186eccf9,
- 0xc0d23785, 0xd370aff2, 0xe797076b, 0xf4359f1c,
- 0x8e585659, 0x9dface2e, 0xa91d66b7, 0xbabffec0,
- 0x5dc6f43d, 0x4e646c4a, 0x7a83c4d3, 0x69215ca4,
- 0x134c95e1, 0x00ee0d96, 0x3409a50f, 0x27ab3d78,
- 0x809c2506, 0x933ebd71, 0xa7d915e8, 0xb47b8d9f,
- 0xce1644da, 0xddb4dcad, 0xe9537434, 0xfaf1ec43,
- 0x1d88e6be, 0x0e2a7ec9, 0x3acdd650, 0x296f4e27,
- 0x53028762, 0x40a01f15, 0x7447b78c, 0x67e52ffb,
- 0xbf59d487, 0xacfb4cf0, 0x981ce469, 0x8bbe7c1e,
- 0xf1d3b55b, 0xe2712d2c, 0xd69685b5, 0xc5341dc2,
- 0x224d173f, 0x31ef8f48, 0x050827d1, 0x16aabfa6,
- 0x6cc776e3, 0x7f65ee94, 0x4b82460d, 0x5820de7a,
- 0xfbc3faf9, 0xe861628e, 0xdc86ca17, 0xcf245260,
- 0xb5499b25, 0xa6eb0352, 0x920cabcb, 0x81ae33bc,
- 0x66d73941, 0x7575a136, 0x419209af, 0x523091d8,
- 0x285d589d, 0x3bffc0ea, 0x0f186873, 0x1cbaf004,
- 0xc4060b78, 0xd7a4930f, 0xe3433b96, 0xf0e1a3e1,
- 0x8a8c6aa4, 0x992ef2d3, 0xadc95a4a, 0xbe6bc23d,
- 0x5912c8c0, 0x4ab050b7, 0x7e57f82e, 0x6df56059,
- 0x1798a91c, 0x043a316b, 0x30dd99f2, 0x237f0185,
- 0x844819fb, 0x97ea818c, 0xa30d2915, 0xb0afb162,
- 0xcac27827, 0xd960e050, 0xed8748c9, 0xfe25d0be,
- 0x195cda43, 0x0afe4234, 0x3e19eaad, 0x2dbb72da,
- 0x57d6bb9f, 0x447423e8, 0x70938b71, 0x63311306,
- 0xbb8de87a, 0xa82f700d, 0x9cc8d894, 0x8f6a40e3,
- 0xf50789a6, 0xe6a511d1, 0xd242b948, 0xc1e0213f,
- 0x26992bc2, 0x353bb3b5, 0x01dc1b2c, 0x127e835b,
- 0x68134a1e, 0x7bb1d269, 0x4f567af0, 0x5cf4e287,
- 0x04d43cfd, 0x1776a48a, 0x23910c13, 0x30339464,
- 0x4a5e5d21, 0x59fcc556, 0x6d1b6dcf, 0x7eb9f5b8,
- 0x99c0ff45, 0x8a626732, 0xbe85cfab, 0xad2757dc,
- 0xd74a9e99, 0xc4e806ee, 0xf00fae77, 0xe3ad3600,
- 0x3b11cd7c, 0x28b3550b, 0x1c54fd92, 0x0ff665e5,
- 0x759baca0, 0x663934d7, 0x52de9c4e, 0x417c0439,
- 0xa6050ec4, 0xb5a796b3, 0x81403e2a, 0x92e2a65d,
- 0xe88f6f18, 0xfb2df76f, 0xcfca5ff6, 0xdc68c781,
- 0x7b5fdfff, 0x68fd4788, 0x5c1aef11, 0x4fb87766,
- 0x35d5be23, 0x26772654, 0x12908ecd, 0x013216ba,
- 0xe64b1c47, 0xf5e98430, 0xc10e2ca9, 0xd2acb4de,
- 0xa8c17d9b, 0xbb63e5ec, 0x8f844d75, 0x9c26d502,
- 0x449a2e7e, 0x5738b609, 0x63df1e90, 0x707d86e7,
- 0x0a104fa2, 0x19b2d7d5, 0x2d557f4c, 0x3ef7e73b,
- 0xd98eedc6, 0xca2c75b1, 0xfecbdd28, 0xed69455f,
- 0x97048c1a, 0x84a6146d, 0xb041bcf4, 0xa3e32483
-};
-static const uint32_t table2_[256] = {
- 0x00000000, 0xa541927e, 0x4f6f520d, 0xea2ec073,
- 0x9edea41a, 0x3b9f3664, 0xd1b1f617, 0x74f06469,
- 0x38513ec5, 0x9d10acbb, 0x773e6cc8, 0xd27ffeb6,
- 0xa68f9adf, 0x03ce08a1, 0xe9e0c8d2, 0x4ca15aac,
- 0x70a27d8a, 0xd5e3eff4, 0x3fcd2f87, 0x9a8cbdf9,
- 0xee7cd990, 0x4b3d4bee, 0xa1138b9d, 0x045219e3,
- 0x48f3434f, 0xedb2d131, 0x079c1142, 0xa2dd833c,
- 0xd62de755, 0x736c752b, 0x9942b558, 0x3c032726,
- 0xe144fb14, 0x4405696a, 0xae2ba919, 0x0b6a3b67,
- 0x7f9a5f0e, 0xdadbcd70, 0x30f50d03, 0x95b49f7d,
- 0xd915c5d1, 0x7c5457af, 0x967a97dc, 0x333b05a2,
- 0x47cb61cb, 0xe28af3b5, 0x08a433c6, 0xade5a1b8,
- 0x91e6869e, 0x34a714e0, 0xde89d493, 0x7bc846ed,
- 0x0f382284, 0xaa79b0fa, 0x40577089, 0xe516e2f7,
- 0xa9b7b85b, 0x0cf62a25, 0xe6d8ea56, 0x43997828,
- 0x37691c41, 0x92288e3f, 0x78064e4c, 0xdd47dc32,
- 0xc76580d9, 0x622412a7, 0x880ad2d4, 0x2d4b40aa,
- 0x59bb24c3, 0xfcfab6bd, 0x16d476ce, 0xb395e4b0,
- 0xff34be1c, 0x5a752c62, 0xb05bec11, 0x151a7e6f,
- 0x61ea1a06, 0xc4ab8878, 0x2e85480b, 0x8bc4da75,
- 0xb7c7fd53, 0x12866f2d, 0xf8a8af5e, 0x5de93d20,
- 0x29195949, 0x8c58cb37, 0x66760b44, 0xc337993a,
- 0x8f96c396, 0x2ad751e8, 0xc0f9919b, 0x65b803e5,
- 0x1148678c, 0xb409f5f2, 0x5e273581, 0xfb66a7ff,
- 0x26217bcd, 0x8360e9b3, 0x694e29c0, 0xcc0fbbbe,
- 0xb8ffdfd7, 0x1dbe4da9, 0xf7908dda, 0x52d11fa4,
- 0x1e704508, 0xbb31d776, 0x511f1705, 0xf45e857b,
- 0x80aee112, 0x25ef736c, 0xcfc1b31f, 0x6a802161,
- 0x56830647, 0xf3c29439, 0x19ec544a, 0xbcadc634,
- 0xc85da25d, 0x6d1c3023, 0x8732f050, 0x2273622e,
- 0x6ed23882, 0xcb93aafc, 0x21bd6a8f, 0x84fcf8f1,
- 0xf00c9c98, 0x554d0ee6, 0xbf63ce95, 0x1a225ceb,
- 0x8b277743, 0x2e66e53d, 0xc448254e, 0x6109b730,
- 0x15f9d359, 0xb0b84127, 0x5a968154, 0xffd7132a,
- 0xb3764986, 0x1637dbf8, 0xfc191b8b, 0x595889f5,
- 0x2da8ed9c, 0x88e97fe2, 0x62c7bf91, 0xc7862def,
- 0xfb850ac9, 0x5ec498b7, 0xb4ea58c4, 0x11abcaba,
- 0x655baed3, 0xc01a3cad, 0x2a34fcde, 0x8f756ea0,
- 0xc3d4340c, 0x6695a672, 0x8cbb6601, 0x29faf47f,
- 0x5d0a9016, 0xf84b0268, 0x1265c21b, 0xb7245065,
- 0x6a638c57, 0xcf221e29, 0x250cde5a, 0x804d4c24,
- 0xf4bd284d, 0x51fcba33, 0xbbd27a40, 0x1e93e83e,
- 0x5232b292, 0xf77320ec, 0x1d5de09f, 0xb81c72e1,
- 0xccec1688, 0x69ad84f6, 0x83834485, 0x26c2d6fb,
- 0x1ac1f1dd, 0xbf8063a3, 0x55aea3d0, 0xf0ef31ae,
- 0x841f55c7, 0x215ec7b9, 0xcb7007ca, 0x6e3195b4,
- 0x2290cf18, 0x87d15d66, 0x6dff9d15, 0xc8be0f6b,
- 0xbc4e6b02, 0x190ff97c, 0xf321390f, 0x5660ab71,
- 0x4c42f79a, 0xe90365e4, 0x032da597, 0xa66c37e9,
- 0xd29c5380, 0x77ddc1fe, 0x9df3018d, 0x38b293f3,
- 0x7413c95f, 0xd1525b21, 0x3b7c9b52, 0x9e3d092c,
- 0xeacd6d45, 0x4f8cff3b, 0xa5a23f48, 0x00e3ad36,
- 0x3ce08a10, 0x99a1186e, 0x738fd81d, 0xd6ce4a63,
- 0xa23e2e0a, 0x077fbc74, 0xed517c07, 0x4810ee79,
- 0x04b1b4d5, 0xa1f026ab, 0x4bdee6d8, 0xee9f74a6,
- 0x9a6f10cf, 0x3f2e82b1, 0xd50042c2, 0x7041d0bc,
- 0xad060c8e, 0x08479ef0, 0xe2695e83, 0x4728ccfd,
- 0x33d8a894, 0x96993aea, 0x7cb7fa99, 0xd9f668e7,
- 0x9557324b, 0x3016a035, 0xda386046, 0x7f79f238,
- 0x0b899651, 0xaec8042f, 0x44e6c45c, 0xe1a75622,
- 0xdda47104, 0x78e5e37a, 0x92cb2309, 0x378ab177,
- 0x437ad51e, 0xe63b4760, 0x0c158713, 0xa954156d,
- 0xe5f54fc1, 0x40b4ddbf, 0xaa9a1dcc, 0x0fdb8fb2,
- 0x7b2bebdb, 0xde6a79a5, 0x3444b9d6, 0x91052ba8
-};
-static const uint32_t table3_[256] = {
- 0x00000000, 0xdd45aab8, 0xbf672381, 0x62228939,
- 0x7b2231f3, 0xa6679b4b, 0xc4451272, 0x1900b8ca,
- 0xf64463e6, 0x2b01c95e, 0x49234067, 0x9466eadf,
- 0x8d665215, 0x5023f8ad, 0x32017194, 0xef44db2c,
- 0xe964b13d, 0x34211b85, 0x560392bc, 0x8b463804,
- 0x924680ce, 0x4f032a76, 0x2d21a34f, 0xf06409f7,
- 0x1f20d2db, 0xc2657863, 0xa047f15a, 0x7d025be2,
- 0x6402e328, 0xb9474990, 0xdb65c0a9, 0x06206a11,
- 0xd725148b, 0x0a60be33, 0x6842370a, 0xb5079db2,
- 0xac072578, 0x71428fc0, 0x136006f9, 0xce25ac41,
- 0x2161776d, 0xfc24ddd5, 0x9e0654ec, 0x4343fe54,
- 0x5a43469e, 0x8706ec26, 0xe524651f, 0x3861cfa7,
- 0x3e41a5b6, 0xe3040f0e, 0x81268637, 0x5c632c8f,
- 0x45639445, 0x98263efd, 0xfa04b7c4, 0x27411d7c,
- 0xc805c650, 0x15406ce8, 0x7762e5d1, 0xaa274f69,
- 0xb327f7a3, 0x6e625d1b, 0x0c40d422, 0xd1057e9a,
- 0xaba65fe7, 0x76e3f55f, 0x14c17c66, 0xc984d6de,
- 0xd0846e14, 0x0dc1c4ac, 0x6fe34d95, 0xb2a6e72d,
- 0x5de23c01, 0x80a796b9, 0xe2851f80, 0x3fc0b538,
- 0x26c00df2, 0xfb85a74a, 0x99a72e73, 0x44e284cb,
- 0x42c2eeda, 0x9f874462, 0xfda5cd5b, 0x20e067e3,
- 0x39e0df29, 0xe4a57591, 0x8687fca8, 0x5bc25610,
- 0xb4868d3c, 0x69c32784, 0x0be1aebd, 0xd6a40405,
- 0xcfa4bccf, 0x12e11677, 0x70c39f4e, 0xad8635f6,
- 0x7c834b6c, 0xa1c6e1d4, 0xc3e468ed, 0x1ea1c255,
- 0x07a17a9f, 0xdae4d027, 0xb8c6591e, 0x6583f3a6,
- 0x8ac7288a, 0x57828232, 0x35a00b0b, 0xe8e5a1b3,
- 0xf1e51979, 0x2ca0b3c1, 0x4e823af8, 0x93c79040,
- 0x95e7fa51, 0x48a250e9, 0x2a80d9d0, 0xf7c57368,
- 0xeec5cba2, 0x3380611a, 0x51a2e823, 0x8ce7429b,
- 0x63a399b7, 0xbee6330f, 0xdcc4ba36, 0x0181108e,
- 0x1881a844, 0xc5c402fc, 0xa7e68bc5, 0x7aa3217d,
- 0x52a0c93f, 0x8fe56387, 0xedc7eabe, 0x30824006,
- 0x2982f8cc, 0xf4c75274, 0x96e5db4d, 0x4ba071f5,
- 0xa4e4aad9, 0x79a10061, 0x1b838958, 0xc6c623e0,
- 0xdfc69b2a, 0x02833192, 0x60a1b8ab, 0xbde41213,
- 0xbbc47802, 0x6681d2ba, 0x04a35b83, 0xd9e6f13b,
- 0xc0e649f1, 0x1da3e349, 0x7f816a70, 0xa2c4c0c8,
- 0x4d801be4, 0x90c5b15c, 0xf2e73865, 0x2fa292dd,
- 0x36a22a17, 0xebe780af, 0x89c50996, 0x5480a32e,
- 0x8585ddb4, 0x58c0770c, 0x3ae2fe35, 0xe7a7548d,
- 0xfea7ec47, 0x23e246ff, 0x41c0cfc6, 0x9c85657e,
- 0x73c1be52, 0xae8414ea, 0xcca69dd3, 0x11e3376b,
- 0x08e38fa1, 0xd5a62519, 0xb784ac20, 0x6ac10698,
- 0x6ce16c89, 0xb1a4c631, 0xd3864f08, 0x0ec3e5b0,
- 0x17c35d7a, 0xca86f7c2, 0xa8a47efb, 0x75e1d443,
- 0x9aa50f6f, 0x47e0a5d7, 0x25c22cee, 0xf8878656,
- 0xe1873e9c, 0x3cc29424, 0x5ee01d1d, 0x83a5b7a5,
- 0xf90696d8, 0x24433c60, 0x4661b559, 0x9b241fe1,
- 0x8224a72b, 0x5f610d93, 0x3d4384aa, 0xe0062e12,
- 0x0f42f53e, 0xd2075f86, 0xb025d6bf, 0x6d607c07,
- 0x7460c4cd, 0xa9256e75, 0xcb07e74c, 0x16424df4,
- 0x106227e5, 0xcd278d5d, 0xaf050464, 0x7240aedc,
- 0x6b401616, 0xb605bcae, 0xd4273597, 0x09629f2f,
- 0xe6264403, 0x3b63eebb, 0x59416782, 0x8404cd3a,
- 0x9d0475f0, 0x4041df48, 0x22635671, 0xff26fcc9,
- 0x2e238253, 0xf36628eb, 0x9144a1d2, 0x4c010b6a,
- 0x5501b3a0, 0x88441918, 0xea669021, 0x37233a99,
- 0xd867e1b5, 0x05224b0d, 0x6700c234, 0xba45688c,
- 0xa345d046, 0x7e007afe, 0x1c22f3c7, 0xc167597f,
- 0xc747336e, 0x1a0299d6, 0x782010ef, 0xa565ba57,
- 0xbc65029d, 0x6120a825, 0x0302211c, 0xde478ba4,
- 0x31035088, 0xec46fa30, 0x8e647309, 0x5321d9b1,
- 0x4a21617b, 0x9764cbc3, 0xf54642fa, 0x2803e842
-};
+namespace {
-// Used to fetch a naturally-aligned 32-bit word in little endian byte-order
-static inline uint32_t LE_LOAD32(const uint8_t *p) {
- return DecodeFixed32(reinterpret_cast<const char*>(p));
+const uint32_t kByteExtensionTable[256] = {
+ 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c,
+ 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
+ 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c,
+ 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
+ 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc,
+ 0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
+ 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512,
+ 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
+ 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad,
+ 0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
+ 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf,
+ 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
+ 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f,
+ 0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
+ 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f,
+ 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
+ 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e,
+ 0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
+ 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e,
+ 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
+ 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de,
+ 0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
+ 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4,
+ 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
+ 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b,
+ 0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
+ 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5,
+ 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
+ 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975,
+ 0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
+ 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905,
+ 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
+ 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8,
+ 0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
+ 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8,
+ 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
+ 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78,
+ 0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
+ 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6,
+ 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
+ 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69,
+ 0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
+ 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351};
+
+const uint32_t kStrideExtensionTable0[256] = {
+ 0x00000000, 0x30d23865, 0x61a470ca, 0x517648af, 0xc348e194, 0xf39ad9f1,
+ 0xa2ec915e, 0x923ea93b, 0x837db5d9, 0xb3af8dbc, 0xe2d9c513, 0xd20bfd76,
+ 0x4035544d, 0x70e76c28, 0x21912487, 0x11431ce2, 0x03171d43, 0x33c52526,
+ 0x62b36d89, 0x526155ec, 0xc05ffcd7, 0xf08dc4b2, 0xa1fb8c1d, 0x9129b478,
+ 0x806aa89a, 0xb0b890ff, 0xe1ced850, 0xd11ce035, 0x4322490e, 0x73f0716b,
+ 0x228639c4, 0x125401a1, 0x062e3a86, 0x36fc02e3, 0x678a4a4c, 0x57587229,
+ 0xc566db12, 0xf5b4e377, 0xa4c2abd8, 0x941093bd, 0x85538f5f, 0xb581b73a,
+ 0xe4f7ff95, 0xd425c7f0, 0x461b6ecb, 0x76c956ae, 0x27bf1e01, 0x176d2664,
+ 0x053927c5, 0x35eb1fa0, 0x649d570f, 0x544f6f6a, 0xc671c651, 0xf6a3fe34,
+ 0xa7d5b69b, 0x97078efe, 0x8644921c, 0xb696aa79, 0xe7e0e2d6, 0xd732dab3,
+ 0x450c7388, 0x75de4bed, 0x24a80342, 0x147a3b27, 0x0c5c750c, 0x3c8e4d69,
+ 0x6df805c6, 0x5d2a3da3, 0xcf149498, 0xffc6acfd, 0xaeb0e452, 0x9e62dc37,
+ 0x8f21c0d5, 0xbff3f8b0, 0xee85b01f, 0xde57887a, 0x4c692141, 0x7cbb1924,
+ 0x2dcd518b, 0x1d1f69ee, 0x0f4b684f, 0x3f99502a, 0x6eef1885, 0x5e3d20e0,
+ 0xcc0389db, 0xfcd1b1be, 0xada7f911, 0x9d75c174, 0x8c36dd96, 0xbce4e5f3,
+ 0xed92ad5c, 0xdd409539, 0x4f7e3c02, 0x7fac0467, 0x2eda4cc8, 0x1e0874ad,
+ 0x0a724f8a, 0x3aa077ef, 0x6bd63f40, 0x5b040725, 0xc93aae1e, 0xf9e8967b,
+ 0xa89eded4, 0x984ce6b1, 0x890ffa53, 0xb9ddc236, 0xe8ab8a99, 0xd879b2fc,
+ 0x4a471bc7, 0x7a9523a2, 0x2be36b0d, 0x1b315368, 0x096552c9, 0x39b76aac,
+ 0x68c12203, 0x58131a66, 0xca2db35d, 0xfaff8b38, 0xab89c397, 0x9b5bfbf2,
+ 0x8a18e710, 0xbacadf75, 0xebbc97da, 0xdb6eafbf, 0x49500684, 0x79823ee1,
+ 0x28f4764e, 0x18264e2b, 0x18b8ea18, 0x286ad27d, 0x791c9ad2, 0x49cea2b7,
+ 0xdbf00b8c, 0xeb2233e9, 0xba547b46, 0x8a864323, 0x9bc55fc1, 0xab1767a4,
+ 0xfa612f0b, 0xcab3176e, 0x588dbe55, 0x685f8630, 0x3929ce9f, 0x09fbf6fa,
+ 0x1baff75b, 0x2b7dcf3e, 0x7a0b8791, 0x4ad9bff4, 0xd8e716cf, 0xe8352eaa,
+ 0xb9436605, 0x89915e60, 0x98d24282, 0xa8007ae7, 0xf9763248, 0xc9a40a2d,
+ 0x5b9aa316, 0x6b489b73, 0x3a3ed3dc, 0x0aecebb9, 0x1e96d09e, 0x2e44e8fb,
+ 0x7f32a054, 0x4fe09831, 0xddde310a, 0xed0c096f, 0xbc7a41c0, 0x8ca879a5,
+ 0x9deb6547, 0xad395d22, 0xfc4f158d, 0xcc9d2de8, 0x5ea384d3, 0x6e71bcb6,
+ 0x3f07f419, 0x0fd5cc7c, 0x1d81cddd, 0x2d53f5b8, 0x7c25bd17, 0x4cf78572,
+ 0xdec92c49, 0xee1b142c, 0xbf6d5c83, 0x8fbf64e6, 0x9efc7804, 0xae2e4061,
+ 0xff5808ce, 0xcf8a30ab, 0x5db49990, 0x6d66a1f5, 0x3c10e95a, 0x0cc2d13f,
+ 0x14e49f14, 0x2436a771, 0x7540efde, 0x4592d7bb, 0xd7ac7e80, 0xe77e46e5,
+ 0xb6080e4a, 0x86da362f, 0x97992acd, 0xa74b12a8, 0xf63d5a07, 0xc6ef6262,
+ 0x54d1cb59, 0x6403f33c, 0x3575bb93, 0x05a783f6, 0x17f38257, 0x2721ba32,
+ 0x7657f29d, 0x4685caf8, 0xd4bb63c3, 0xe4695ba6, 0xb51f1309, 0x85cd2b6c,
+ 0x948e378e, 0xa45c0feb, 0xf52a4744, 0xc5f87f21, 0x57c6d61a, 0x6714ee7f,
+ 0x3662a6d0, 0x06b09eb5, 0x12caa592, 0x22189df7, 0x736ed558, 0x43bced3d,
+ 0xd1824406, 0xe1507c63, 0xb02634cc, 0x80f40ca9, 0x91b7104b, 0xa165282e,
+ 0xf0136081, 0xc0c158e4, 0x52fff1df, 0x622dc9ba, 0x335b8115, 0x0389b970,
+ 0x11ddb8d1, 0x210f80b4, 0x7079c81b, 0x40abf07e, 0xd2955945, 0xe2476120,
+ 0xb331298f, 0x83e311ea, 0x92a00d08, 0xa272356d, 0xf3047dc2, 0xc3d645a7,
+ 0x51e8ec9c, 0x613ad4f9, 0x304c9c56, 0x009ea433};
+
+const uint32_t kStrideExtensionTable1[256] = {
+ 0x00000000, 0x54075546, 0xa80eaa8c, 0xfc09ffca, 0x55f123e9, 0x01f676af,
+ 0xfdff8965, 0xa9f8dc23, 0xabe247d2, 0xffe51294, 0x03eced5e, 0x57ebb818,
+ 0xfe13643b, 0xaa14317d, 0x561dceb7, 0x021a9bf1, 0x5228f955, 0x062fac13,
+ 0xfa2653d9, 0xae21069f, 0x07d9dabc, 0x53de8ffa, 0xafd77030, 0xfbd02576,
+ 0xf9cabe87, 0xadcdebc1, 0x51c4140b, 0x05c3414d, 0xac3b9d6e, 0xf83cc828,
+ 0x043537e2, 0x503262a4, 0xa451f2aa, 0xf056a7ec, 0x0c5f5826, 0x58580d60,
+ 0xf1a0d143, 0xa5a78405, 0x59ae7bcf, 0x0da92e89, 0x0fb3b578, 0x5bb4e03e,
+ 0xa7bd1ff4, 0xf3ba4ab2, 0x5a429691, 0x0e45c3d7, 0xf24c3c1d, 0xa64b695b,
+ 0xf6790bff, 0xa27e5eb9, 0x5e77a173, 0x0a70f435, 0xa3882816, 0xf78f7d50,
+ 0x0b86829a, 0x5f81d7dc, 0x5d9b4c2d, 0x099c196b, 0xf595e6a1, 0xa192b3e7,
+ 0x086a6fc4, 0x5c6d3a82, 0xa064c548, 0xf463900e, 0x4d4f93a5, 0x1948c6e3,
+ 0xe5413929, 0xb1466c6f, 0x18beb04c, 0x4cb9e50a, 0xb0b01ac0, 0xe4b74f86,
+ 0xe6add477, 0xb2aa8131, 0x4ea37efb, 0x1aa42bbd, 0xb35cf79e, 0xe75ba2d8,
+ 0x1b525d12, 0x4f550854, 0x1f676af0, 0x4b603fb6, 0xb769c07c, 0xe36e953a,
+ 0x4a964919, 0x1e911c5f, 0xe298e395, 0xb69fb6d3, 0xb4852d22, 0xe0827864,
+ 0x1c8b87ae, 0x488cd2e8, 0xe1740ecb, 0xb5735b8d, 0x497aa447, 0x1d7df101,
+ 0xe91e610f, 0xbd193449, 0x4110cb83, 0x15179ec5, 0xbcef42e6, 0xe8e817a0,
+ 0x14e1e86a, 0x40e6bd2c, 0x42fc26dd, 0x16fb739b, 0xeaf28c51, 0xbef5d917,
+ 0x170d0534, 0x430a5072, 0xbf03afb8, 0xeb04fafe, 0xbb36985a, 0xef31cd1c,
+ 0x133832d6, 0x473f6790, 0xeec7bbb3, 0xbac0eef5, 0x46c9113f, 0x12ce4479,
+ 0x10d4df88, 0x44d38ace, 0xb8da7504, 0xecdd2042, 0x4525fc61, 0x1122a927,
+ 0xed2b56ed, 0xb92c03ab, 0x9a9f274a, 0xce98720c, 0x32918dc6, 0x6696d880,
+ 0xcf6e04a3, 0x9b6951e5, 0x6760ae2f, 0x3367fb69, 0x317d6098, 0x657a35de,
+ 0x9973ca14, 0xcd749f52, 0x648c4371, 0x308b1637, 0xcc82e9fd, 0x9885bcbb,
+ 0xc8b7de1f, 0x9cb08b59, 0x60b97493, 0x34be21d5, 0x9d46fdf6, 0xc941a8b0,
+ 0x3548577a, 0x614f023c, 0x635599cd, 0x3752cc8b, 0xcb5b3341, 0x9f5c6607,
+ 0x36a4ba24, 0x62a3ef62, 0x9eaa10a8, 0xcaad45ee, 0x3eced5e0, 0x6ac980a6,
+ 0x96c07f6c, 0xc2c72a2a, 0x6b3ff609, 0x3f38a34f, 0xc3315c85, 0x973609c3,
+ 0x952c9232, 0xc12bc774, 0x3d2238be, 0x69256df8, 0xc0ddb1db, 0x94dae49d,
+ 0x68d31b57, 0x3cd44e11, 0x6ce62cb5, 0x38e179f3, 0xc4e88639, 0x90efd37f,
+ 0x39170f5c, 0x6d105a1a, 0x9119a5d0, 0xc51ef096, 0xc7046b67, 0x93033e21,
+ 0x6f0ac1eb, 0x3b0d94ad, 0x92f5488e, 0xc6f21dc8, 0x3afbe202, 0x6efcb744,
+ 0xd7d0b4ef, 0x83d7e1a9, 0x7fde1e63, 0x2bd94b25, 0x82219706, 0xd626c240,
+ 0x2a2f3d8a, 0x7e2868cc, 0x7c32f33d, 0x2835a67b, 0xd43c59b1, 0x803b0cf7,
+ 0x29c3d0d4, 0x7dc48592, 0x81cd7a58, 0xd5ca2f1e, 0x85f84dba, 0xd1ff18fc,
+ 0x2df6e736, 0x79f1b270, 0xd0096e53, 0x840e3b15, 0x7807c4df, 0x2c009199,
+ 0x2e1a0a68, 0x7a1d5f2e, 0x8614a0e4, 0xd213f5a2, 0x7beb2981, 0x2fec7cc7,
+ 0xd3e5830d, 0x87e2d64b, 0x73814645, 0x27861303, 0xdb8fecc9, 0x8f88b98f,
+ 0x267065ac, 0x727730ea, 0x8e7ecf20, 0xda799a66, 0xd8630197, 0x8c6454d1,
+ 0x706dab1b, 0x246afe5d, 0x8d92227e, 0xd9957738, 0x259c88f2, 0x719bddb4,
+ 0x21a9bf10, 0x75aeea56, 0x89a7159c, 0xdda040da, 0x74589cf9, 0x205fc9bf,
+ 0xdc563675, 0x88516333, 0x8a4bf8c2, 0xde4cad84, 0x2245524e, 0x76420708,
+ 0xdfbadb2b, 0x8bbd8e6d, 0x77b471a7, 0x23b324e1};
+
+const uint32_t kStrideExtensionTable2[256] = {
+ 0x00000000, 0x678efd01, 0xcf1dfa02, 0xa8930703, 0x9bd782f5, 0xfc597ff4,
+ 0x54ca78f7, 0x334485f6, 0x3243731b, 0x55cd8e1a, 0xfd5e8919, 0x9ad07418,
+ 0xa994f1ee, 0xce1a0cef, 0x66890bec, 0x0107f6ed, 0x6486e636, 0x03081b37,
+ 0xab9b1c34, 0xcc15e135, 0xff5164c3, 0x98df99c2, 0x304c9ec1, 0x57c263c0,
+ 0x56c5952d, 0x314b682c, 0x99d86f2f, 0xfe56922e, 0xcd1217d8, 0xaa9cead9,
+ 0x020fedda, 0x658110db, 0xc90dcc6c, 0xae83316d, 0x0610366e, 0x619ecb6f,
+ 0x52da4e99, 0x3554b398, 0x9dc7b49b, 0xfa49499a, 0xfb4ebf77, 0x9cc04276,
+ 0x34534575, 0x53ddb874, 0x60993d82, 0x0717c083, 0xaf84c780, 0xc80a3a81,
+ 0xad8b2a5a, 0xca05d75b, 0x6296d058, 0x05182d59, 0x365ca8af, 0x51d255ae,
+ 0xf94152ad, 0x9ecfafac, 0x9fc85941, 0xf846a440, 0x50d5a343, 0x375b5e42,
+ 0x041fdbb4, 0x639126b5, 0xcb0221b6, 0xac8cdcb7, 0x97f7ee29, 0xf0791328,
+ 0x58ea142b, 0x3f64e92a, 0x0c206cdc, 0x6bae91dd, 0xc33d96de, 0xa4b36bdf,
+ 0xa5b49d32, 0xc23a6033, 0x6aa96730, 0x0d279a31, 0x3e631fc7, 0x59ede2c6,
+ 0xf17ee5c5, 0x96f018c4, 0xf371081f, 0x94fff51e, 0x3c6cf21d, 0x5be20f1c,
+ 0x68a68aea, 0x0f2877eb, 0xa7bb70e8, 0xc0358de9, 0xc1327b04, 0xa6bc8605,
+ 0x0e2f8106, 0x69a17c07, 0x5ae5f9f1, 0x3d6b04f0, 0x95f803f3, 0xf276fef2,
+ 0x5efa2245, 0x3974df44, 0x91e7d847, 0xf6692546, 0xc52da0b0, 0xa2a35db1,
+ 0x0a305ab2, 0x6dbea7b3, 0x6cb9515e, 0x0b37ac5f, 0xa3a4ab5c, 0xc42a565d,
+ 0xf76ed3ab, 0x90e02eaa, 0x387329a9, 0x5ffdd4a8, 0x3a7cc473, 0x5df23972,
+ 0xf5613e71, 0x92efc370, 0xa1ab4686, 0xc625bb87, 0x6eb6bc84, 0x09384185,
+ 0x083fb768, 0x6fb14a69, 0xc7224d6a, 0xa0acb06b, 0x93e8359d, 0xf466c89c,
+ 0x5cf5cf9f, 0x3b7b329e, 0x2a03aaa3, 0x4d8d57a2, 0xe51e50a1, 0x8290ada0,
+ 0xb1d42856, 0xd65ad557, 0x7ec9d254, 0x19472f55, 0x1840d9b8, 0x7fce24b9,
+ 0xd75d23ba, 0xb0d3debb, 0x83975b4d, 0xe419a64c, 0x4c8aa14f, 0x2b045c4e,
+ 0x4e854c95, 0x290bb194, 0x8198b697, 0xe6164b96, 0xd552ce60, 0xb2dc3361,
+ 0x1a4f3462, 0x7dc1c963, 0x7cc63f8e, 0x1b48c28f, 0xb3dbc58c, 0xd455388d,
+ 0xe711bd7b, 0x809f407a, 0x280c4779, 0x4f82ba78, 0xe30e66cf, 0x84809bce,
+ 0x2c139ccd, 0x4b9d61cc, 0x78d9e43a, 0x1f57193b, 0xb7c41e38, 0xd04ae339,
+ 0xd14d15d4, 0xb6c3e8d5, 0x1e50efd6, 0x79de12d7, 0x4a9a9721, 0x2d146a20,
+ 0x85876d23, 0xe2099022, 0x878880f9, 0xe0067df8, 0x48957afb, 0x2f1b87fa,
+ 0x1c5f020c, 0x7bd1ff0d, 0xd342f80e, 0xb4cc050f, 0xb5cbf3e2, 0xd2450ee3,
+ 0x7ad609e0, 0x1d58f4e1, 0x2e1c7117, 0x49928c16, 0xe1018b15, 0x868f7614,
+ 0xbdf4448a, 0xda7ab98b, 0x72e9be88, 0x15674389, 0x2623c67f, 0x41ad3b7e,
+ 0xe93e3c7d, 0x8eb0c17c, 0x8fb73791, 0xe839ca90, 0x40aacd93, 0x27243092,
+ 0x1460b564, 0x73ee4865, 0xdb7d4f66, 0xbcf3b267, 0xd972a2bc, 0xbefc5fbd,
+ 0x166f58be, 0x71e1a5bf, 0x42a52049, 0x252bdd48, 0x8db8da4b, 0xea36274a,
+ 0xeb31d1a7, 0x8cbf2ca6, 0x242c2ba5, 0x43a2d6a4, 0x70e65352, 0x1768ae53,
+ 0xbffba950, 0xd8755451, 0x74f988e6, 0x137775e7, 0xbbe472e4, 0xdc6a8fe5,
+ 0xef2e0a13, 0x88a0f712, 0x2033f011, 0x47bd0d10, 0x46bafbfd, 0x213406fc,
+ 0x89a701ff, 0xee29fcfe, 0xdd6d7908, 0xbae38409, 0x1270830a, 0x75fe7e0b,
+ 0x107f6ed0, 0x77f193d1, 0xdf6294d2, 0xb8ec69d3, 0x8ba8ec25, 0xec261124,
+ 0x44b51627, 0x233beb26, 0x223c1dcb, 0x45b2e0ca, 0xed21e7c9, 0x8aaf1ac8,
+ 0xb9eb9f3e, 0xde65623f, 0x76f6653c, 0x1178983d};
+
+const uint32_t kStrideExtensionTable3[256] = {
+ 0x00000000, 0xf20c0dfe, 0xe1f46d0d, 0x13f860f3, 0xc604aceb, 0x3408a115,
+ 0x27f0c1e6, 0xd5fccc18, 0x89e52f27, 0x7be922d9, 0x6811422a, 0x9a1d4fd4,
+ 0x4fe183cc, 0xbded8e32, 0xae15eec1, 0x5c19e33f, 0x162628bf, 0xe42a2541,
+ 0xf7d245b2, 0x05de484c, 0xd0228454, 0x222e89aa, 0x31d6e959, 0xc3dae4a7,
+ 0x9fc30798, 0x6dcf0a66, 0x7e376a95, 0x8c3b676b, 0x59c7ab73, 0xabcba68d,
+ 0xb833c67e, 0x4a3fcb80, 0x2c4c517e, 0xde405c80, 0xcdb83c73, 0x3fb4318d,
+ 0xea48fd95, 0x1844f06b, 0x0bbc9098, 0xf9b09d66, 0xa5a97e59, 0x57a573a7,
+ 0x445d1354, 0xb6511eaa, 0x63add2b2, 0x91a1df4c, 0x8259bfbf, 0x7055b241,
+ 0x3a6a79c1, 0xc866743f, 0xdb9e14cc, 0x29921932, 0xfc6ed52a, 0x0e62d8d4,
+ 0x1d9ab827, 0xef96b5d9, 0xb38f56e6, 0x41835b18, 0x527b3beb, 0xa0773615,
+ 0x758bfa0d, 0x8787f7f3, 0x947f9700, 0x66739afe, 0x5898a2fc, 0xaa94af02,
+ 0xb96ccff1, 0x4b60c20f, 0x9e9c0e17, 0x6c9003e9, 0x7f68631a, 0x8d646ee4,
+ 0xd17d8ddb, 0x23718025, 0x3089e0d6, 0xc285ed28, 0x17792130, 0xe5752cce,
+ 0xf68d4c3d, 0x048141c3, 0x4ebe8a43, 0xbcb287bd, 0xaf4ae74e, 0x5d46eab0,
+ 0x88ba26a8, 0x7ab62b56, 0x694e4ba5, 0x9b42465b, 0xc75ba564, 0x3557a89a,
+ 0x26afc869, 0xd4a3c597, 0x015f098f, 0xf3530471, 0xe0ab6482, 0x12a7697c,
+ 0x74d4f382, 0x86d8fe7c, 0x95209e8f, 0x672c9371, 0xb2d05f69, 0x40dc5297,
+ 0x53243264, 0xa1283f9a, 0xfd31dca5, 0x0f3dd15b, 0x1cc5b1a8, 0xeec9bc56,
+ 0x3b35704e, 0xc9397db0, 0xdac11d43, 0x28cd10bd, 0x62f2db3d, 0x90fed6c3,
+ 0x8306b630, 0x710abbce, 0xa4f677d6, 0x56fa7a28, 0x45021adb, 0xb70e1725,
+ 0xeb17f41a, 0x191bf9e4, 0x0ae39917, 0xf8ef94e9, 0x2d1358f1, 0xdf1f550f,
+ 0xcce735fc, 0x3eeb3802, 0xb13145f8, 0x433d4806, 0x50c528f5, 0xa2c9250b,
+ 0x7735e913, 0x8539e4ed, 0x96c1841e, 0x64cd89e0, 0x38d46adf, 0xcad86721,
+ 0xd92007d2, 0x2b2c0a2c, 0xfed0c634, 0x0cdccbca, 0x1f24ab39, 0xed28a6c7,
+ 0xa7176d47, 0x551b60b9, 0x46e3004a, 0xb4ef0db4, 0x6113c1ac, 0x931fcc52,
+ 0x80e7aca1, 0x72eba15f, 0x2ef24260, 0xdcfe4f9e, 0xcf062f6d, 0x3d0a2293,
+ 0xe8f6ee8b, 0x1afae375, 0x09028386, 0xfb0e8e78, 0x9d7d1486, 0x6f711978,
+ 0x7c89798b, 0x8e857475, 0x5b79b86d, 0xa975b593, 0xba8dd560, 0x4881d89e,
+ 0x14983ba1, 0xe694365f, 0xf56c56ac, 0x07605b52, 0xd29c974a, 0x20909ab4,
+ 0x3368fa47, 0xc164f7b9, 0x8b5b3c39, 0x795731c7, 0x6aaf5134, 0x98a35cca,
+ 0x4d5f90d2, 0xbf539d2c, 0xacabfddf, 0x5ea7f021, 0x02be131e, 0xf0b21ee0,
+ 0xe34a7e13, 0x114673ed, 0xc4babff5, 0x36b6b20b, 0x254ed2f8, 0xd742df06,
+ 0xe9a9e704, 0x1ba5eafa, 0x085d8a09, 0xfa5187f7, 0x2fad4bef, 0xdda14611,
+ 0xce5926e2, 0x3c552b1c, 0x604cc823, 0x9240c5dd, 0x81b8a52e, 0x73b4a8d0,
+ 0xa64864c8, 0x54446936, 0x47bc09c5, 0xb5b0043b, 0xff8fcfbb, 0x0d83c245,
+ 0x1e7ba2b6, 0xec77af48, 0x398b6350, 0xcb876eae, 0xd87f0e5d, 0x2a7303a3,
+ 0x766ae09c, 0x8466ed62, 0x979e8d91, 0x6592806f, 0xb06e4c77, 0x42624189,
+ 0x519a217a, 0xa3962c84, 0xc5e5b67a, 0x37e9bb84, 0x2411db77, 0xd61dd689,
+ 0x03e11a91, 0xf1ed176f, 0xe215779c, 0x10197a62, 0x4c00995d, 0xbe0c94a3,
+ 0xadf4f450, 0x5ff8f9ae, 0x8a0435b6, 0x78083848, 0x6bf058bb, 0x99fc5545,
+ 0xd3c39ec5, 0x21cf933b, 0x3237f3c8, 0xc03bfe36, 0x15c7322e, 0xe7cb3fd0,
+ 0xf4335f23, 0x063f52dd, 0x5a26b1e2, 0xa82abc1c, 0xbbd2dcef, 0x49ded111,
+ 0x9c221d09, 0x6e2e10f7, 0x7dd67004, 0x8fda7dfa};
+
+// CRCs are pre- and post- conditioned by xoring with all ones.
+static constexpr const uint32_t kCRC32Xor = static_cast<uint32_t>(0xffffffffU);
+
+// Reads a little-endian 32-bit integer from a 32-bit-aligned buffer.
+inline uint32_t ReadUint32LE(const uint8_t* buffer) {
+ return DecodeFixed32(reinterpret_cast<const char*>(buffer));
}
+// Returns the smallest address >= the given address that is aligned to N bytes.
+//
+// N must be a power of two.
+template <int N>
+constexpr inline const uint8_t* RoundUp(const uint8_t* pointer) {
+ return reinterpret_cast<uint8_t*>(
+ (reinterpret_cast<uintptr_t>(pointer) + (N - 1)) &
+ ~static_cast<uintptr_t>(N - 1));
+}
+
+} // namespace
+
// Determine if the CPU running this program can accelerate the CRC32C
// calculation.
static bool CanAccelerateCRC32C() {
- if (!port::HasAcceleratedCRC32C())
- return false;
-
- // Double-check that the accelerated implementation functions correctly.
// port::AcceleretedCRC32C returns zero when unable to accelerate.
static const char kTestCRCBuffer[] = "TestCRCBuffer";
static const char kBufSize = sizeof(kTestCRCBuffer) - 1;
@@ -300,54 +273,107 @@ static bool CanAccelerateCRC32C() {
return port::AcceleratedCRC32C(0, kTestCRCBuffer, kBufSize) == kTestCRCValue;
}
-uint32_t Extend(uint32_t crc, const char* buf, size_t size) {
+uint32_t Extend(uint32_t crc, const char* data, size_t n) {
static bool accelerate = CanAccelerateCRC32C();
if (accelerate) {
- return port::AcceleratedCRC32C(crc, buf, size);
+ return port::AcceleratedCRC32C(crc, data, n);
}
- const uint8_t *p = reinterpret_cast<const uint8_t *>(buf);
- const uint8_t *e = p + size;
- uint32_t l = crc ^ 0xffffffffu;
+ const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
+ const uint8_t* e = p + n;
+ uint32_t l = crc ^ kCRC32Xor;
+
+// Process one byte at a time.
+#define STEP1 \
+ do { \
+ int c = (l & 0xff) ^ *p++; \
+ l = kByteExtensionTable[c] ^ (l >> 8); \
+ } while (0)
-#define STEP1 do { \
- int c = (l & 0xff) ^ *p++; \
- l = table0_[c] ^ (l >> 8); \
-} while (0)
-#define STEP4 do { \
- uint32_t c = l ^ LE_LOAD32(p); \
- p += 4; \
- l = table3_[c & 0xff] ^ \
- table2_[(c >> 8) & 0xff] ^ \
- table1_[(c >> 16) & 0xff] ^ \
- table0_[c >> 24]; \
-} while (0)
+// Process one of the 4 strides of 4-byte data.
+#define STEP4(s) \
+ do { \
+ crc##s = ReadUint32LE(p + s * 4) ^ kStrideExtensionTable3[crc##s & 0xff] ^ \
+ kStrideExtensionTable2[(crc##s >> 8) & 0xff] ^ \
+ kStrideExtensionTable1[(crc##s >> 16) & 0xff] ^ \
+ kStrideExtensionTable0[crc##s >> 24]; \
+ } while (0)
- // Point x at first 4-byte aligned byte in string. This might be
- // just past the end of the string.
- const uintptr_t pval = reinterpret_cast<uintptr_t>(p);
- const uint8_t* x = reinterpret_cast<const uint8_t*>(((pval + 3) >> 2) << 2);
+// Process a 16-byte swath of 4 strides, each of which has 4 bytes of data.
+#define STEP16 \
+ do { \
+ STEP4(0); \
+ STEP4(1); \
+ STEP4(2); \
+ STEP4(3); \
+ p += 16; \
+ } while (0)
+
+// Process 4 bytes that were already loaded into a word.
+#define STEP4W(w) \
+ do { \
+ w ^= l; \
+ for (size_t i = 0; i < 4; ++i) { \
+ w = (w >> 8) ^ kByteExtensionTable[w & 0xff]; \
+ } \
+ l = w; \
+ } while (0)
+
+ // Point x at first 4-byte aligned byte in the buffer. This might be past the
+ // end of the buffer.
+ const uint8_t* x = RoundUp<4>(p);
if (x <= e) {
- // Process bytes until finished or p is 4-byte aligned
+ // Process bytes p is 4-byte aligned.
while (p != x) {
STEP1;
}
}
- // Process bytes 16 at a time
- while ((e-p) >= 16) {
- STEP4; STEP4; STEP4; STEP4;
- }
- // Process bytes 4 at a time
- while ((e-p) >= 4) {
- STEP4;
+
+ if ((e - p) >= 16) {
+ // Load a 16-byte swath into the stride partial results.
+ uint32_t crc0 = ReadUint32LE(p + 0 * 4) ^ l;
+ uint32_t crc1 = ReadUint32LE(p + 1 * 4);
+ uint32_t crc2 = ReadUint32LE(p + 2 * 4);
+ uint32_t crc3 = ReadUint32LE(p + 3 * 4);
+ p += 16;
+
+ // It is possible to get better speeds (at least on x86) by interleaving
+ // prefetching 256 bytes ahead with processing 64 bytes at a time. See the
+ // portable implementation in https://github.com/google/crc32c/.
+
+ // Process one 16-byte swath at a time.
+ while ((e - p) >= 16) {
+ STEP16;
+ }
+
+ // Advance one word at a time as far as possible.
+ while ((e - p) >= 4) {
+ STEP4(0);
+ uint32_t tmp = crc0;
+ crc0 = crc1;
+ crc1 = crc2;
+ crc2 = crc3;
+ crc3 = tmp;
+ p += 4;
+ }
+
+ // Combine the 4 partial stride results.
+ l = 0;
+ STEP4W(crc0);
+ STEP4W(crc1);
+ STEP4W(crc2);
+ STEP4W(crc3);
}
- // Process the last few bytes
+
+ // Process the last few bytes.
while (p != e) {
STEP1;
}
+#undef STEP4W
+#undef STEP16
#undef STEP4
#undef STEP1
- return l ^ 0xffffffffu;
+ return l ^ kCRC32Xor;
}
} // namespace crc32c
diff --git a/src/leveldb/util/crc32c.h b/src/leveldb/util/crc32c.h
index 1d7e5c075d..98fabb0d2f 100644
--- a/src/leveldb/util/crc32c.h
+++ b/src/leveldb/util/crc32c.h
@@ -14,12 +14,10 @@ namespace crc32c {
// Return the crc32c of concat(A, data[0,n-1]) where init_crc is the
// crc32c of some string A. Extend() is often used to maintain the
// crc32c of a stream of data.
-extern uint32_t Extend(uint32_t init_crc, const char* data, size_t n);
+uint32_t Extend(uint32_t init_crc, const char* data, size_t n);
// Return the crc32c of data[0,n-1]
-inline uint32_t Value(const char* data, size_t n) {
- return Extend(0, data, n);
-}
+inline uint32_t Value(const char* data, size_t n) { return Extend(0, data, n); }
static const uint32_t kMaskDelta = 0xa282ead8ul;
diff --git a/src/leveldb/util/crc32c_test.cc b/src/leveldb/util/crc32c_test.cc
index 4b957ee120..18a8494824 100644
--- a/src/leveldb/util/crc32c_test.cc
+++ b/src/leveldb/util/crc32c_test.cc
@@ -8,7 +8,7 @@
namespace leveldb {
namespace crc32c {
-class CRC { };
+class CRC {};
TEST(CRC, StandardResults) {
// From rfc3720 section B.4.
@@ -30,30 +30,19 @@ TEST(CRC, StandardResults) {
}
ASSERT_EQ(0x113fdb5c, Value(buf, sizeof(buf)));
- unsigned char data[48] = {
- 0x01, 0xc0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x14,
- 0x00, 0x00, 0x00, 0x18,
- 0x28, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
+ uint8_t data[48] = {
+ 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
ASSERT_EQ(0xd9963a56, Value(reinterpret_cast<char*>(data), sizeof(data)));
}
-TEST(CRC, Values) {
- ASSERT_NE(Value("a", 1), Value("foo", 3));
-}
+TEST(CRC, Values) { ASSERT_NE(Value("a", 1), Value("foo", 3)); }
TEST(CRC, Extend) {
- ASSERT_EQ(Value("hello world", 11),
- Extend(Value("hello ", 6), "world", 5));
+ ASSERT_EQ(Value("hello world", 11), Extend(Value("hello ", 6), "world", 5));
}
TEST(CRC, Mask) {
@@ -67,6 +56,4 @@ TEST(CRC, Mask) {
} // namespace crc32c
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/env.cc b/src/leveldb/util/env.cc
index c58a0821ef..d2f0aef326 100644
--- a/src/leveldb/util/env.cc
+++ b/src/leveldb/util/env.cc
@@ -6,30 +6,24 @@
namespace leveldb {
-Env::~Env() {
-}
+Env::~Env() = default;
Status Env::NewAppendableFile(const std::string& fname, WritableFile** result) {
return Status::NotSupported("NewAppendableFile", fname);
}
-SequentialFile::~SequentialFile() {
-}
+SequentialFile::~SequentialFile() = default;
-RandomAccessFile::~RandomAccessFile() {
-}
+RandomAccessFile::~RandomAccessFile() = default;
-WritableFile::~WritableFile() {
-}
+WritableFile::~WritableFile() = default;
-Logger::~Logger() {
-}
+Logger::~Logger() = default;
-FileLock::~FileLock() {
-}
+FileLock::~FileLock() = default;
void Log(Logger* info_log, const char* format, ...) {
- if (info_log != NULL) {
+ if (info_log != nullptr) {
va_list ap;
va_start(ap, format);
info_log->Logv(format, ap);
@@ -38,8 +32,7 @@ void Log(Logger* info_log, const char* format, ...) {
}
static Status DoWriteStringToFile(Env* env, const Slice& data,
- const std::string& fname,
- bool should_sync) {
+ const std::string& fname, bool should_sync) {
WritableFile* file;
Status s = env->NewWritableFile(fname, &file);
if (!s.ok()) {
@@ -94,7 +87,6 @@ Status ReadFileToString(Env* env, const std::string& fname, std::string* data) {
return s;
}
-EnvWrapper::~EnvWrapper() {
-}
+EnvWrapper::~EnvWrapper() {}
} // namespace leveldb
diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc
index f77918313e..9f5863a0f3 100644
--- a/src/leveldb/util/env_posix.cc
+++ b/src/leveldb/util/env_posix.cc
@@ -1,706 +1,906 @@
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// 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.
-#if !defined(LEVELDB_PLATFORM_WINDOWS)
#include <dirent.h>
-#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <time.h>
#include <unistd.h>
-#include <deque>
+
+#include <atomic>
+#include <cerrno>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <limits>
+#include <queue>
#include <set>
+#include <string>
+#include <thread>
+#include <type_traits>
+#include <utility>
+
#include "leveldb/env.h"
#include "leveldb/slice.h"
+#include "leveldb/status.h"
#include "port/port.h"
-#include "util/logging.h"
-#include "util/mutexlock.h"
-#include "util/posix_logger.h"
+#include "port/thread_annotations.h"
#include "util/env_posix_test_helper.h"
+#include "util/posix_logger.h"
namespace leveldb {
namespace {
-static int open_read_only_file_limit = -1;
-static int mmap_limit = -1;
+// Set by EnvPosixTestHelper::SetReadOnlyMMapLimit() and MaxOpenFiles().
+int g_open_read_only_file_limit = -1;
+
+// Up to 4096 mmap regions for 64-bit binaries; none for 32-bit.
+constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 4096 : 0;
+
+// Can be set using EnvPosixTestHelper::SetReadOnlyMMapLimit().
+int g_mmap_limit = kDefaultMmapLimit;
-static Status IOError(const std::string& context, int err_number) {
- return Status::IOError(context, strerror(err_number));
+// Common flags defined for all posix open operations
+#if defined(HAVE_O_CLOEXEC)
+constexpr const int kOpenBaseFlags = O_CLOEXEC;
+#else
+constexpr const int kOpenBaseFlags = 0;
+#endif // defined(HAVE_O_CLOEXEC)
+
+constexpr const size_t kWritableFileBufferSize = 65536;
+
+Status PosixError(const std::string& context, int error_number) {
+ if (error_number == ENOENT) {
+ return Status::NotFound(context, std::strerror(error_number));
+ } else {
+ return Status::IOError(context, std::strerror(error_number));
+ }
}
// Helper class to limit resource usage to avoid exhaustion.
// Currently used to limit read-only file descriptors and mmap file usage
-// so that we do not end up running out of file descriptors, virtual memory,
-// or running into kernel performance problems for very large databases.
+// so that we do not run out of file descriptors or virtual memory, or run into
+// kernel performance problems for very large databases.
class Limiter {
public:
- // Limit maximum number of resources to |n|.
- Limiter(intptr_t n) {
- SetAllowed(n);
- }
+ // Limit maximum number of resources to |max_acquires|.
+ Limiter(int max_acquires) : acquires_allowed_(max_acquires) {}
+
+ Limiter(const Limiter&) = delete;
+ Limiter operator=(const Limiter&) = delete;
// If another resource is available, acquire it and return true.
// Else return false.
bool Acquire() {
- if (GetAllowed() <= 0) {
- return false;
- }
- MutexLock l(&mu_);
- intptr_t x = GetAllowed();
- if (x <= 0) {
- return false;
- } else {
- SetAllowed(x - 1);
- return true;
- }
+ int old_acquires_allowed =
+ acquires_allowed_.fetch_sub(1, std::memory_order_relaxed);
+
+ if (old_acquires_allowed > 0) return true;
+
+ acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
+ return false;
}
// Release a resource acquired by a previous call to Acquire() that returned
// true.
- void Release() {
- MutexLock l(&mu_);
- SetAllowed(GetAllowed() + 1);
- }
+ void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }
private:
- port::Mutex mu_;
- port::AtomicPointer allowed_;
-
- intptr_t GetAllowed() const {
- return reinterpret_cast<intptr_t>(allowed_.Acquire_Load());
- }
-
- // REQUIRES: mu_ must be held
- void SetAllowed(intptr_t v) {
- allowed_.Release_Store(reinterpret_cast<void*>(v));
- }
-
- Limiter(const Limiter&);
- void operator=(const Limiter&);
+ // The number of available resources.
+ //
+ // This is a counter and is not tied to the invariants of any other class, so
+ // it can be operated on safely using std::memory_order_relaxed.
+ std::atomic<int> acquires_allowed_;
};
-class PosixSequentialFile: public SequentialFile {
- private:
- std::string filename_;
- FILE* file_;
-
+// Implements sequential read access in a file using read().
+//
+// Instances of this class are thread-friendly but not thread-safe, as required
+// by the SequentialFile API.
+class PosixSequentialFile final : public SequentialFile {
public:
- PosixSequentialFile(const std::string& fname, FILE* f)
- : filename_(fname), file_(f) { }
- virtual ~PosixSequentialFile() { fclose(file_); }
-
- virtual Status Read(size_t n, Slice* result, char* scratch) {
- Status s;
- size_t r = fread_unlocked(scratch, 1, n, file_);
- *result = Slice(scratch, r);
- if (r < n) {
- if (feof(file_)) {
- // We leave status as ok if we hit the end of the file
- } else {
- // A partial read with an error: return a non-ok status
- s = IOError(filename_, errno);
+ PosixSequentialFile(std::string filename, int fd)
+ : fd_(fd), filename_(filename) {}
+ ~PosixSequentialFile() override { close(fd_); }
+
+ Status Read(size_t n, Slice* result, char* scratch) override {
+ Status status;
+ while (true) {
+ ::ssize_t read_size = ::read(fd_, scratch, n);
+ if (read_size < 0) { // Read error.
+ if (errno == EINTR) {
+ continue; // Retry
+ }
+ status = PosixError(filename_, errno);
+ break;
}
+ *result = Slice(scratch, read_size);
+ break;
}
- return s;
+ return status;
}
- virtual Status Skip(uint64_t n) {
- if (fseek(file_, n, SEEK_CUR)) {
- return IOError(filename_, errno);
+ Status Skip(uint64_t n) override {
+ if (::lseek(fd_, n, SEEK_CUR) == static_cast<off_t>(-1)) {
+ return PosixError(filename_, errno);
}
return Status::OK();
}
- virtual std::string GetName() const { return filename_; }
-};
+ virtual std::string GetName() const override { return filename_; }
-// pread() based random-access
-class PosixRandomAccessFile: public RandomAccessFile {
private:
- std::string filename_;
- bool temporary_fd_; // If true, fd_ is -1 and we open on every read.
- int fd_;
- Limiter* limiter_;
+ const int fd_;
+ const std::string filename_;
+};
+// Implements random read access in a file using pread().
+//
+// Instances of this class are thread-safe, as required by the RandomAccessFile
+// API. Instances are immutable and Read() only calls thread-safe library
+// functions.
+class PosixRandomAccessFile final : public RandomAccessFile {
public:
- PosixRandomAccessFile(const std::string& fname, int fd, Limiter* limiter)
- : filename_(fname), fd_(fd), limiter_(limiter) {
- temporary_fd_ = !limiter->Acquire();
- if (temporary_fd_) {
- // Open file on every access.
- close(fd_);
- fd_ = -1;
+ // The new instance takes ownership of |fd|. |fd_limiter| must outlive this
+ // instance, and will be used to determine if .
+ PosixRandomAccessFile(std::string filename, int fd, Limiter* fd_limiter)
+ : has_permanent_fd_(fd_limiter->Acquire()),
+ fd_(has_permanent_fd_ ? fd : -1),
+ fd_limiter_(fd_limiter),
+ filename_(std::move(filename)) {
+ if (!has_permanent_fd_) {
+ assert(fd_ == -1);
+ ::close(fd); // The file will be opened on every read.
}
}
- virtual ~PosixRandomAccessFile() {
- if (!temporary_fd_) {
- close(fd_);
- limiter_->Release();
+ ~PosixRandomAccessFile() override {
+ if (has_permanent_fd_) {
+ assert(fd_ != -1);
+ ::close(fd_);
+ fd_limiter_->Release();
}
}
- virtual Status Read(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
+ Status Read(uint64_t offset, size_t n, Slice* result,
+ char* scratch) const override {
int fd = fd_;
- if (temporary_fd_) {
- fd = open(filename_.c_str(), O_RDONLY);
+ if (!has_permanent_fd_) {
+ fd = ::open(filename_.c_str(), O_RDONLY | kOpenBaseFlags);
if (fd < 0) {
- return IOError(filename_, errno);
+ return PosixError(filename_, errno);
}
}
- Status s;
- ssize_t r = pread(fd, scratch, n, static_cast<off_t>(offset));
- *result = Slice(scratch, (r < 0) ? 0 : r);
- if (r < 0) {
- // An error: return a non-ok status
- s = IOError(filename_, errno);
+ assert(fd != -1);
+
+ Status status;
+ ssize_t read_size = ::pread(fd, scratch, n, static_cast<off_t>(offset));
+ *result = Slice(scratch, (read_size < 0) ? 0 : read_size);
+ if (read_size < 0) {
+ // An error: return a non-ok status.
+ status = PosixError(filename_, errno);
}
- if (temporary_fd_) {
+ if (!has_permanent_fd_) {
// Close the temporary file descriptor opened earlier.
- close(fd);
+ assert(fd != fd_);
+ ::close(fd);
}
- return s;
+ return status;
}
- virtual std::string GetName() const { return filename_; }
-};
+ virtual std::string GetName() const override { return filename_; }
-// mmap() based random-access
-class PosixMmapReadableFile: public RandomAccessFile {
private:
- std::string filename_;
- void* mmapped_region_;
- size_t length_;
- Limiter* limiter_;
+ const bool has_permanent_fd_; // If false, the file is opened on every read.
+ const int fd_; // -1 if has_permanent_fd_ is false.
+ Limiter* const fd_limiter_;
+ const std::string filename_;
+};
+// Implements random read access in a file using mmap().
+//
+// Instances of this class are thread-safe, as required by the RandomAccessFile
+// API. Instances are immutable and Read() only calls thread-safe library
+// functions.
+class PosixMmapReadableFile final : public RandomAccessFile {
public:
- // base[0,length-1] contains the mmapped contents of the file.
- PosixMmapReadableFile(const std::string& fname, void* base, size_t length,
- Limiter* limiter)
- : filename_(fname), mmapped_region_(base), length_(length),
- limiter_(limiter) {
- }
-
- virtual ~PosixMmapReadableFile() {
- munmap(mmapped_region_, length_);
- limiter_->Release();
- }
-
- virtual Status Read(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
- Status s;
+ // mmap_base[0, length-1] points to the memory-mapped contents of the file. It
+ // must be the result of a successful call to mmap(). This instances takes
+ // over the ownership of the region.
+ //
+ // |mmap_limiter| must outlive this instance. The caller must have already
+ // aquired the right to use one mmap region, which will be released when this
+ // instance is destroyed.
+ PosixMmapReadableFile(std::string filename, char* mmap_base, size_t length,
+ Limiter* mmap_limiter)
+ : mmap_base_(mmap_base),
+ length_(length),
+ mmap_limiter_(mmap_limiter),
+ filename_(std::move(filename)) {}
+
+ ~PosixMmapReadableFile() override {
+ ::munmap(static_cast<void*>(mmap_base_), length_);
+ mmap_limiter_->Release();
+ }
+
+ Status Read(uint64_t offset, size_t n, Slice* result,
+ char* scratch) const override {
if (offset + n > length_) {
*result = Slice();
- s = IOError(filename_, EINVAL);
- } else {
- *result = Slice(reinterpret_cast<char*>(mmapped_region_) + offset, n);
+ return PosixError(filename_, EINVAL);
}
- return s;
+
+ *result = Slice(mmap_base_ + offset, n);
+ return Status::OK();
}
- virtual std::string GetName() const { return filename_; }
-};
+ virtual std::string GetName() const override { return filename_; }
-class PosixWritableFile : public WritableFile {
private:
- std::string filename_;
- FILE* file_;
+ char* const mmap_base_;
+ const size_t length_;
+ Limiter* const mmap_limiter_;
+ const std::string filename_;
+};
+class PosixWritableFile final : public WritableFile {
public:
- PosixWritableFile(const std::string& fname, FILE* f)
- : filename_(fname), file_(f) { }
-
- ~PosixWritableFile() {
- if (file_ != NULL) {
+ PosixWritableFile(std::string filename, int fd)
+ : pos_(0),
+ fd_(fd),
+ is_manifest_(IsManifest(filename)),
+ filename_(std::move(filename)),
+ dirname_(Dirname(filename_)) {}
+
+ ~PosixWritableFile() override {
+ if (fd_ >= 0) {
// Ignoring any potential errors
- fclose(file_);
+ Close();
}
}
- virtual Status Append(const Slice& data) {
- size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_);
- if (r != data.size()) {
- return IOError(filename_, errno);
+ Status Append(const Slice& data) override {
+ size_t write_size = data.size();
+ const char* write_data = data.data();
+
+ // Fit as much as possible into buffer.
+ size_t copy_size = std::min(write_size, kWritableFileBufferSize - pos_);
+ std::memcpy(buf_ + pos_, write_data, copy_size);
+ write_data += copy_size;
+ write_size -= copy_size;
+ pos_ += copy_size;
+ if (write_size == 0) {
+ return Status::OK();
}
- return Status::OK();
+
+ // Can't fit in buffer, so need to do at least one write.
+ Status status = FlushBuffer();
+ if (!status.ok()) {
+ return status;
+ }
+
+ // Small writes go to buffer, large writes are written directly.
+ if (write_size < kWritableFileBufferSize) {
+ std::memcpy(buf_, write_data, write_size);
+ pos_ = write_size;
+ return Status::OK();
+ }
+ return WriteUnbuffered(write_data, write_size);
}
- virtual Status Close() {
- Status result;
- if (fclose(file_) != 0) {
- result = IOError(filename_, errno);
+ Status Close() override {
+ Status status = FlushBuffer();
+ const int close_result = ::close(fd_);
+ if (close_result < 0 && status.ok()) {
+ status = PosixError(filename_, errno);
}
- file_ = NULL;
- return result;
+ fd_ = -1;
+ return status;
}
- virtual Status Flush() {
- if (fflush_unlocked(file_) != 0) {
- return IOError(filename_, errno);
+ Status Flush() override { return FlushBuffer(); }
+
+ Status Sync() override {
+ // Ensure new files referred to by the manifest are in the filesystem.
+ //
+ // This needs to happen before the manifest file is flushed to disk, to
+ // avoid crashing in a state where the manifest refers to files that are not
+ // yet on disk.
+ Status status = SyncDirIfManifest();
+ if (!status.ok()) {
+ return status;
+ }
+
+ status = FlushBuffer();
+ if (!status.ok()) {
+ return status;
+ }
+
+ return SyncFd(fd_, filename_, false);
+ }
+
+ private:
+ Status FlushBuffer() {
+ Status status = WriteUnbuffered(buf_, pos_);
+ pos_ = 0;
+ return status;
+ }
+
+ Status WriteUnbuffered(const char* data, size_t size) {
+ while (size > 0) {
+ ssize_t write_result = ::write(fd_, data, size);
+ if (write_result < 0) {
+ if (errno == EINTR) {
+ continue; // Retry
+ }
+ return PosixError(filename_, errno);
+ }
+ data += write_result;
+ size -= write_result;
}
return Status::OK();
}
Status SyncDirIfManifest() {
- const char* f = filename_.c_str();
- const char* sep = strrchr(f, '/');
- Slice basename;
- std::string dir;
- if (sep == NULL) {
- dir = ".";
- basename = f;
+ Status status;
+ if (!is_manifest_) {
+ return status;
+ }
+
+ int fd = ::open(dirname_.c_str(), O_RDONLY | kOpenBaseFlags);
+ if (fd < 0) {
+ status = PosixError(dirname_, errno);
} else {
- dir = std::string(f, sep - f);
- basename = sep + 1;
+ status = SyncFd(fd, dirname_, true);
+ ::close(fd);
+ }
+ return status;
+ }
+
+ // Ensures that all the caches associated with the given file descriptor's
+ // data are flushed all the way to durable media, and can withstand power
+ // failures.
+ //
+ // The path argument is only used to populate the description string in the
+ // returned Status if an error occurs.
+ static Status SyncFd(int fd, const std::string& fd_path, bool syncing_dir) {
+#if HAVE_FULLFSYNC
+ // On macOS and iOS, fsync() doesn't guarantee durability past power
+ // failures. fcntl(F_FULLFSYNC) is required for that purpose. Some
+ // filesystems don't support fcntl(F_FULLFSYNC), and require a fallback to
+ // fsync().
+ if (::fcntl(fd, F_FULLFSYNC) == 0) {
+ return Status::OK();
}
- Status s;
- if (basename.starts_with("MANIFEST")) {
- int fd = open(dir.c_str(), O_RDONLY);
- if (fd < 0) {
- s = IOError(dir, errno);
- } else {
- if (fsync(fd) < 0 && errno != EINVAL) {
- s = IOError(dir, errno);
- }
- close(fd);
- }
+#endif // HAVE_FULLFSYNC
+
+#if HAVE_FDATASYNC
+ bool sync_success = ::fdatasync(fd) == 0;
+#else
+ bool sync_success = ::fsync(fd) == 0;
+#endif // HAVE_FDATASYNC
+
+ if (sync_success) {
+ return Status::OK();
}
- return s;
+ // Do not crash if filesystem can't fsync directories
+ // (see https://github.com/bitcoin/bitcoin/pull/10000)
+ if (syncing_dir && errno == EINVAL) {
+ return Status::OK();
+ }
+ return PosixError(fd_path, errno);
}
- virtual Status Sync() {
- // Ensure new files referred to by the manifest are in the filesystem.
- Status s = SyncDirIfManifest();
- if (!s.ok()) {
- return s;
+ // Returns the directory name in a path pointing to a file.
+ //
+ // Returns "." if the path does not contain any directory separator.
+ static std::string Dirname(const std::string& filename) {
+ std::string::size_type separator_pos = filename.rfind('/');
+ if (separator_pos == std::string::npos) {
+ return std::string(".");
}
- if (fflush_unlocked(file_) != 0 ||
- fdatasync(fileno(file_)) != 0) {
- s = Status::IOError(filename_, strerror(errno));
+ // The filename component should not contain a path separator. If it does,
+ // the splitting was done incorrectly.
+ assert(filename.find('/', separator_pos + 1) == std::string::npos);
+
+ return filename.substr(0, separator_pos);
+ }
+
+ // Extracts the file name from a path pointing to a file.
+ //
+ // The returned Slice points to |filename|'s data buffer, so it is only valid
+ // while |filename| is alive and unchanged.
+ static Slice Basename(const std::string& filename) {
+ std::string::size_type separator_pos = filename.rfind('/');
+ if (separator_pos == std::string::npos) {
+ return Slice(filename);
}
- return s;
+ // The filename component should not contain a path separator. If it does,
+ // the splitting was done incorrectly.
+ assert(filename.find('/', separator_pos + 1) == std::string::npos);
+
+ return Slice(filename.data() + separator_pos + 1,
+ filename.length() - separator_pos - 1);
}
- virtual std::string GetName() const { return filename_; }
+ // True if the given file is a manifest file.
+ static bool IsManifest(const std::string& filename) {
+ return Basename(filename).starts_with("MANIFEST");
+ }
+
+ virtual std::string GetName() const override { return filename_; }
+
+ // buf_[0, pos_ - 1] contains data to be written to fd_.
+ char buf_[kWritableFileBufferSize];
+ size_t pos_;
+ int fd_;
+
+ const bool is_manifest_; // True if the file's name starts with MANIFEST.
+ const std::string filename_;
+ const std::string dirname_; // The directory of filename_.
};
-static int LockOrUnlock(int fd, bool lock) {
+int LockOrUnlock(int fd, bool lock) {
errno = 0;
- struct flock f;
- memset(&f, 0, sizeof(f));
- f.l_type = (lock ? F_WRLCK : F_UNLCK);
- f.l_whence = SEEK_SET;
- f.l_start = 0;
- f.l_len = 0; // Lock/unlock entire file
- return fcntl(fd, F_SETLK, &f);
+ struct ::flock file_lock_info;
+ std::memset(&file_lock_info, 0, sizeof(file_lock_info));
+ file_lock_info.l_type = (lock ? F_WRLCK : F_UNLCK);
+ file_lock_info.l_whence = SEEK_SET;
+ file_lock_info.l_start = 0;
+ file_lock_info.l_len = 0; // Lock/unlock entire file.
+ return ::fcntl(fd, F_SETLK, &file_lock_info);
}
+// Instances are thread-safe because they are immutable.
class PosixFileLock : public FileLock {
public:
- int fd_;
- std::string name_;
+ PosixFileLock(int fd, std::string filename)
+ : fd_(fd), filename_(std::move(filename)) {}
+
+ int fd() const { return fd_; }
+ const std::string& filename() const { return filename_; }
+
+ private:
+ const int fd_;
+ const std::string filename_;
};
-// Set of locked files. We keep a separate set instead of just
-// relying on fcntrl(F_SETLK) since fcntl(F_SETLK) does not provide
-// any protection against multiple uses from the same process.
+// Tracks the files locked by PosixEnv::LockFile().
+//
+// We maintain a separate set instead of relying on fcntl(F_SETLK) because
+// fcntl(F_SETLK) does not provide any protection against multiple uses from the
+// same process.
+//
+// Instances are thread-safe because all member data is guarded by a mutex.
class PosixLockTable {
- private:
- port::Mutex mu_;
- std::set<std::string> locked_files_;
public:
- bool Insert(const std::string& fname) {
- MutexLock l(&mu_);
- return locked_files_.insert(fname).second;
- }
- void Remove(const std::string& fname) {
- MutexLock l(&mu_);
+ bool Insert(const std::string& fname) LOCKS_EXCLUDED(mu_) {
+ mu_.Lock();
+ bool succeeded = locked_files_.insert(fname).second;
+ mu_.Unlock();
+ return succeeded;
+ }
+ void Remove(const std::string& fname) LOCKS_EXCLUDED(mu_) {
+ mu_.Lock();
locked_files_.erase(fname);
+ mu_.Unlock();
}
+
+ private:
+ port::Mutex mu_;
+ std::set<std::string> locked_files_ GUARDED_BY(mu_);
};
class PosixEnv : public Env {
public:
PosixEnv();
- virtual ~PosixEnv() {
- char msg[] = "Destroying Env::Default()\n";
- fwrite(msg, 1, sizeof(msg), stderr);
- abort();
- }
-
- virtual Status NewSequentialFile(const std::string& fname,
- SequentialFile** result) {
- FILE* f = fopen(fname.c_str(), "r");
- if (f == NULL) {
- *result = NULL;
- return IOError(fname, errno);
- } else {
- *result = new PosixSequentialFile(fname, f);
- return Status::OK();
+ ~PosixEnv() override {
+ static const char msg[] =
+ "PosixEnv singleton destroyed. Unsupported behavior!\n";
+ std::fwrite(msg, 1, sizeof(msg), stderr);
+ std::abort();
+ }
+
+ Status NewSequentialFile(const std::string& filename,
+ SequentialFile** result) override {
+ int fd = ::open(filename.c_str(), O_RDONLY | kOpenBaseFlags);
+ if (fd < 0) {
+ *result = nullptr;
+ return PosixError(filename, errno);
}
+
+ *result = new PosixSequentialFile(filename, fd);
+ return Status::OK();
}
- virtual Status NewRandomAccessFile(const std::string& fname,
- RandomAccessFile** result) {
- *result = NULL;
- Status s;
- int fd = open(fname.c_str(), O_RDONLY);
+ Status NewRandomAccessFile(const std::string& filename,
+ RandomAccessFile** result) override {
+ *result = nullptr;
+ int fd = ::open(filename.c_str(), O_RDONLY | kOpenBaseFlags);
if (fd < 0) {
- s = IOError(fname, errno);
- } else if (mmap_limit_.Acquire()) {
- uint64_t size;
- s = GetFileSize(fname, &size);
- if (s.ok()) {
- void* base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
- if (base != MAP_FAILED) {
- *result = new PosixMmapReadableFile(fname, base, size, &mmap_limit_);
- } else {
- s = IOError(fname, errno);
- }
- }
- close(fd);
- if (!s.ok()) {
- mmap_limit_.Release();
+ return PosixError(filename, errno);
+ }
+
+ if (!mmap_limiter_.Acquire()) {
+ *result = new PosixRandomAccessFile(filename, fd, &fd_limiter_);
+ return Status::OK();
+ }
+
+ uint64_t file_size;
+ Status status = GetFileSize(filename, &file_size);
+ if (status.ok()) {
+ void* mmap_base =
+ ::mmap(/*addr=*/nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (mmap_base != MAP_FAILED) {
+ *result = new PosixMmapReadableFile(filename,
+ reinterpret_cast<char*>(mmap_base),
+ file_size, &mmap_limiter_);
+ } else {
+ status = PosixError(filename, errno);
}
- } else {
- *result = new PosixRandomAccessFile(fname, fd, &fd_limit_);
}
- return s;
+ ::close(fd);
+ if (!status.ok()) {
+ mmap_limiter_.Release();
+ }
+ return status;
}
- virtual Status NewWritableFile(const std::string& fname,
- WritableFile** result) {
- Status s;
- FILE* f = fopen(fname.c_str(), "w");
- if (f == NULL) {
- *result = NULL;
- s = IOError(fname, errno);
- } else {
- *result = new PosixWritableFile(fname, f);
+ Status NewWritableFile(const std::string& filename,
+ WritableFile** result) override {
+ int fd = ::open(filename.c_str(),
+ O_TRUNC | O_WRONLY | O_CREAT | kOpenBaseFlags, 0644);
+ if (fd < 0) {
+ *result = nullptr;
+ return PosixError(filename, errno);
}
- return s;
+
+ *result = new PosixWritableFile(filename, fd);
+ return Status::OK();
}
- virtual Status NewAppendableFile(const std::string& fname,
- WritableFile** result) {
- Status s;
- FILE* f = fopen(fname.c_str(), "a");
- if (f == NULL) {
- *result = NULL;
- s = IOError(fname, errno);
- } else {
- *result = new PosixWritableFile(fname, f);
+ Status NewAppendableFile(const std::string& filename,
+ WritableFile** result) override {
+ int fd = ::open(filename.c_str(),
+ O_APPEND | O_WRONLY | O_CREAT | kOpenBaseFlags, 0644);
+ if (fd < 0) {
+ *result = nullptr;
+ return PosixError(filename, errno);
}
- return s;
+
+ *result = new PosixWritableFile(filename, fd);
+ return Status::OK();
}
- virtual bool FileExists(const std::string& fname) {
- return access(fname.c_str(), F_OK) == 0;
+ bool FileExists(const std::string& filename) override {
+ return ::access(filename.c_str(), F_OK) == 0;
}
- virtual Status GetChildren(const std::string& dir,
- std::vector<std::string>* result) {
+ Status GetChildren(const std::string& directory_path,
+ std::vector<std::string>* result) override {
result->clear();
- DIR* d = opendir(dir.c_str());
- if (d == NULL) {
- return IOError(dir, errno);
+ ::DIR* dir = ::opendir(directory_path.c_str());
+ if (dir == nullptr) {
+ return PosixError(directory_path, errno);
}
- struct dirent* entry;
- while ((entry = readdir(d)) != NULL) {
- result->push_back(entry->d_name);
+ struct ::dirent* entry;
+ while ((entry = ::readdir(dir)) != nullptr) {
+ result->emplace_back(entry->d_name);
}
- closedir(d);
+ ::closedir(dir);
return Status::OK();
}
- virtual Status DeleteFile(const std::string& fname) {
- Status result;
- if (unlink(fname.c_str()) != 0) {
- result = IOError(fname, errno);
+ Status DeleteFile(const std::string& filename) override {
+ if (::unlink(filename.c_str()) != 0) {
+ return PosixError(filename, errno);
}
- return result;
+ return Status::OK();
}
- virtual Status CreateDir(const std::string& name) {
- Status result;
- if (mkdir(name.c_str(), 0755) != 0) {
- result = IOError(name, errno);
+ Status CreateDir(const std::string& dirname) override {
+ if (::mkdir(dirname.c_str(), 0755) != 0) {
+ return PosixError(dirname, errno);
}
- return result;
+ return Status::OK();
}
- virtual Status DeleteDir(const std::string& name) {
- Status result;
- if (rmdir(name.c_str()) != 0) {
- result = IOError(name, errno);
+ Status DeleteDir(const std::string& dirname) override {
+ if (::rmdir(dirname.c_str()) != 0) {
+ return PosixError(dirname, errno);
}
- return result;
+ return Status::OK();
}
- virtual Status GetFileSize(const std::string& fname, uint64_t* size) {
- Status s;
- struct stat sbuf;
- if (stat(fname.c_str(), &sbuf) != 0) {
+ Status GetFileSize(const std::string& filename, uint64_t* size) override {
+ struct ::stat file_stat;
+ if (::stat(filename.c_str(), &file_stat) != 0) {
*size = 0;
- s = IOError(fname, errno);
- } else {
- *size = sbuf.st_size;
+ return PosixError(filename, errno);
}
- return s;
+ *size = file_stat.st_size;
+ return Status::OK();
}
- virtual Status RenameFile(const std::string& src, const std::string& target) {
- Status result;
- if (rename(src.c_str(), target.c_str()) != 0) {
- result = IOError(src, errno);
+ Status RenameFile(const std::string& from, const std::string& to) override {
+ if (std::rename(from.c_str(), to.c_str()) != 0) {
+ return PosixError(from, errno);
}
- return result;
+ return Status::OK();
}
- virtual Status LockFile(const std::string& fname, FileLock** lock) {
- *lock = NULL;
- Status result;
- int fd = open(fname.c_str(), O_RDWR | O_CREAT, 0644);
+ Status LockFile(const std::string& filename, FileLock** lock) override {
+ *lock = nullptr;
+
+ int fd = ::open(filename.c_str(), O_RDWR | O_CREAT | kOpenBaseFlags, 0644);
if (fd < 0) {
- result = IOError(fname, errno);
- } else if (!locks_.Insert(fname)) {
- close(fd);
- result = Status::IOError("lock " + fname, "already held by process");
- } else if (LockOrUnlock(fd, true) == -1) {
- result = IOError("lock " + fname, errno);
- close(fd);
- locks_.Remove(fname);
- } else {
- PosixFileLock* my_lock = new PosixFileLock;
- my_lock->fd_ = fd;
- my_lock->name_ = fname;
- *lock = my_lock;
+ return PosixError(filename, errno);
}
- return result;
+
+ if (!locks_.Insert(filename)) {
+ ::close(fd);
+ return Status::IOError("lock " + filename, "already held by process");
+ }
+
+ if (LockOrUnlock(fd, true) == -1) {
+ int lock_errno = errno;
+ ::close(fd);
+ locks_.Remove(filename);
+ return PosixError("lock " + filename, lock_errno);
+ }
+
+ *lock = new PosixFileLock(fd, filename);
+ return Status::OK();
}
- virtual Status UnlockFile(FileLock* lock) {
- PosixFileLock* my_lock = reinterpret_cast<PosixFileLock*>(lock);
- Status result;
- if (LockOrUnlock(my_lock->fd_, false) == -1) {
- result = IOError("unlock", errno);
+ Status UnlockFile(FileLock* lock) override {
+ PosixFileLock* posix_file_lock = static_cast<PosixFileLock*>(lock);
+ if (LockOrUnlock(posix_file_lock->fd(), false) == -1) {
+ return PosixError("unlock " + posix_file_lock->filename(), errno);
}
- locks_.Remove(my_lock->name_);
- close(my_lock->fd_);
- delete my_lock;
- return result;
+ locks_.Remove(posix_file_lock->filename());
+ ::close(posix_file_lock->fd());
+ delete posix_file_lock;
+ return Status::OK();
}
- virtual void Schedule(void (*function)(void*), void* arg);
+ void Schedule(void (*background_work_function)(void* background_work_arg),
+ void* background_work_arg) override;
- virtual void StartThread(void (*function)(void* arg), void* arg);
+ void StartThread(void (*thread_main)(void* thread_main_arg),
+ void* thread_main_arg) override {
+ std::thread new_thread(thread_main, thread_main_arg);
+ new_thread.detach();
+ }
- virtual Status GetTestDirectory(std::string* result) {
- const char* env = getenv("TEST_TMPDIR");
+ Status GetTestDirectory(std::string* result) override {
+ const char* env = std::getenv("TEST_TMPDIR");
if (env && env[0] != '\0') {
*result = env;
} else {
char buf[100];
- snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d", int(geteuid()));
+ std::snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d",
+ static_cast<int>(::geteuid()));
*result = buf;
}
- // Directory may already exist
+
+ // The CreateDir status is ignored because the directory may already exist.
CreateDir(*result);
+
return Status::OK();
}
- static uint64_t gettid() {
- pthread_t tid = pthread_self();
- uint64_t thread_id = 0;
- memcpy(&thread_id, &tid, std::min(sizeof(thread_id), sizeof(tid)));
- return thread_id;
- }
+ Status NewLogger(const std::string& filename, Logger** result) override {
+ int fd = ::open(filename.c_str(),
+ O_APPEND | O_WRONLY | O_CREAT | kOpenBaseFlags, 0644);
+ if (fd < 0) {
+ *result = nullptr;
+ return PosixError(filename, errno);
+ }
- virtual Status NewLogger(const std::string& fname, Logger** result) {
- FILE* f = fopen(fname.c_str(), "w");
- if (f == NULL) {
- *result = NULL;
- return IOError(fname, errno);
+ std::FILE* fp = ::fdopen(fd, "w");
+ if (fp == nullptr) {
+ ::close(fd);
+ *result = nullptr;
+ return PosixError(filename, errno);
} else {
- *result = new PosixLogger(f, &PosixEnv::gettid);
+ *result = new PosixLogger(fp);
return Status::OK();
}
}
- virtual uint64_t NowMicros() {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return static_cast<uint64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
+ uint64_t NowMicros() override {
+ static constexpr uint64_t kUsecondsPerSecond = 1000000;
+ struct ::timeval tv;
+ ::gettimeofday(&tv, nullptr);
+ return static_cast<uint64_t>(tv.tv_sec) * kUsecondsPerSecond + tv.tv_usec;
}
- virtual void SleepForMicroseconds(int micros) {
- usleep(micros);
+ void SleepForMicroseconds(int micros) override {
+ std::this_thread::sleep_for(std::chrono::microseconds(micros));
}
private:
- void PthreadCall(const char* label, int result) {
- if (result != 0) {
- fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
- abort();
- }
- }
+ void BackgroundThreadMain();
- // BGThread() is the body of the background thread
- void BGThread();
- static void* BGThreadWrapper(void* arg) {
- reinterpret_cast<PosixEnv*>(arg)->BGThread();
- return NULL;
+ static void BackgroundThreadEntryPoint(PosixEnv* env) {
+ env->BackgroundThreadMain();
}
- pthread_mutex_t mu_;
- pthread_cond_t bgsignal_;
- pthread_t bgthread_;
- bool started_bgthread_;
+ // Stores the work item data in a Schedule() call.
+ //
+ // Instances are constructed on the thread calling Schedule() and used on the
+ // background thread.
+ //
+ // This structure is thread-safe beacuse it is immutable.
+ struct BackgroundWorkItem {
+ explicit BackgroundWorkItem(void (*function)(void* arg), void* arg)
+ : function(function), arg(arg) {}
+
+ void (*const function)(void*);
+ void* const arg;
+ };
- // Entry per Schedule() call
- struct BGItem { void* arg; void (*function)(void*); };
- typedef std::deque<BGItem> BGQueue;
- BGQueue queue_;
+ port::Mutex background_work_mutex_;
+ port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_);
+ bool started_background_thread_ GUARDED_BY(background_work_mutex_);
- PosixLockTable locks_;
- Limiter mmap_limit_;
- Limiter fd_limit_;
+ std::queue<BackgroundWorkItem> background_work_queue_
+ GUARDED_BY(background_work_mutex_);
+
+ PosixLockTable locks_; // Thread-safe.
+ Limiter mmap_limiter_; // Thread-safe.
+ Limiter fd_limiter_; // Thread-safe.
};
// Return the maximum number of concurrent mmaps.
-static int MaxMmaps() {
- if (mmap_limit >= 0) {
- return mmap_limit;
- }
- // Up to 4096 mmaps for 64-bit binaries; none for smaller pointer sizes.
- mmap_limit = sizeof(void*) >= 8 ? 4096 : 0;
- return mmap_limit;
-}
+int MaxMmaps() { return g_mmap_limit; }
// Return the maximum number of read-only files to keep open.
-static intptr_t MaxOpenFiles() {
- if (open_read_only_file_limit >= 0) {
- return open_read_only_file_limit;
+int MaxOpenFiles() {
+ if (g_open_read_only_file_limit >= 0) {
+ return g_open_read_only_file_limit;
}
- struct rlimit rlim;
- if (getrlimit(RLIMIT_NOFILE, &rlim)) {
+ struct ::rlimit rlim;
+ if (::getrlimit(RLIMIT_NOFILE, &rlim)) {
// getrlimit failed, fallback to hard-coded default.
- open_read_only_file_limit = 50;
+ g_open_read_only_file_limit = 50;
} else if (rlim.rlim_cur == RLIM_INFINITY) {
- open_read_only_file_limit = std::numeric_limits<int>::max();
+ g_open_read_only_file_limit = std::numeric_limits<int>::max();
} else {
// Allow use of 20% of available file descriptors for read-only files.
- open_read_only_file_limit = rlim.rlim_cur / 5;
+ g_open_read_only_file_limit = rlim.rlim_cur / 5;
}
- return open_read_only_file_limit;
+ return g_open_read_only_file_limit;
}
+} // namespace
+
PosixEnv::PosixEnv()
- : started_bgthread_(false),
- mmap_limit_(MaxMmaps()),
- fd_limit_(MaxOpenFiles()) {
- PthreadCall("mutex_init", pthread_mutex_init(&mu_, NULL));
- PthreadCall("cvar_init", pthread_cond_init(&bgsignal_, NULL));
-}
+ : background_work_cv_(&background_work_mutex_),
+ started_background_thread_(false),
+ mmap_limiter_(MaxMmaps()),
+ fd_limiter_(MaxOpenFiles()) {}
-void PosixEnv::Schedule(void (*function)(void*), void* arg) {
- PthreadCall("lock", pthread_mutex_lock(&mu_));
+void PosixEnv::Schedule(
+ void (*background_work_function)(void* background_work_arg),
+ void* background_work_arg) {
+ background_work_mutex_.Lock();
- // Start background thread if necessary
- if (!started_bgthread_) {
- started_bgthread_ = true;
- PthreadCall(
- "create thread",
- pthread_create(&bgthread_, NULL, &PosixEnv::BGThreadWrapper, this));
+ // Start the background thread, if we haven't done so already.
+ if (!started_background_thread_) {
+ started_background_thread_ = true;
+ std::thread background_thread(PosixEnv::BackgroundThreadEntryPoint, this);
+ background_thread.detach();
}
- // If the queue is currently empty, the background thread may currently be
- // waiting.
- if (queue_.empty()) {
- PthreadCall("signal", pthread_cond_signal(&bgsignal_));
+ // If the queue is empty, the background thread may be waiting for work.
+ if (background_work_queue_.empty()) {
+ background_work_cv_.Signal();
}
- // Add to priority queue
- queue_.push_back(BGItem());
- queue_.back().function = function;
- queue_.back().arg = arg;
-
- PthreadCall("unlock", pthread_mutex_unlock(&mu_));
+ background_work_queue_.emplace(background_work_function, background_work_arg);
+ background_work_mutex_.Unlock();
}
-void PosixEnv::BGThread() {
+void PosixEnv::BackgroundThreadMain() {
while (true) {
- // Wait until there is an item that is ready to run
- PthreadCall("lock", pthread_mutex_lock(&mu_));
- while (queue_.empty()) {
- PthreadCall("wait", pthread_cond_wait(&bgsignal_, &mu_));
+ background_work_mutex_.Lock();
+
+ // Wait until there is work to be done.
+ while (background_work_queue_.empty()) {
+ background_work_cv_.Wait();
}
- void (*function)(void*) = queue_.front().function;
- void* arg = queue_.front().arg;
- queue_.pop_front();
+ assert(!background_work_queue_.empty());
+ auto background_work_function = background_work_queue_.front().function;
+ void* background_work_arg = background_work_queue_.front().arg;
+ background_work_queue_.pop();
- PthreadCall("unlock", pthread_mutex_unlock(&mu_));
- (*function)(arg);
+ background_work_mutex_.Unlock();
+ background_work_function(background_work_arg);
}
}
namespace {
-struct StartThreadState {
- void (*user_function)(void*);
- void* arg;
+
+// Wraps an Env instance whose destructor is never created.
+//
+// Intended usage:
+// using PlatformSingletonEnv = SingletonEnv<PlatformEnv>;
+// void ConfigurePosixEnv(int param) {
+// PlatformSingletonEnv::AssertEnvNotInitialized();
+// // set global configuration flags.
+// }
+// Env* Env::Default() {
+// static PlatformSingletonEnv default_env;
+// return default_env.env();
+// }
+template <typename EnvType>
+class SingletonEnv {
+ public:
+ SingletonEnv() {
+#if !defined(NDEBUG)
+ env_initialized_.store(true, std::memory_order::memory_order_relaxed);
+#endif // !defined(NDEBUG)
+ static_assert(sizeof(env_storage_) >= sizeof(EnvType),
+ "env_storage_ will not fit the Env");
+ static_assert(alignof(decltype(env_storage_)) >= alignof(EnvType),
+ "env_storage_ does not meet the Env's alignment needs");
+ new (&env_storage_) EnvType();
+ }
+ ~SingletonEnv() = default;
+
+ SingletonEnv(const SingletonEnv&) = delete;
+ SingletonEnv& operator=(const SingletonEnv&) = delete;
+
+ Env* env() { return reinterpret_cast<Env*>(&env_storage_); }
+
+ static void AssertEnvNotInitialized() {
+#if !defined(NDEBUG)
+ assert(!env_initialized_.load(std::memory_order::memory_order_relaxed));
+#endif // !defined(NDEBUG)
+ }
+
+ private:
+ typename std::aligned_storage<sizeof(EnvType), alignof(EnvType)>::type
+ env_storage_;
+#if !defined(NDEBUG)
+ static std::atomic<bool> env_initialized_;
+#endif // !defined(NDEBUG)
};
-}
-static void* StartThreadWrapper(void* arg) {
- StartThreadState* state = reinterpret_cast<StartThreadState*>(arg);
- state->user_function(state->arg);
- delete state;
- return NULL;
-}
-void PosixEnv::StartThread(void (*function)(void* arg), void* arg) {
- pthread_t t;
- StartThreadState* state = new StartThreadState;
- state->user_function = function;
- state->arg = arg;
- PthreadCall("start thread",
- pthread_create(&t, NULL, &StartThreadWrapper, state));
-}
+#if !defined(NDEBUG)
+template <typename EnvType>
+std::atomic<bool> SingletonEnv<EnvType>::env_initialized_;
+#endif // !defined(NDEBUG)
-} // namespace
+using PosixDefaultEnv = SingletonEnv<PosixEnv>;
-static pthread_once_t once = PTHREAD_ONCE_INIT;
-static Env* default_env;
-static void InitDefaultEnv() { default_env = new PosixEnv; }
+} // namespace
void EnvPosixTestHelper::SetReadOnlyFDLimit(int limit) {
- assert(default_env == NULL);
- open_read_only_file_limit = limit;
+ PosixDefaultEnv::AssertEnvNotInitialized();
+ g_open_read_only_file_limit = limit;
}
void EnvPosixTestHelper::SetReadOnlyMMapLimit(int limit) {
- assert(default_env == NULL);
- mmap_limit = limit;
+ PosixDefaultEnv::AssertEnvNotInitialized();
+ g_mmap_limit = limit;
}
Env* Env::Default() {
- pthread_once(&once, InitDefaultEnv);
- return default_env;
+ static PosixDefaultEnv env_container;
+ return env_container.env();
}
} // namespace leveldb
-
-#endif
diff --git a/src/leveldb/util/env_posix_test.cc b/src/leveldb/util/env_posix_test.cc
index 295f8ae440..9675d739ad 100644
--- a/src/leveldb/util/env_posix_test.cc
+++ b/src/leveldb/util/env_posix_test.cc
@@ -2,27 +2,182 @@
// 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.
-#include "leveldb/env.h"
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <unordered_set>
+#include <vector>
+#include "leveldb/env.h"
#include "port/port.h"
-#include "util/testharness.h"
#include "util/env_posix_test_helper.h"
+#include "util/testharness.h"
+
+#if HAVE_O_CLOEXEC
+
+namespace {
+
+// Exit codes for the helper process spawned by TestCloseOnExec* tests.
+// Useful for debugging test failures.
+constexpr int kTextCloseOnExecHelperExecFailedCode = 61;
+constexpr int kTextCloseOnExecHelperDup2FailedCode = 62;
+constexpr int kTextCloseOnExecHelperFoundOpenFdCode = 63;
+
+// Global set by main() and read in TestCloseOnExec.
+//
+// The argv[0] value is stored in a std::vector instead of a std::string because
+// std::string does not return a mutable pointer to its buffer until C++17.
+//
+// The vector stores the string pointed to by argv[0], plus the trailing null.
+std::vector<char>* GetArgvZero() {
+ static std::vector<char> program_name;
+ return &program_name;
+}
+
+// Command-line switch used to run this test as the CloseOnExecSwitch helper.
+static const char kTestCloseOnExecSwitch[] = "--test-close-on-exec-helper";
+
+// Executed in a separate process by TestCloseOnExec* tests.
+//
+// main() delegates to this function when the test executable is launched with
+// a special command-line switch. TestCloseOnExec* tests fork()+exec() the test
+// executable and pass the special command-line switch.
+//
+
+// main() delegates to this function when the test executable is launched with
+// a special command-line switch. TestCloseOnExec* tests fork()+exec() the test
+// executable and pass the special command-line switch.
+//
+// When main() delegates to this function, the process probes whether a given
+// file descriptor is open, and communicates the result via its exit code.
+int TestCloseOnExecHelperMain(char* pid_arg) {
+ int fd = std::atoi(pid_arg);
+ // When given the same file descriptor twice, dup2() returns -1 if the
+ // file descriptor is closed, or the given file descriptor if it is open.
+ if (::dup2(fd, fd) == fd) {
+ std::fprintf(stderr, "Unexpected open fd %d\n", fd);
+ return kTextCloseOnExecHelperFoundOpenFdCode;
+ }
+ // Double-check that dup2() is saying the file descriptor is closed.
+ if (errno != EBADF) {
+ std::fprintf(stderr, "Unexpected errno after calling dup2 on fd %d: %s\n",
+ fd, std::strerror(errno));
+ return kTextCloseOnExecHelperDup2FailedCode;
+ }
+ return 0;
+}
+
+// File descriptors are small non-negative integers.
+//
+// Returns void so the implementation can use ASSERT_EQ.
+void GetMaxFileDescriptor(int* result_fd) {
+ // Get the maximum file descriptor number.
+ ::rlimit fd_rlimit;
+ ASSERT_EQ(0, ::getrlimit(RLIMIT_NOFILE, &fd_rlimit));
+ *result_fd = fd_rlimit.rlim_cur;
+}
+
+// Iterates through all possible FDs and returns the currently open ones.
+//
+// Returns void so the implementation can use ASSERT_EQ.
+void GetOpenFileDescriptors(std::unordered_set<int>* open_fds) {
+ int max_fd = 0;
+ GetMaxFileDescriptor(&max_fd);
+
+ for (int fd = 0; fd < max_fd; ++fd) {
+ if (::dup2(fd, fd) != fd) {
+ // When given the same file descriptor twice, dup2() returns -1 if the
+ // file descriptor is closed, or the given file descriptor if it is open.
+ //
+ // Double-check that dup2() is saying the fd is closed.
+ ASSERT_EQ(EBADF, errno)
+ << "dup2() should set errno to EBADF on closed file descriptors";
+ continue;
+ }
+ open_fds->insert(fd);
+ }
+}
+
+// Finds an FD open since a previous call to GetOpenFileDescriptors().
+//
+// |baseline_open_fds| is the result of a previous GetOpenFileDescriptors()
+// call. Assumes that exactly one FD was opened since that call.
+//
+// Returns void so the implementation can use ASSERT_EQ.
+void GetNewlyOpenedFileDescriptor(
+ const std::unordered_set<int>& baseline_open_fds, int* result_fd) {
+ std::unordered_set<int> open_fds;
+ GetOpenFileDescriptors(&open_fds);
+ for (int fd : baseline_open_fds) {
+ ASSERT_EQ(1, open_fds.count(fd))
+ << "Previously opened file descriptor was closed during test setup";
+ open_fds.erase(fd);
+ }
+ ASSERT_EQ(1, open_fds.size())
+ << "Expected exactly one newly opened file descriptor during test setup";
+ *result_fd = *open_fds.begin();
+}
+
+// Check that a fork()+exec()-ed child process does not have an extra open FD.
+void CheckCloseOnExecDoesNotLeakFDs(
+ const std::unordered_set<int>& baseline_open_fds) {
+ // Prepare the argument list for the child process.
+ // execv() wants mutable buffers.
+ char switch_buffer[sizeof(kTestCloseOnExecSwitch)];
+ std::memcpy(switch_buffer, kTestCloseOnExecSwitch,
+ sizeof(kTestCloseOnExecSwitch));
+
+ int probed_fd;
+ GetNewlyOpenedFileDescriptor(baseline_open_fds, &probed_fd);
+ std::string fd_string = std::to_string(probed_fd);
+ std::vector<char> fd_buffer(fd_string.begin(), fd_string.end());
+ fd_buffer.emplace_back('\0');
+
+ // The helper process is launched with the command below.
+ // env_posix_tests --test-close-on-exec-helper 3
+ char* child_argv[] = {GetArgvZero()->data(), switch_buffer, fd_buffer.data(),
+ nullptr};
+
+ constexpr int kForkInChildProcessReturnValue = 0;
+ int child_pid = fork();
+ if (child_pid == kForkInChildProcessReturnValue) {
+ ::execv(child_argv[0], child_argv);
+ std::fprintf(stderr, "Error spawning child process: %s\n", strerror(errno));
+ std::exit(kTextCloseOnExecHelperExecFailedCode);
+ }
+
+ int child_status = 0;
+ ASSERT_EQ(child_pid, ::waitpid(child_pid, &child_status, 0));
+ ASSERT_TRUE(WIFEXITED(child_status))
+ << "The helper process did not exit with an exit code";
+ ASSERT_EQ(0, WEXITSTATUS(child_status))
+ << "The helper process encountered an error";
+}
+
+} // namespace
+
+#endif // HAVE_O_CLOEXEC
namespace leveldb {
-static const int kDelayMicros = 100000;
static const int kReadOnlyFileLimit = 4;
static const int kMMapLimit = 4;
class EnvPosixTest {
public:
- Env* env_;
- EnvPosixTest() : env_(Env::Default()) { }
-
static void SetFileLimits(int read_only_file_limit, int mmap_limit) {
EnvPosixTestHelper::SetReadOnlyFDLimit(read_only_file_limit);
EnvPosixTestHelper::SetReadOnlyMMapLimit(mmap_limit);
}
+
+ EnvPosixTest() : env_(Env::Default()) {}
+
+ Env* env_;
};
TEST(EnvPosixTest, TestOpenOnRead) {
@@ -31,8 +186,8 @@ TEST(EnvPosixTest, TestOpenOnRead) {
ASSERT_OK(env_->GetTestDirectory(&test_dir));
std::string test_file = test_dir + "/open_on_read.txt";
- FILE* f = fopen(test_file.c_str(), "w");
- ASSERT_TRUE(f != NULL);
+ FILE* f = fopen(test_file.c_str(), "we");
+ ASSERT_TRUE(f != nullptr);
const char kFileData[] = "abcdefghijklmnopqrstuvwxyz";
fputs(kFileData, f);
fclose(f);
@@ -56,9 +211,138 @@ TEST(EnvPosixTest, TestOpenOnRead) {
ASSERT_OK(env_->DeleteFile(test_file));
}
+#if HAVE_O_CLOEXEC
+
+TEST(EnvPosixTest, TestCloseOnExecSequentialFile) {
+ std::unordered_set<int> open_fds;
+ GetOpenFileDescriptors(&open_fds);
+
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string file_path = test_dir + "/close_on_exec_sequential.txt";
+ ASSERT_OK(WriteStringToFile(env_, "0123456789", file_path));
+
+ leveldb::SequentialFile* file = nullptr;
+ ASSERT_OK(env_->NewSequentialFile(file_path, &file));
+ CheckCloseOnExecDoesNotLeakFDs(open_fds);
+ delete file;
+
+ ASSERT_OK(env_->DeleteFile(file_path));
+}
+
+TEST(EnvPosixTest, TestCloseOnExecRandomAccessFile) {
+ std::unordered_set<int> open_fds;
+ GetOpenFileDescriptors(&open_fds);
+
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string file_path = test_dir + "/close_on_exec_random_access.txt";
+ ASSERT_OK(WriteStringToFile(env_, "0123456789", file_path));
+
+ // Exhaust the RandomAccessFile mmap limit. This way, the test
+ // RandomAccessFile instance below is backed by a file descriptor, not by an
+ // mmap region.
+ leveldb::RandomAccessFile* mmapped_files[kReadOnlyFileLimit] = {nullptr};
+ for (int i = 0; i < kReadOnlyFileLimit; i++) {
+ ASSERT_OK(env_->NewRandomAccessFile(file_path, &mmapped_files[i]));
+ }
+
+ leveldb::RandomAccessFile* file = nullptr;
+ ASSERT_OK(env_->NewRandomAccessFile(file_path, &file));
+ CheckCloseOnExecDoesNotLeakFDs(open_fds);
+ delete file;
+
+ for (int i = 0; i < kReadOnlyFileLimit; i++) {
+ delete mmapped_files[i];
+ }
+ ASSERT_OK(env_->DeleteFile(file_path));
+}
+
+TEST(EnvPosixTest, TestCloseOnExecWritableFile) {
+ std::unordered_set<int> open_fds;
+ GetOpenFileDescriptors(&open_fds);
+
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string file_path = test_dir + "/close_on_exec_writable.txt";
+ ASSERT_OK(WriteStringToFile(env_, "0123456789", file_path));
+
+ leveldb::WritableFile* file = nullptr;
+ ASSERT_OK(env_->NewWritableFile(file_path, &file));
+ CheckCloseOnExecDoesNotLeakFDs(open_fds);
+ delete file;
+
+ ASSERT_OK(env_->DeleteFile(file_path));
+}
+
+TEST(EnvPosixTest, TestCloseOnExecAppendableFile) {
+ std::unordered_set<int> open_fds;
+ GetOpenFileDescriptors(&open_fds);
+
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string file_path = test_dir + "/close_on_exec_appendable.txt";
+ ASSERT_OK(WriteStringToFile(env_, "0123456789", file_path));
+
+ leveldb::WritableFile* file = nullptr;
+ ASSERT_OK(env_->NewAppendableFile(file_path, &file));
+ CheckCloseOnExecDoesNotLeakFDs(open_fds);
+ delete file;
+
+ ASSERT_OK(env_->DeleteFile(file_path));
+}
+
+TEST(EnvPosixTest, TestCloseOnExecLockFile) {
+ std::unordered_set<int> open_fds;
+ GetOpenFileDescriptors(&open_fds);
+
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string file_path = test_dir + "/close_on_exec_lock.txt";
+ ASSERT_OK(WriteStringToFile(env_, "0123456789", file_path));
+
+ leveldb::FileLock* lock = nullptr;
+ ASSERT_OK(env_->LockFile(file_path, &lock));
+ CheckCloseOnExecDoesNotLeakFDs(open_fds);
+ ASSERT_OK(env_->UnlockFile(lock));
+
+ ASSERT_OK(env_->DeleteFile(file_path));
+}
+
+TEST(EnvPosixTest, TestCloseOnExecLogger) {
+ std::unordered_set<int> open_fds;
+ GetOpenFileDescriptors(&open_fds);
+
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string file_path = test_dir + "/close_on_exec_logger.txt";
+ ASSERT_OK(WriteStringToFile(env_, "0123456789", file_path));
+
+ leveldb::Logger* file = nullptr;
+ ASSERT_OK(env_->NewLogger(file_path, &file));
+ CheckCloseOnExecDoesNotLeakFDs(open_fds);
+ delete file;
+
+ ASSERT_OK(env_->DeleteFile(file_path));
+}
+
+#endif // HAVE_O_CLOEXEC
+
} // namespace leveldb
int main(int argc, char** argv) {
+#if HAVE_O_CLOEXEC
+ // Check if we're invoked as a helper program, or as the test suite.
+ for (int i = 1; i < argc; ++i) {
+ if (!std::strcmp(argv[i], kTestCloseOnExecSwitch)) {
+ return TestCloseOnExecHelperMain(argv[i + 1]);
+ }
+ }
+
+ // Save argv[0] early, because googletest may modify argv.
+ GetArgvZero()->assign(argv[0], argv[0] + std::strlen(argv[0]) + 1);
+#endif // HAVE_O_CLOEXEC
+
// All tests currently run with the same read-only file limits.
leveldb::EnvPosixTest::SetFileLimits(leveldb::kReadOnlyFileLimit,
leveldb::kMMapLimit);
diff --git a/src/leveldb/util/env_test.cc b/src/leveldb/util/env_test.cc
index 839ae56a1a..7db03fc11c 100644
--- a/src/leveldb/util/env_test.cc
+++ b/src/leveldb/util/env_test.cc
@@ -4,72 +4,144 @@
#include "leveldb/env.h"
+#include <algorithm>
+
#include "port/port.h"
+#include "port/thread_annotations.h"
+#include "util/mutexlock.h"
#include "util/testharness.h"
+#include "util/testutil.h"
namespace leveldb {
static const int kDelayMicros = 100000;
-static const int kReadOnlyFileLimit = 4;
-static const int kMMapLimit = 4;
class EnvTest {
- private:
- port::Mutex mu_;
- std::string events_;
-
public:
+ EnvTest() : env_(Env::Default()) {}
+
Env* env_;
- EnvTest() : env_(Env::Default()) { }
};
-static void SetBool(void* ptr) {
- reinterpret_cast<port::AtomicPointer*>(ptr)->NoBarrier_Store(ptr);
+TEST(EnvTest, ReadWrite) {
+ Random rnd(test::RandomSeed());
+
+ // Get file to use for testing.
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string test_file_name = test_dir + "/open_on_read.txt";
+ WritableFile* writable_file;
+ ASSERT_OK(env_->NewWritableFile(test_file_name, &writable_file));
+
+ // Fill a file with data generated via a sequence of randomly sized writes.
+ static const size_t kDataSize = 10 * 1048576;
+ std::string data;
+ while (data.size() < kDataSize) {
+ int len = rnd.Skewed(18); // Up to 2^18 - 1, but typically much smaller
+ std::string r;
+ test::RandomString(&rnd, len, &r);
+ ASSERT_OK(writable_file->Append(r));
+ data += r;
+ if (rnd.OneIn(10)) {
+ ASSERT_OK(writable_file->Flush());
+ }
+ }
+ ASSERT_OK(writable_file->Sync());
+ ASSERT_OK(writable_file->Close());
+ delete writable_file;
+
+ // Read all data using a sequence of randomly sized reads.
+ SequentialFile* sequential_file;
+ ASSERT_OK(env_->NewSequentialFile(test_file_name, &sequential_file));
+ std::string read_result;
+ std::string scratch;
+ while (read_result.size() < data.size()) {
+ int len = std::min<int>(rnd.Skewed(18), data.size() - read_result.size());
+ scratch.resize(std::max(len, 1)); // at least 1 so &scratch[0] is legal
+ Slice read;
+ ASSERT_OK(sequential_file->Read(len, &read, &scratch[0]));
+ if (len > 0) {
+ ASSERT_GT(read.size(), 0);
+ }
+ ASSERT_LE(read.size(), len);
+ read_result.append(read.data(), read.size());
+ }
+ ASSERT_EQ(read_result, data);
+ delete sequential_file;
}
TEST(EnvTest, RunImmediately) {
- port::AtomicPointer called (NULL);
- env_->Schedule(&SetBool, &called);
- env_->SleepForMicroseconds(kDelayMicros);
- ASSERT_TRUE(called.NoBarrier_Load() != NULL);
+ struct RunState {
+ port::Mutex mu;
+ port::CondVar cvar{&mu};
+ bool called = false;
+
+ static void Run(void* arg) {
+ RunState* state = reinterpret_cast<RunState*>(arg);
+ MutexLock l(&state->mu);
+ ASSERT_EQ(state->called, false);
+ state->called = true;
+ state->cvar.Signal();
+ }
+ };
+
+ RunState state;
+ env_->Schedule(&RunState::Run, &state);
+
+ MutexLock l(&state.mu);
+ while (!state.called) {
+ state.cvar.Wait();
+ }
}
TEST(EnvTest, RunMany) {
- port::AtomicPointer last_id (NULL);
+ struct RunState {
+ port::Mutex mu;
+ port::CondVar cvar{&mu};
+ int last_id = 0;
+ };
+
+ struct Callback {
+ RunState* state_; // Pointer to shared state.
+ const int id_; // Order# for the execution of this callback.
- struct CB {
- port::AtomicPointer* last_id_ptr; // Pointer to shared slot
- uintptr_t id; // Order# for the execution of this callback
+ Callback(RunState* s, int id) : state_(s), id_(id) {}
- CB(port::AtomicPointer* p, int i) : last_id_ptr(p), id(i) { }
+ static void Run(void* arg) {
+ Callback* callback = reinterpret_cast<Callback*>(arg);
+ RunState* state = callback->state_;
- static void Run(void* v) {
- CB* cb = reinterpret_cast<CB*>(v);
- void* cur = cb->last_id_ptr->NoBarrier_Load();
- ASSERT_EQ(cb->id-1, reinterpret_cast<uintptr_t>(cur));
- cb->last_id_ptr->Release_Store(reinterpret_cast<void*>(cb->id));
+ MutexLock l(&state->mu);
+ ASSERT_EQ(state->last_id, callback->id_ - 1);
+ state->last_id = callback->id_;
+ state->cvar.Signal();
}
};
- // Schedule in different order than start time
- CB cb1(&last_id, 1);
- CB cb2(&last_id, 2);
- CB cb3(&last_id, 3);
- CB cb4(&last_id, 4);
- env_->Schedule(&CB::Run, &cb1);
- env_->Schedule(&CB::Run, &cb2);
- env_->Schedule(&CB::Run, &cb3);
- env_->Schedule(&CB::Run, &cb4);
-
- env_->SleepForMicroseconds(kDelayMicros);
- void* cur = last_id.Acquire_Load();
- ASSERT_EQ(4, reinterpret_cast<uintptr_t>(cur));
+ RunState state;
+ Callback callback1(&state, 1);
+ Callback callback2(&state, 2);
+ Callback callback3(&state, 3);
+ Callback callback4(&state, 4);
+ env_->Schedule(&Callback::Run, &callback1);
+ env_->Schedule(&Callback::Run, &callback2);
+ env_->Schedule(&Callback::Run, &callback3);
+ env_->Schedule(&Callback::Run, &callback4);
+
+ MutexLock l(&state.mu);
+ while (state.last_id != 4) {
+ state.cvar.Wait();
+ }
}
struct State {
port::Mutex mu;
- int val;
- int num_running;
+ port::CondVar cvar{&mu};
+
+ int val GUARDED_BY(mu);
+ int num_running GUARDED_BY(mu);
+
+ State(int val, int num_running) : val(val), num_running(num_running) {}
};
static void ThreadBody(void* arg) {
@@ -77,30 +149,89 @@ static void ThreadBody(void* arg) {
s->mu.Lock();
s->val += 1;
s->num_running -= 1;
+ s->cvar.Signal();
s->mu.Unlock();
}
TEST(EnvTest, StartThread) {
- State state;
- state.val = 0;
- state.num_running = 3;
+ State state(0, 3);
for (int i = 0; i < 3; i++) {
env_->StartThread(&ThreadBody, &state);
}
- while (true) {
- state.mu.Lock();
- int num = state.num_running;
- state.mu.Unlock();
- if (num == 0) {
- break;
- }
- env_->SleepForMicroseconds(kDelayMicros);
+
+ MutexLock l(&state.mu);
+ while (state.num_running != 0) {
+ state.cvar.Wait();
}
ASSERT_EQ(state.val, 3);
}
-} // namespace leveldb
+TEST(EnvTest, TestOpenNonExistentFile) {
+ // Write some test data to a single file that will be opened |n| times.
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+
+ std::string non_existent_file = test_dir + "/non_existent_file";
+ ASSERT_TRUE(!env_->FileExists(non_existent_file));
+
+ RandomAccessFile* random_access_file;
+ Status status =
+ env_->NewRandomAccessFile(non_existent_file, &random_access_file);
+ ASSERT_TRUE(status.IsNotFound());
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
+ SequentialFile* sequential_file;
+ status = env_->NewSequentialFile(non_existent_file, &sequential_file);
+ ASSERT_TRUE(status.IsNotFound());
}
+
+TEST(EnvTest, ReopenWritableFile) {
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string test_file_name = test_dir + "/reopen_writable_file.txt";
+ env_->DeleteFile(test_file_name);
+
+ WritableFile* writable_file;
+ ASSERT_OK(env_->NewWritableFile(test_file_name, &writable_file));
+ std::string data("hello world!");
+ ASSERT_OK(writable_file->Append(data));
+ ASSERT_OK(writable_file->Close());
+ delete writable_file;
+
+ ASSERT_OK(env_->NewWritableFile(test_file_name, &writable_file));
+ data = "42";
+ ASSERT_OK(writable_file->Append(data));
+ ASSERT_OK(writable_file->Close());
+ delete writable_file;
+
+ ASSERT_OK(ReadFileToString(env_, test_file_name, &data));
+ ASSERT_EQ(std::string("42"), data);
+ env_->DeleteFile(test_file_name);
+}
+
+TEST(EnvTest, ReopenAppendableFile) {
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string test_file_name = test_dir + "/reopen_appendable_file.txt";
+ env_->DeleteFile(test_file_name);
+
+ WritableFile* appendable_file;
+ ASSERT_OK(env_->NewAppendableFile(test_file_name, &appendable_file));
+ std::string data("hello world!");
+ ASSERT_OK(appendable_file->Append(data));
+ ASSERT_OK(appendable_file->Close());
+ delete appendable_file;
+
+ ASSERT_OK(env_->NewAppendableFile(test_file_name, &appendable_file));
+ data = "42";
+ ASSERT_OK(appendable_file->Append(data));
+ ASSERT_OK(appendable_file->Close());
+ delete appendable_file;
+
+ ASSERT_OK(ReadFileToString(env_, test_file_name, &data));
+ ASSERT_EQ(std::string("hello world!42"), data);
+ env_->DeleteFile(test_file_name);
+}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/env_win.cc b/src/leveldb/util/env_win.cc
deleted file mode 100644
index 830332abe9..0000000000
--- a/src/leveldb/util/env_win.cc
+++ /dev/null
@@ -1,902 +0,0 @@
-// This file contains source that originates from:
-// http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/env_win32.h
-// http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/port_win32.cc
-// Those files don't have any explicit license headers but the
-// project (http://code.google.com/p/leveldbwin/) lists the 'New BSD License'
-// as the license.
-#if defined(LEVELDB_PLATFORM_WINDOWS)
-#include <map>
-
-
-#include "leveldb/env.h"
-
-#include "port/port.h"
-#include "leveldb/slice.h"
-#include "util/logging.h"
-
-#include <shlwapi.h>
-#include <process.h>
-#include <cstring>
-#include <stdio.h>
-#include <errno.h>
-#include <io.h>
-#include <algorithm>
-
-#ifdef max
-#undef max
-#endif
-
-#ifndef va_copy
-#define va_copy(d,s) ((d) = (s))
-#endif
-
-#if defined DeleteFile
-#undef DeleteFile
-#endif
-
-//Declarations
-namespace leveldb
-{
-
-namespace Win32
-{
-
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
-std::string GetCurrentDir();
-std::wstring GetCurrentDirW();
-
-static const std::string CurrentDir = GetCurrentDir();
-static const std::wstring CurrentDirW = GetCurrentDirW();
-
-std::string& ModifyPath(std::string& path);
-std::wstring& ModifyPath(std::wstring& path);
-
-std::string GetLastErrSz();
-std::wstring GetLastErrSzW();
-
-size_t GetPageSize();
-
-typedef void (*ScheduleProc)(void*) ;
-
-struct WorkItemWrapper
-{
- WorkItemWrapper(ScheduleProc proc_,void* content_);
- ScheduleProc proc;
- void* pContent;
-};
-
-DWORD WINAPI WorkItemWrapperProc(LPVOID pContent);
-
-class Win32SequentialFile : public SequentialFile
-{
-public:
- friend class Win32Env;
- virtual ~Win32SequentialFile();
- virtual Status Read(size_t n, Slice* result, char* scratch);
- virtual Status Skip(uint64_t n);
- BOOL isEnable();
- virtual std::string GetName() const { return _filename; }
-private:
- BOOL _Init();
- void _CleanUp();
- Win32SequentialFile(const std::string& fname);
- std::string _filename;
- ::HANDLE _hFile;
- DISALLOW_COPY_AND_ASSIGN(Win32SequentialFile);
-};
-
-class Win32RandomAccessFile : public RandomAccessFile
-{
-public:
- friend class Win32Env;
- virtual ~Win32RandomAccessFile();
- virtual Status Read(uint64_t offset, size_t n, Slice* result,char* scratch) const;
- BOOL isEnable();
- virtual std::string GetName() const { return _filename; }
-private:
- BOOL _Init(LPCWSTR path);
- void _CleanUp();
- Win32RandomAccessFile(const std::string& fname);
- HANDLE _hFile;
- const std::string _filename;
- DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile);
-};
-
-class Win32WritableFile : public WritableFile
-{
-public:
- Win32WritableFile(const std::string& fname, bool append);
- ~Win32WritableFile();
-
- virtual Status Append(const Slice& data);
- virtual Status Close();
- virtual Status Flush();
- virtual Status Sync();
- BOOL isEnable();
- virtual std::string GetName() const { return filename_; }
-private:
- std::string filename_;
- ::HANDLE _hFile;
-};
-
-class Win32FileLock : public FileLock
-{
-public:
- friend class Win32Env;
- virtual ~Win32FileLock();
- BOOL isEnable();
-private:
- BOOL _Init(LPCWSTR path);
- void _CleanUp();
- Win32FileLock(const std::string& fname);
- HANDLE _hFile;
- std::string _filename;
- DISALLOW_COPY_AND_ASSIGN(Win32FileLock);
-};
-
-class Win32Logger : public Logger
-{
-public:
- friend class Win32Env;
- virtual ~Win32Logger();
- virtual void Logv(const char* format, va_list ap);
-private:
- explicit Win32Logger(WritableFile* pFile);
- WritableFile* _pFileProxy;
- DISALLOW_COPY_AND_ASSIGN(Win32Logger);
-};
-
-class Win32Env : public Env
-{
-public:
- Win32Env();
- virtual ~Win32Env();
- virtual Status NewSequentialFile(const std::string& fname,
- SequentialFile** result);
-
- virtual Status NewRandomAccessFile(const std::string& fname,
- RandomAccessFile** result);
- virtual Status NewWritableFile(const std::string& fname,
- WritableFile** result);
- virtual Status NewAppendableFile(const std::string& fname,
- WritableFile** result);
-
- virtual bool FileExists(const std::string& fname);
-
- virtual Status GetChildren(const std::string& dir,
- std::vector<std::string>* result);
-
- virtual Status DeleteFile(const std::string& fname);
-
- virtual Status CreateDir(const std::string& dirname);
-
- virtual Status DeleteDir(const std::string& dirname);
-
- virtual Status GetFileSize(const std::string& fname, uint64_t* file_size);
-
- virtual Status RenameFile(const std::string& src,
- const std::string& target);
-
- virtual Status LockFile(const std::string& fname, FileLock** lock);
-
- virtual Status UnlockFile(FileLock* lock);
-
- virtual void Schedule(
- void (*function)(void* arg),
- void* arg);
-
- virtual void StartThread(void (*function)(void* arg), void* arg);
-
- virtual Status GetTestDirectory(std::string* path);
-
- //virtual void Logv(WritableFile* log, const char* format, va_list ap);
-
- virtual Status NewLogger(const std::string& fname, Logger** result);
-
- virtual uint64_t NowMicros();
-
- virtual void SleepForMicroseconds(int micros);
-};
-
-void ToWidePath(const std::string& value, std::wstring& target) {
- wchar_t buffer[MAX_PATH];
- MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, buffer, MAX_PATH);
- target = buffer;
-}
-
-void ToNarrowPath(const std::wstring& value, std::string& target) {
- char buffer[MAX_PATH];
- WideCharToMultiByte(CP_UTF8, 0, value.c_str(), -1, buffer, MAX_PATH, NULL, NULL);
- target = buffer;
-}
-
-std::wstring GetCurrentDirW()
-{
- WCHAR path[MAX_PATH];
- ::GetModuleFileNameW(::GetModuleHandleW(NULL),path,MAX_PATH);
- *wcsrchr(path,L'\\') = 0;
- return std::wstring(path);
-}
-
-std::string GetCurrentDir()
-{
- std::string path;
- ToNarrowPath(GetCurrentDirW(), path);
- return path;
-}
-
-std::string& ModifyPath(std::string& path)
-{
- if(path[0] == '/' || path[0] == '\\'){
- path = CurrentDir + path;
- }
- std::replace(path.begin(),path.end(),'/','\\');
-
- return path;
-}
-
-std::wstring& ModifyPath(std::wstring& path)
-{
- if(path[0] == L'/' || path[0] == L'\\'){
- path = CurrentDirW + path;
- }
- std::replace(path.begin(),path.end(),L'/',L'\\');
- return path;
-}
-
-std::string GetLastErrSz()
-{
- LPWSTR lpMsgBuf;
- FormatMessageW(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- 0, // Default language
- (LPWSTR) &lpMsgBuf,
- 0,
- NULL
- );
- std::string Err;
- ToNarrowPath(lpMsgBuf, Err);
- LocalFree( lpMsgBuf );
- return Err;
-}
-
-std::wstring GetLastErrSzW()
-{
- LPVOID lpMsgBuf;
- FormatMessageW(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- 0, // Default language
- (LPWSTR) &lpMsgBuf,
- 0,
- NULL
- );
- std::wstring Err = (LPCWSTR)lpMsgBuf;
- LocalFree(lpMsgBuf);
- return Err;
-}
-
-WorkItemWrapper::WorkItemWrapper( ScheduleProc proc_,void* content_ ) :
- proc(proc_),pContent(content_)
-{
-
-}
-
-DWORD WINAPI WorkItemWrapperProc(LPVOID pContent)
-{
- WorkItemWrapper* item = static_cast<WorkItemWrapper*>(pContent);
- ScheduleProc TempProc = item->proc;
- void* arg = item->pContent;
- delete item;
- TempProc(arg);
- return 0;
-}
-
-size_t GetPageSize()
-{
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- return std::max(si.dwPageSize,si.dwAllocationGranularity);
-}
-
-const size_t g_PageSize = GetPageSize();
-
-
-Win32SequentialFile::Win32SequentialFile( const std::string& fname ) :
- _filename(fname),_hFile(NULL)
-{
- _Init();
-}
-
-Win32SequentialFile::~Win32SequentialFile()
-{
- _CleanUp();
-}
-
-Status Win32SequentialFile::Read( size_t n, Slice* result, char* scratch )
-{
- Status sRet;
- DWORD hasRead = 0;
- if(_hFile && ReadFile(_hFile,scratch,n,&hasRead,NULL) ){
- *result = Slice(scratch,hasRead);
- } else {
- sRet = Status::IOError(_filename, Win32::GetLastErrSz() );
- }
- return sRet;
-}
-
-Status Win32SequentialFile::Skip( uint64_t n )
-{
- Status sRet;
- LARGE_INTEGER Move,NowPointer;
- Move.QuadPart = n;
- if(!SetFilePointerEx(_hFile,Move,&NowPointer,FILE_CURRENT)){
- sRet = Status::IOError(_filename,Win32::GetLastErrSz());
- }
- return sRet;
-}
-
-BOOL Win32SequentialFile::isEnable()
-{
- return _hFile ? TRUE : FALSE;
-}
-
-BOOL Win32SequentialFile::_Init()
-{
- std::wstring path;
- ToWidePath(_filename, path);
- _hFile = CreateFileW(path.c_str(),
- GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
- NULL);
- if (_hFile == INVALID_HANDLE_VALUE)
- _hFile = NULL;
- return _hFile ? TRUE : FALSE;
-}
-
-void Win32SequentialFile::_CleanUp()
-{
- if(_hFile){
- CloseHandle(_hFile);
- _hFile = NULL;
- }
-}
-
-Win32RandomAccessFile::Win32RandomAccessFile( const std::string& fname ) :
- _filename(fname),_hFile(NULL)
-{
- std::wstring path;
- ToWidePath(fname, path);
- _Init( path.c_str() );
-}
-
-Win32RandomAccessFile::~Win32RandomAccessFile()
-{
- _CleanUp();
-}
-
-Status Win32RandomAccessFile::Read(uint64_t offset,size_t n,Slice* result,char* scratch) const
-{
- Status sRet;
- OVERLAPPED ol = {0};
- ZeroMemory(&ol,sizeof(ol));
- ol.Offset = (DWORD)offset;
- ol.OffsetHigh = (DWORD)(offset >> 32);
- DWORD hasRead = 0;
- if(!ReadFile(_hFile,scratch,n,&hasRead,&ol))
- sRet = Status::IOError(_filename,Win32::GetLastErrSz());
- else
- *result = Slice(scratch,hasRead);
- return sRet;
-}
-
-BOOL Win32RandomAccessFile::_Init( LPCWSTR path )
-{
- BOOL bRet = FALSE;
- if(!_hFile)
- _hFile = ::CreateFileW(path,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,NULL);
- if(!_hFile || _hFile == INVALID_HANDLE_VALUE )
- _hFile = NULL;
- else
- bRet = TRUE;
- return bRet;
-}
-
-BOOL Win32RandomAccessFile::isEnable()
-{
- return _hFile ? TRUE : FALSE;
-}
-
-void Win32RandomAccessFile::_CleanUp()
-{
- if(_hFile){
- ::CloseHandle(_hFile);
- _hFile = NULL;
- }
-}
-
-Win32WritableFile::Win32WritableFile(const std::string& fname, bool append)
- : filename_(fname)
-{
- std::wstring path;
- ToWidePath(fname, path);
- // NewAppendableFile: append to an existing file, or create a new one
- // if none exists - this is OPEN_ALWAYS behavior, with
- // FILE_APPEND_DATA to avoid having to manually position the file
- // pointer at the end of the file.
- // NewWritableFile: create a new file, delete if it exists - this is
- // CREATE_ALWAYS behavior. This file is used for writing only so
- // use GENERIC_WRITE.
- _hFile = CreateFileW(path.c_str(),
- append ? FILE_APPEND_DATA : GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
- NULL,
- append ? OPEN_ALWAYS : CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- // CreateFileW returns INVALID_HANDLE_VALUE in case of error, always check isEnable() before use
-}
-
-Win32WritableFile::~Win32WritableFile()
-{
- if (_hFile != INVALID_HANDLE_VALUE)
- Close();
-}
-
-Status Win32WritableFile::Append(const Slice& data)
-{
- DWORD r = 0;
- if (!WriteFile(_hFile, data.data(), data.size(), &r, NULL) || r != data.size()) {
- return Status::IOError("Win32WritableFile.Append::WriteFile: "+filename_, Win32::GetLastErrSz());
- }
- return Status::OK();
-}
-
-Status Win32WritableFile::Close()
-{
- if (!CloseHandle(_hFile)) {
- return Status::IOError("Win32WritableFile.Close::CloseHandle: "+filename_, Win32::GetLastErrSz());
- }
- _hFile = INVALID_HANDLE_VALUE;
- return Status::OK();
-}
-
-Status Win32WritableFile::Flush()
-{
- // Nothing to do here, there are no application-side buffers
- return Status::OK();
-}
-
-Status Win32WritableFile::Sync()
-{
- if (!FlushFileBuffers(_hFile)) {
- return Status::IOError("Win32WritableFile.Sync::FlushFileBuffers "+filename_, Win32::GetLastErrSz());
- }
- return Status::OK();
-}
-
-BOOL Win32WritableFile::isEnable()
-{
- return _hFile != INVALID_HANDLE_VALUE;
-}
-
-Win32FileLock::Win32FileLock( const std::string& fname ) :
- _hFile(NULL),_filename(fname)
-{
- std::wstring path;
- ToWidePath(fname, path);
- _Init(path.c_str());
-}
-
-Win32FileLock::~Win32FileLock()
-{
- _CleanUp();
-}
-
-BOOL Win32FileLock::_Init( LPCWSTR path )
-{
- BOOL bRet = FALSE;
- if(!_hFile)
- _hFile = ::CreateFileW(path,0,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- if(!_hFile || _hFile == INVALID_HANDLE_VALUE ){
- _hFile = NULL;
- }
- else
- bRet = TRUE;
- return bRet;
-}
-
-void Win32FileLock::_CleanUp()
-{
- ::CloseHandle(_hFile);
- _hFile = NULL;
-}
-
-BOOL Win32FileLock::isEnable()
-{
- return _hFile ? TRUE : FALSE;
-}
-
-Win32Logger::Win32Logger(WritableFile* pFile) : _pFileProxy(pFile)
-{
- assert(_pFileProxy);
-}
-
-Win32Logger::~Win32Logger()
-{
- if(_pFileProxy)
- delete _pFileProxy;
-}
-
-void Win32Logger::Logv( const char* format, va_list ap )
-{
- uint64_t thread_id = ::GetCurrentThreadId();
-
- // We try twice: the first time with a fixed-size stack allocated buffer,
- // and the second time with a much larger dynamically allocated buffer.
- char buffer[500];
- for (int iter = 0; iter < 2; iter++) {
- char* base;
- int bufsize;
- if (iter == 0) {
- bufsize = sizeof(buffer);
- base = buffer;
- } else {
- bufsize = 30000;
- base = new char[bufsize];
- }
- char* p = base;
- char* limit = base + bufsize;
-
- SYSTEMTIME st;
- GetLocalTime(&st);
- p += snprintf(p, limit - p,
- "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
- int(st.wYear),
- int(st.wMonth),
- int(st.wDay),
- int(st.wHour),
- int(st.wMinute),
- int(st.wMinute),
- int(st.wMilliseconds),
- static_cast<long long unsigned int>(thread_id));
-
- // Print the message
- if (p < limit) {
- va_list backup_ap;
- va_copy(backup_ap, ap);
- p += vsnprintf(p, limit - p, format, backup_ap);
- va_end(backup_ap);
- }
-
- // Truncate to available space if necessary
- if (p >= limit) {
- if (iter == 0) {
- continue; // Try again with larger buffer
- } else {
- p = limit - 1;
- }
- }
-
- // Add newline if necessary
- if (p == base || p[-1] != '\n') {
- *p++ = '\n';
- }
-
- assert(p <= limit);
- DWORD hasWritten = 0;
- if(_pFileProxy){
- _pFileProxy->Append(Slice(base, p - base));
- _pFileProxy->Flush();
- }
- if (base != buffer) {
- delete[] base;
- }
- break;
- }
-}
-
-bool Win32Env::FileExists(const std::string& fname)
-{
- std::string path = fname;
- std::wstring wpath;
- ToWidePath(ModifyPath(path), wpath);
- return ::PathFileExistsW(wpath.c_str()) ? true : false;
-}
-
-Status Win32Env::GetChildren(const std::string& dir, std::vector<std::string>* result)
-{
- Status sRet;
- ::WIN32_FIND_DATAW wfd;
- std::string path = dir;
- ModifyPath(path);
- path += "\\*.*";
- std::wstring wpath;
- ToWidePath(path, wpath);
-
- ::HANDLE hFind = ::FindFirstFileW(wpath.c_str() ,&wfd);
- if(hFind && hFind != INVALID_HANDLE_VALUE){
- BOOL hasNext = TRUE;
- std::string child;
- while(hasNext){
- ToNarrowPath(wfd.cFileName, child);
- if(child != ".." && child != ".") {
- result->push_back(child);
- }
- hasNext = ::FindNextFileW(hFind,&wfd);
- }
- ::FindClose(hFind);
- }
- else
- sRet = Status::IOError(dir,"Could not get children.");
- return sRet;
-}
-
-void Win32Env::SleepForMicroseconds( int micros )
-{
- ::Sleep((micros + 999) /1000);
-}
-
-
-Status Win32Env::DeleteFile( const std::string& fname )
-{
- Status sRet;
- std::string path = fname;
- std::wstring wpath;
- ToWidePath(ModifyPath(path), wpath);
-
- if(!::DeleteFileW(wpath.c_str())) {
- sRet = Status::IOError(path, "Could not delete file.");
- }
- return sRet;
-}
-
-Status Win32Env::GetFileSize( const std::string& fname, uint64_t* file_size )
-{
- Status sRet;
- std::string path = fname;
- std::wstring wpath;
- ToWidePath(ModifyPath(path), wpath);
-
- HANDLE file = ::CreateFileW(wpath.c_str(),
- GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
- LARGE_INTEGER li;
- if(::GetFileSizeEx(file,&li)){
- *file_size = (uint64_t)li.QuadPart;
- }else
- sRet = Status::IOError(path,"Could not get the file size.");
- CloseHandle(file);
- return sRet;
-}
-
-Status Win32Env::RenameFile( const std::string& src, const std::string& target )
-{
- Status sRet;
- std::string src_path = src;
- std::wstring wsrc_path;
- ToWidePath(ModifyPath(src_path), wsrc_path);
- std::string target_path = target;
- std::wstring wtarget_path;
- ToWidePath(ModifyPath(target_path), wtarget_path);
-
- if(!MoveFileW(wsrc_path.c_str(), wtarget_path.c_str() ) ){
- DWORD err = GetLastError();
- if(err == 0x000000b7){
- if(!::DeleteFileW(wtarget_path.c_str() ) )
- sRet = Status::IOError(src, "Could not rename file.");
- else if(!::MoveFileW(wsrc_path.c_str(),
- wtarget_path.c_str() ) )
- sRet = Status::IOError(src, "Could not rename file.");
- }
- }
- return sRet;
-}
-
-Status Win32Env::LockFile( const std::string& fname, FileLock** lock )
-{
- Status sRet;
- std::string path = fname;
- ModifyPath(path);
- Win32FileLock* _lock = new Win32FileLock(path);
- if(!_lock->isEnable()){
- delete _lock;
- *lock = NULL;
- sRet = Status::IOError(path, "Could not lock file.");
- }
- else
- *lock = _lock;
- return sRet;
-}
-
-Status Win32Env::UnlockFile( FileLock* lock )
-{
- Status sRet;
- delete lock;
- return sRet;
-}
-
-void Win32Env::Schedule( void (*function)(void* arg), void* arg )
-{
- QueueUserWorkItem(Win32::WorkItemWrapperProc,
- new Win32::WorkItemWrapper(function,arg),
- WT_EXECUTEDEFAULT);
-}
-
-void Win32Env::StartThread( void (*function)(void* arg), void* arg )
-{
- ::_beginthread(function,0,arg);
-}
-
-Status Win32Env::GetTestDirectory( std::string* path )
-{
- Status sRet;
- WCHAR TempPath[MAX_PATH];
- ::GetTempPathW(MAX_PATH,TempPath);
- ToNarrowPath(TempPath, *path);
- path->append("leveldb\\test\\");
- ModifyPath(*path);
- return sRet;
-}
-
-uint64_t Win32Env::NowMicros()
-{
-#ifndef USE_VISTA_API
-#define GetTickCount64 GetTickCount
-#endif
- return (uint64_t)(GetTickCount64()*1000);
-}
-
-static Status CreateDirInner( const std::string& dirname )
-{
- Status sRet;
- std::wstring dirnameW;
- ToWidePath(dirname, dirnameW);
- DWORD attr = ::GetFileAttributesW(dirnameW.c_str());
- if (attr == INVALID_FILE_ATTRIBUTES) { // doesn't exist:
- std::size_t slash = dirname.find_last_of("\\");
- if (slash != std::string::npos){
- sRet = CreateDirInner(dirname.substr(0, slash));
- if (!sRet.ok()) return sRet;
- }
- BOOL result = ::CreateDirectoryW(dirnameW.c_str(), NULL);
- if (result == FALSE) {
- sRet = Status::IOError(dirname, "Could not create directory.");
- return sRet;
- }
- }
- return sRet;
-}
-
-Status Win32Env::CreateDir( const std::string& dirname )
-{
- std::string path = dirname;
- if(path[path.length() - 1] != '\\'){
- path += '\\';
- }
- ModifyPath(path);
-
- return CreateDirInner(path);
-}
-
-Status Win32Env::DeleteDir( const std::string& dirname )
-{
- Status sRet;
- std::wstring path;
- ToWidePath(dirname, path);
- ModifyPath(path);
- if(!::RemoveDirectoryW( path.c_str() ) ){
- sRet = Status::IOError(dirname, "Could not delete directory.");
- }
- return sRet;
-}
-
-Status Win32Env::NewSequentialFile( const std::string& fname, SequentialFile** result )
-{
- Status sRet;
- std::string path = fname;
- ModifyPath(path);
- Win32SequentialFile* pFile = new Win32SequentialFile(path);
- if(pFile->isEnable()){
- *result = pFile;
- }else {
- delete pFile;
- sRet = Status::IOError(path, Win32::GetLastErrSz());
- }
- return sRet;
-}
-
-Status Win32Env::NewRandomAccessFile( const std::string& fname, RandomAccessFile** result )
-{
- Status sRet;
- std::string path = fname;
- Win32RandomAccessFile* pFile = new Win32RandomAccessFile(ModifyPath(path));
- if(!pFile->isEnable()){
- delete pFile;
- *result = NULL;
- sRet = Status::IOError(path, Win32::GetLastErrSz());
- }else
- *result = pFile;
- return sRet;
-}
-
-Status Win32Env::NewLogger( const std::string& fname, Logger** result )
-{
- Status sRet;
- std::string path = fname;
- // Logs are opened with write semantics, not with append semantics
- // (see PosixEnv::NewLogger)
- Win32WritableFile* pMapFile = new Win32WritableFile(ModifyPath(path), false);
- if(!pMapFile->isEnable()){
- delete pMapFile;
- *result = NULL;
- sRet = Status::IOError(path,"could not create a logger.");
- }else
- *result = new Win32Logger(pMapFile);
- return sRet;
-}
-
-Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** result )
-{
- Status sRet;
- std::string path = fname;
- Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path), false);
- if(!pFile->isEnable()){
- *result = NULL;
- sRet = Status::IOError(fname,Win32::GetLastErrSz());
- }else
- *result = pFile;
- return sRet;
-}
-
-Status Win32Env::NewAppendableFile( const std::string& fname, WritableFile** result )
-{
- Status sRet;
- std::string path = fname;
- Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path), true);
- if(!pFile->isEnable()){
- *result = NULL;
- sRet = Status::IOError(fname,Win32::GetLastErrSz());
- }else
- *result = pFile;
- return sRet;
-}
-
-Win32Env::Win32Env()
-{
-
-}
-
-Win32Env::~Win32Env()
-{
-
-}
-
-
-} // Win32 namespace
-
-static port::OnceType once = LEVELDB_ONCE_INIT;
-static Env* default_env;
-static void InitDefaultEnv() { default_env = new Win32::Win32Env(); }
-
-Env* Env::Default() {
- port::InitOnce(&once, InitDefaultEnv);
- return default_env;
-}
-
-} // namespace leveldb
-
-#endif // defined(LEVELDB_PLATFORM_WINDOWS)
diff --git a/src/leveldb/util/env_windows.cc b/src/leveldb/util/env_windows.cc
new file mode 100644
index 0000000000..1834206562
--- /dev/null
+++ b/src/leveldb/util/env_windows.cc
@@ -0,0 +1,849 @@
+// Copyright (c) 2018 The LevelDB Authors. All rights reserved.
+// 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.
+
+// Prevent Windows headers from defining min/max macros and instead
+// use STL.
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif // ifndef NOMINMAX
+#include <windows.h>
+
+#include <algorithm>
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+#include <mutex>
+#include <queue>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "leveldb/env.h"
+#include "leveldb/slice.h"
+#include "port/port.h"
+#include "port/thread_annotations.h"
+#include "util/env_windows_test_helper.h"
+#include "util/logging.h"
+#include "util/mutexlock.h"
+#include "util/windows_logger.h"
+
+#if defined(DeleteFile)
+#undef DeleteFile
+#endif // defined(DeleteFile)
+
+namespace leveldb {
+
+namespace {
+
+constexpr const size_t kWritableFileBufferSize = 65536;
+
+// Up to 1000 mmaps for 64-bit binaries; none for 32-bit.
+constexpr int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0;
+
+// Can be set by by EnvWindowsTestHelper::SetReadOnlyMMapLimit().
+int g_mmap_limit = kDefaultMmapLimit;
+
+std::string GetWindowsErrorMessage(DWORD error_code) {
+ std::string message;
+ char* error_text = nullptr;
+ // Use MBCS version of FormatMessage to match return value.
+ size_t error_text_size = ::FormatMessageA(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ reinterpret_cast<char*>(&error_text), 0, nullptr);
+ if (!error_text) {
+ return message;
+ }
+ message.assign(error_text, error_text_size);
+ ::LocalFree(error_text);
+ return message;
+}
+
+Status WindowsError(const std::string& context, DWORD error_code) {
+ if (error_code == ERROR_FILE_NOT_FOUND || error_code == ERROR_PATH_NOT_FOUND)
+ return Status::NotFound(context, GetWindowsErrorMessage(error_code));
+ return Status::IOError(context, GetWindowsErrorMessage(error_code));
+}
+
+class ScopedHandle {
+ public:
+ ScopedHandle(HANDLE handle) : handle_(handle) {}
+ ScopedHandle(const ScopedHandle&) = delete;
+ ScopedHandle(ScopedHandle&& other) noexcept : handle_(other.Release()) {}
+ ~ScopedHandle() { Close(); }
+
+ ScopedHandle& operator=(const ScopedHandle&) = delete;
+
+ ScopedHandle& operator=(ScopedHandle&& rhs) noexcept {
+ if (this != &rhs) handle_ = rhs.Release();
+ return *this;
+ }
+
+ bool Close() {
+ if (!is_valid()) {
+ return true;
+ }
+ HANDLE h = handle_;
+ handle_ = INVALID_HANDLE_VALUE;
+ return ::CloseHandle(h);
+ }
+
+ bool is_valid() const {
+ return handle_ != INVALID_HANDLE_VALUE && handle_ != nullptr;
+ }
+
+ HANDLE get() const { return handle_; }
+
+ HANDLE Release() {
+ HANDLE h = handle_;
+ handle_ = INVALID_HANDLE_VALUE;
+ return h;
+ }
+
+ private:
+ HANDLE handle_;
+};
+
+// Helper class to limit resource usage to avoid exhaustion.
+// Currently used to limit read-only file descriptors and mmap file usage
+// so that we do not run out of file descriptors or virtual memory, or run into
+// kernel performance problems for very large databases.
+class Limiter {
+ public:
+ // Limit maximum number of resources to |max_acquires|.
+ Limiter(int max_acquires) : acquires_allowed_(max_acquires) {}
+
+ Limiter(const Limiter&) = delete;
+ Limiter operator=(const Limiter&) = delete;
+
+ // If another resource is available, acquire it and return true.
+ // Else return false.
+ bool Acquire() {
+ int old_acquires_allowed =
+ acquires_allowed_.fetch_sub(1, std::memory_order_relaxed);
+
+ if (old_acquires_allowed > 0) return true;
+
+ acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
+ return false;
+ }
+
+ // Release a resource acquired by a previous call to Acquire() that returned
+ // true.
+ void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }
+
+ private:
+ // The number of available resources.
+ //
+ // This is a counter and is not tied to the invariants of any other class, so
+ // it can be operated on safely using std::memory_order_relaxed.
+ std::atomic<int> acquires_allowed_;
+};
+
+class WindowsSequentialFile : public SequentialFile {
+ public:
+ WindowsSequentialFile(std::string filename, ScopedHandle handle)
+ : handle_(std::move(handle)), filename_(std::move(filename)) {}
+ ~WindowsSequentialFile() override {}
+
+ Status Read(size_t n, Slice* result, char* scratch) override {
+ DWORD bytes_read;
+ // DWORD is 32-bit, but size_t could technically be larger. However leveldb
+ // files are limited to leveldb::Options::max_file_size which is clamped to
+ // 1<<30 or 1 GiB.
+ assert(n <= std::numeric_limits<DWORD>::max());
+ if (!::ReadFile(handle_.get(), scratch, static_cast<DWORD>(n), &bytes_read,
+ nullptr)) {
+ return WindowsError(filename_, ::GetLastError());
+ }
+
+ *result = Slice(scratch, bytes_read);
+ return Status::OK();
+ }
+
+ Status Skip(uint64_t n) override {
+ LARGE_INTEGER distance;
+ distance.QuadPart = n;
+ if (!::SetFilePointerEx(handle_.get(), distance, nullptr, FILE_CURRENT)) {
+ return WindowsError(filename_, ::GetLastError());
+ }
+ return Status::OK();
+ }
+
+ std::string GetName() const override { return filename_; }
+
+ private:
+ const ScopedHandle handle_;
+ const std::string filename_;
+};
+
+class WindowsRandomAccessFile : public RandomAccessFile {
+ public:
+ WindowsRandomAccessFile(std::string filename, ScopedHandle handle)
+ : handle_(std::move(handle)), filename_(std::move(filename)) {}
+
+ ~WindowsRandomAccessFile() override = default;
+
+ Status Read(uint64_t offset, size_t n, Slice* result,
+ char* scratch) const override {
+ DWORD bytes_read = 0;
+ OVERLAPPED overlapped = {0};
+
+ overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
+ overlapped.Offset = static_cast<DWORD>(offset);
+ if (!::ReadFile(handle_.get(), scratch, static_cast<DWORD>(n), &bytes_read,
+ &overlapped)) {
+ DWORD error_code = ::GetLastError();
+ if (error_code != ERROR_HANDLE_EOF) {
+ *result = Slice(scratch, 0);
+ return Status::IOError(filename_, GetWindowsErrorMessage(error_code));
+ }
+ }
+
+ *result = Slice(scratch, bytes_read);
+ return Status::OK();
+ }
+
+ std::string GetName() const override { return filename_; }
+
+ private:
+ const ScopedHandle handle_;
+ const std::string filename_;
+};
+
+class WindowsMmapReadableFile : public RandomAccessFile {
+ public:
+ // base[0,length-1] contains the mmapped contents of the file.
+ WindowsMmapReadableFile(std::string filename, char* mmap_base, size_t length,
+ Limiter* mmap_limiter)
+ : mmap_base_(mmap_base),
+ length_(length),
+ mmap_limiter_(mmap_limiter),
+ filename_(std::move(filename)) {}
+
+ ~WindowsMmapReadableFile() override {
+ ::UnmapViewOfFile(mmap_base_);
+ mmap_limiter_->Release();
+ }
+
+ Status Read(uint64_t offset, size_t n, Slice* result,
+ char* scratch) const override {
+ if (offset + n > length_) {
+ *result = Slice();
+ return WindowsError(filename_, ERROR_INVALID_PARAMETER);
+ }
+
+ *result = Slice(mmap_base_ + offset, n);
+ return Status::OK();
+ }
+
+ std::string GetName() const override { return filename_; }
+
+ private:
+ char* const mmap_base_;
+ const size_t length_;
+ Limiter* const mmap_limiter_;
+ const std::string filename_;
+};
+
+class WindowsWritableFile : public WritableFile {
+ public:
+ WindowsWritableFile(std::string filename, ScopedHandle handle)
+ : pos_(0), handle_(std::move(handle)), filename_(std::move(filename)) {}
+
+ ~WindowsWritableFile() override = default;
+
+ Status Append(const Slice& data) override {
+ size_t write_size = data.size();
+ const char* write_data = data.data();
+
+ // Fit as much as possible into buffer.
+ size_t copy_size = std::min(write_size, kWritableFileBufferSize - pos_);
+ std::memcpy(buf_ + pos_, write_data, copy_size);
+ write_data += copy_size;
+ write_size -= copy_size;
+ pos_ += copy_size;
+ if (write_size == 0) {
+ return Status::OK();
+ }
+
+ // Can't fit in buffer, so need to do at least one write.
+ Status status = FlushBuffer();
+ if (!status.ok()) {
+ return status;
+ }
+
+ // Small writes go to buffer, large writes are written directly.
+ if (write_size < kWritableFileBufferSize) {
+ std::memcpy(buf_, write_data, write_size);
+ pos_ = write_size;
+ return Status::OK();
+ }
+ return WriteUnbuffered(write_data, write_size);
+ }
+
+ Status Close() override {
+ Status status = FlushBuffer();
+ if (!handle_.Close() && status.ok()) {
+ status = WindowsError(filename_, ::GetLastError());
+ }
+ return status;
+ }
+
+ Status Flush() override { return FlushBuffer(); }
+
+ Status Sync() override {
+ // On Windows no need to sync parent directory. Its metadata will be updated
+ // via the creation of the new file, without an explicit sync.
+
+ Status status = FlushBuffer();
+ if (!status.ok()) {
+ return status;
+ }
+
+ if (!::FlushFileBuffers(handle_.get())) {
+ return Status::IOError(filename_,
+ GetWindowsErrorMessage(::GetLastError()));
+ }
+ return Status::OK();
+ }
+
+ std::string GetName() const override { return filename_; }
+
+ private:
+ Status FlushBuffer() {
+ Status status = WriteUnbuffered(buf_, pos_);
+ pos_ = 0;
+ return status;
+ }
+
+ Status WriteUnbuffered(const char* data, size_t size) {
+ DWORD bytes_written;
+ if (!::WriteFile(handle_.get(), data, static_cast<DWORD>(size),
+ &bytes_written, nullptr)) {
+ return Status::IOError(filename_,
+ GetWindowsErrorMessage(::GetLastError()));
+ }
+ return Status::OK();
+ }
+
+ // buf_[0, pos_-1] contains data to be written to handle_.
+ char buf_[kWritableFileBufferSize];
+ size_t pos_;
+
+ ScopedHandle handle_;
+ const std::string filename_;
+};
+
+// Lock or unlock the entire file as specified by |lock|. Returns true
+// when successful, false upon failure. Caller should call ::GetLastError()
+// to determine cause of failure
+bool LockOrUnlock(HANDLE handle, bool lock) {
+ if (lock) {
+ return ::LockFile(handle,
+ /*dwFileOffsetLow=*/0, /*dwFileOffsetHigh=*/0,
+ /*nNumberOfBytesToLockLow=*/MAXDWORD,
+ /*nNumberOfBytesToLockHigh=*/MAXDWORD);
+ } else {
+ return ::UnlockFile(handle,
+ /*dwFileOffsetLow=*/0, /*dwFileOffsetHigh=*/0,
+ /*nNumberOfBytesToLockLow=*/MAXDWORD,
+ /*nNumberOfBytesToLockHigh=*/MAXDWORD);
+ }
+}
+
+class WindowsFileLock : public FileLock {
+ public:
+ WindowsFileLock(ScopedHandle handle, std::string filename)
+ : handle_(std::move(handle)), filename_(std::move(filename)) {}
+
+ const ScopedHandle& handle() const { return handle_; }
+ const std::string& filename() const { return filename_; }
+
+ private:
+ const ScopedHandle handle_;
+ const std::string filename_;
+};
+
+class WindowsEnv : public Env {
+ public:
+ WindowsEnv();
+ ~WindowsEnv() override {
+ static const char msg[] =
+ "WindowsEnv singleton destroyed. Unsupported behavior!\n";
+ std::fwrite(msg, 1, sizeof(msg), stderr);
+ std::abort();
+ }
+
+ Status NewSequentialFile(const std::string& filename,
+ SequentialFile** result) override {
+ *result = nullptr;
+ DWORD desired_access = GENERIC_READ;
+ DWORD share_mode = FILE_SHARE_READ;
+ auto wFilename = toUtf16(filename);
+ ScopedHandle handle = ::CreateFileW(
+ wFilename.c_str(), desired_access, share_mode,
+ /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ /*hTemplateFile=*/nullptr);
+ if (!handle.is_valid()) {
+ return WindowsError(filename, ::GetLastError());
+ }
+
+ *result = new WindowsSequentialFile(filename, std::move(handle));
+ return Status::OK();
+ }
+
+ Status NewRandomAccessFile(const std::string& filename,
+ RandomAccessFile** result) override {
+ *result = nullptr;
+ DWORD desired_access = GENERIC_READ;
+ DWORD share_mode = FILE_SHARE_READ;
+ auto wFilename = toUtf16(filename);
+ ScopedHandle handle =
+ ::CreateFileW(wFilename.c_str(), desired_access, share_mode,
+ /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING,
+ FILE_ATTRIBUTE_READONLY,
+ /*hTemplateFile=*/nullptr);
+ if (!handle.is_valid()) {
+ return WindowsError(filename, ::GetLastError());
+ }
+ if (!mmap_limiter_.Acquire()) {
+ *result = new WindowsRandomAccessFile(filename, std::move(handle));
+ return Status::OK();
+ }
+
+ LARGE_INTEGER file_size;
+ Status status;
+ if (!::GetFileSizeEx(handle.get(), &file_size)) {
+ mmap_limiter_.Release();
+ return WindowsError(filename, ::GetLastError());
+ }
+
+ ScopedHandle mapping =
+ ::CreateFileMappingW(handle.get(),
+ /*security attributes=*/nullptr, PAGE_READONLY,
+ /*dwMaximumSizeHigh=*/0,
+ /*dwMaximumSizeLow=*/0,
+ /*lpName=*/nullptr);
+ if (mapping.is_valid()) {
+ void* mmap_base = ::MapViewOfFile(mapping.get(), FILE_MAP_READ,
+ /*dwFileOffsetHigh=*/0,
+ /*dwFileOffsetLow=*/0,
+ /*dwNumberOfBytesToMap=*/0);
+ if (mmap_base) {
+ *result = new WindowsMmapReadableFile(
+ filename, reinterpret_cast<char*>(mmap_base),
+ static_cast<size_t>(file_size.QuadPart), &mmap_limiter_);
+ return Status::OK();
+ }
+ }
+ mmap_limiter_.Release();
+ return WindowsError(filename, ::GetLastError());
+ }
+
+ Status NewWritableFile(const std::string& filename,
+ WritableFile** result) override {
+ DWORD desired_access = GENERIC_WRITE;
+ DWORD share_mode = 0; // Exclusive access.
+ auto wFilename = toUtf16(filename);
+ ScopedHandle handle = ::CreateFileW(
+ wFilename.c_str(), desired_access, share_mode,
+ /*lpSecurityAttributes=*/nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ /*hTemplateFile=*/nullptr);
+ if (!handle.is_valid()) {
+ *result = nullptr;
+ return WindowsError(filename, ::GetLastError());
+ }
+
+ *result = new WindowsWritableFile(filename, std::move(handle));
+ return Status::OK();
+ }
+
+ Status NewAppendableFile(const std::string& filename,
+ WritableFile** result) override {
+ DWORD desired_access = FILE_APPEND_DATA;
+ DWORD share_mode = 0; // Exclusive access.
+ auto wFilename = toUtf16(filename);
+ ScopedHandle handle = ::CreateFileW(
+ wFilename.c_str(), desired_access, share_mode,
+ /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ /*hTemplateFile=*/nullptr);
+ if (!handle.is_valid()) {
+ *result = nullptr;
+ return WindowsError(filename, ::GetLastError());
+ }
+
+ *result = new WindowsWritableFile(filename, std::move(handle));
+ return Status::OK();
+ }
+
+ bool FileExists(const std::string& filename) override {
+ auto wFilename = toUtf16(filename);
+ return GetFileAttributesW(wFilename.c_str()) != INVALID_FILE_ATTRIBUTES;
+ }
+
+ Status GetChildren(const std::string& directory_path,
+ std::vector<std::string>* result) override {
+ const std::string find_pattern = directory_path + "\\*";
+ WIN32_FIND_DATAW find_data;
+ auto wFind_pattern = toUtf16(find_pattern);
+ HANDLE dir_handle = ::FindFirstFileW(wFind_pattern.c_str(), &find_data);
+ if (dir_handle == INVALID_HANDLE_VALUE) {
+ DWORD last_error = ::GetLastError();
+ if (last_error == ERROR_FILE_NOT_FOUND) {
+ return Status::OK();
+ }
+ return WindowsError(directory_path, last_error);
+ }
+ do {
+ char base_name[_MAX_FNAME];
+ char ext[_MAX_EXT];
+
+ auto find_data_filename = toUtf8(find_data.cFileName);
+ if (!_splitpath_s(find_data_filename.c_str(), nullptr, 0, nullptr, 0,
+ base_name, ARRAYSIZE(base_name), ext, ARRAYSIZE(ext))) {
+ result->emplace_back(std::string(base_name) + ext);
+ }
+ } while (::FindNextFileW(dir_handle, &find_data));
+ DWORD last_error = ::GetLastError();
+ ::FindClose(dir_handle);
+ if (last_error != ERROR_NO_MORE_FILES) {
+ return WindowsError(directory_path, last_error);
+ }
+ return Status::OK();
+ }
+
+ Status DeleteFile(const std::string& filename) override {
+ auto wFilename = toUtf16(filename);
+ if (!::DeleteFileW(wFilename.c_str())) {
+ return WindowsError(filename, ::GetLastError());
+ }
+ return Status::OK();
+ }
+
+ Status CreateDir(const std::string& dirname) override {
+ auto wDirname = toUtf16(dirname);
+ if (!::CreateDirectoryW(wDirname.c_str(), nullptr)) {
+ return WindowsError(dirname, ::GetLastError());
+ }
+ return Status::OK();
+ }
+
+ Status DeleteDir(const std::string& dirname) override {
+ auto wDirname = toUtf16(dirname);
+ if (!::RemoveDirectoryW(wDirname.c_str())) {
+ return WindowsError(dirname, ::GetLastError());
+ }
+ return Status::OK();
+ }
+
+ Status GetFileSize(const std::string& filename, uint64_t* size) override {
+ WIN32_FILE_ATTRIBUTE_DATA file_attributes;
+ auto wFilename = toUtf16(filename);
+ if (!::GetFileAttributesExW(wFilename.c_str(), GetFileExInfoStandard,
+ &file_attributes)) {
+ return WindowsError(filename, ::GetLastError());
+ }
+ ULARGE_INTEGER file_size;
+ file_size.HighPart = file_attributes.nFileSizeHigh;
+ file_size.LowPart = file_attributes.nFileSizeLow;
+ *size = file_size.QuadPart;
+ return Status::OK();
+ }
+
+ Status RenameFile(const std::string& from, const std::string& to) override {
+ // Try a simple move first. It will only succeed when |to| doesn't already
+ // exist.
+ auto wFrom = toUtf16(from);
+ auto wTo = toUtf16(to);
+ if (::MoveFileW(wFrom.c_str(), wTo.c_str())) {
+ return Status::OK();
+ }
+ DWORD move_error = ::GetLastError();
+
+ // Try the full-blown replace if the move fails, as ReplaceFile will only
+ // succeed when |to| does exist. When writing to a network share, we may not
+ // be able to change the ACLs. Ignore ACL errors then
+ // (REPLACEFILE_IGNORE_MERGE_ERRORS).
+ if (::ReplaceFileW(wTo.c_str(), wFrom.c_str(), /*lpBackupFileName=*/nullptr,
+ REPLACEFILE_IGNORE_MERGE_ERRORS,
+ /*lpExclude=*/nullptr, /*lpReserved=*/nullptr)) {
+ return Status::OK();
+ }
+ DWORD replace_error = ::GetLastError();
+ // In the case of FILE_ERROR_NOT_FOUND from ReplaceFile, it is likely that
+ // |to| does not exist. In this case, the more relevant error comes from the
+ // call to MoveFile.
+ if (replace_error == ERROR_FILE_NOT_FOUND ||
+ replace_error == ERROR_PATH_NOT_FOUND) {
+ return WindowsError(from, move_error);
+ } else {
+ return WindowsError(from, replace_error);
+ }
+ }
+
+ Status LockFile(const std::string& filename, FileLock** lock) override {
+ *lock = nullptr;
+ Status result;
+ auto wFilename = toUtf16(filename);
+ ScopedHandle handle = ::CreateFileW(
+ wFilename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
+ /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ nullptr);
+ if (!handle.is_valid()) {
+ result = WindowsError(filename, ::GetLastError());
+ } else if (!LockOrUnlock(handle.get(), true)) {
+ result = WindowsError("lock " + filename, ::GetLastError());
+ } else {
+ *lock = new WindowsFileLock(std::move(handle), filename);
+ }
+ return result;
+ }
+
+ Status UnlockFile(FileLock* lock) override {
+ WindowsFileLock* windows_file_lock =
+ reinterpret_cast<WindowsFileLock*>(lock);
+ if (!LockOrUnlock(windows_file_lock->handle().get(), false)) {
+ return WindowsError("unlock " + windows_file_lock->filename(),
+ ::GetLastError());
+ }
+ delete windows_file_lock;
+ return Status::OK();
+ }
+
+ void Schedule(void (*background_work_function)(void* background_work_arg),
+ void* background_work_arg) override;
+
+ void StartThread(void (*thread_main)(void* thread_main_arg),
+ void* thread_main_arg) override {
+ std::thread new_thread(thread_main, thread_main_arg);
+ new_thread.detach();
+ }
+
+ Status GetTestDirectory(std::string* result) override {
+ const char* env = getenv("TEST_TMPDIR");
+ if (env && env[0] != '\0') {
+ *result = env;
+ return Status::OK();
+ }
+
+ wchar_t wtmp_path[MAX_PATH];
+ if (!GetTempPathW(ARRAYSIZE(wtmp_path), wtmp_path)) {
+ return WindowsError("GetTempPath", ::GetLastError());
+ }
+ std::string tmp_path = toUtf8(std::wstring(wtmp_path));
+ std::stringstream ss;
+ ss << tmp_path << "leveldbtest-" << std::this_thread::get_id();
+ *result = ss.str();
+
+ // Directory may already exist
+ CreateDir(*result);
+ return Status::OK();
+ }
+
+ Status NewLogger(const std::string& filename, Logger** result) override {
+ auto wFilename = toUtf16(filename);
+ std::FILE* fp = _wfopen(wFilename.c_str(), L"w");
+ if (fp == nullptr) {
+ *result = nullptr;
+ return WindowsError(filename, ::GetLastError());
+ } else {
+ *result = new WindowsLogger(fp);
+ return Status::OK();
+ }
+ }
+
+ uint64_t NowMicros() override {
+ // GetSystemTimeAsFileTime typically has a resolution of 10-20 msec.
+ // TODO(cmumford): Switch to GetSystemTimePreciseAsFileTime which is
+ // available in Windows 8 and later.
+ FILETIME ft;
+ ::GetSystemTimeAsFileTime(&ft);
+ // Each tick represents a 100-nanosecond intervals since January 1, 1601
+ // (UTC).
+ uint64_t num_ticks =
+ (static_cast<uint64_t>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
+ return num_ticks / 10;
+ }
+
+ void SleepForMicroseconds(int micros) override {
+ std::this_thread::sleep_for(std::chrono::microseconds(micros));
+ }
+
+ private:
+ void BackgroundThreadMain();
+
+ static void BackgroundThreadEntryPoint(WindowsEnv* env) {
+ env->BackgroundThreadMain();
+ }
+
+ // Stores the work item data in a Schedule() call.
+ //
+ // Instances are constructed on the thread calling Schedule() and used on the
+ // background thread.
+ //
+ // This structure is thread-safe beacuse it is immutable.
+ struct BackgroundWorkItem {
+ explicit BackgroundWorkItem(void (*function)(void* arg), void* arg)
+ : function(function), arg(arg) {}
+
+ void (*const function)(void*);
+ void* const arg;
+ };
+
+ port::Mutex background_work_mutex_;
+ port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_);
+ bool started_background_thread_ GUARDED_BY(background_work_mutex_);
+
+ std::queue<BackgroundWorkItem> background_work_queue_
+ GUARDED_BY(background_work_mutex_);
+
+ Limiter mmap_limiter_; // Thread-safe.
+
+ // Converts a Windows wide multi-byte UTF-16 string to a UTF-8 string.
+ // See http://utf8everywhere.org/#windows
+ std::string toUtf8(const std::wstring& wstr) {
+ if (wstr.empty()) return std::string();
+ int size_needed = WideCharToMultiByte(
+ CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
+ std::string strTo(size_needed, 0);
+ WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0],
+ size_needed, NULL, NULL);
+ return strTo;
+ }
+
+ // Converts a UTF-8 string to a Windows UTF-16 multi-byte wide character
+ // string.
+ // See http://utf8everywhere.org/#windows
+ std::wstring toUtf16(const std::string& str) {
+ if (str.empty()) return std::wstring();
+ int size_needed =
+ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
+ std::wstring strTo(size_needed, 0);
+ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &strTo[0],
+ size_needed);
+ return strTo;
+ }
+};
+
+// Return the maximum number of concurrent mmaps.
+int MaxMmaps() { return g_mmap_limit; }
+
+WindowsEnv::WindowsEnv()
+ : background_work_cv_(&background_work_mutex_),
+ started_background_thread_(false),
+ mmap_limiter_(MaxMmaps()) {}
+
+void WindowsEnv::Schedule(
+ void (*background_work_function)(void* background_work_arg),
+ void* background_work_arg) {
+ background_work_mutex_.Lock();
+
+ // Start the background thread, if we haven't done so already.
+ if (!started_background_thread_) {
+ started_background_thread_ = true;
+ std::thread background_thread(WindowsEnv::BackgroundThreadEntryPoint, this);
+ background_thread.detach();
+ }
+
+ // If the queue is empty, the background thread may be waiting for work.
+ if (background_work_queue_.empty()) {
+ background_work_cv_.Signal();
+ }
+
+ background_work_queue_.emplace(background_work_function, background_work_arg);
+ background_work_mutex_.Unlock();
+}
+
+void WindowsEnv::BackgroundThreadMain() {
+ while (true) {
+ background_work_mutex_.Lock();
+
+ // Wait until there is work to be done.
+ while (background_work_queue_.empty()) {
+ background_work_cv_.Wait();
+ }
+
+ assert(!background_work_queue_.empty());
+ auto background_work_function = background_work_queue_.front().function;
+ void* background_work_arg = background_work_queue_.front().arg;
+ background_work_queue_.pop();
+
+ background_work_mutex_.Unlock();
+ background_work_function(background_work_arg);
+ }
+}
+
+// Wraps an Env instance whose destructor is never created.
+//
+// Intended usage:
+// using PlatformSingletonEnv = SingletonEnv<PlatformEnv>;
+// void ConfigurePosixEnv(int param) {
+// PlatformSingletonEnv::AssertEnvNotInitialized();
+// // set global configuration flags.
+// }
+// Env* Env::Default() {
+// static PlatformSingletonEnv default_env;
+// return default_env.env();
+// }
+template <typename EnvType>
+class SingletonEnv {
+ public:
+ SingletonEnv() {
+#if !defined(NDEBUG)
+ env_initialized_.store(true, std::memory_order::memory_order_relaxed);
+#endif // !defined(NDEBUG)
+ static_assert(sizeof(env_storage_) >= sizeof(EnvType),
+ "env_storage_ will not fit the Env");
+ static_assert(alignof(decltype(env_storage_)) >= alignof(EnvType),
+ "env_storage_ does not meet the Env's alignment needs");
+ new (&env_storage_) EnvType();
+ }
+ ~SingletonEnv() = default;
+
+ SingletonEnv(const SingletonEnv&) = delete;
+ SingletonEnv& operator=(const SingletonEnv&) = delete;
+
+ Env* env() { return reinterpret_cast<Env*>(&env_storage_); }
+
+ static void AssertEnvNotInitialized() {
+#if !defined(NDEBUG)
+ assert(!env_initialized_.load(std::memory_order::memory_order_relaxed));
+#endif // !defined(NDEBUG)
+ }
+
+ private:
+ typename std::aligned_storage<sizeof(EnvType), alignof(EnvType)>::type
+ env_storage_;
+#if !defined(NDEBUG)
+ static std::atomic<bool> env_initialized_;
+#endif // !defined(NDEBUG)
+};
+
+#if !defined(NDEBUG)
+template <typename EnvType>
+std::atomic<bool> SingletonEnv<EnvType>::env_initialized_;
+#endif // !defined(NDEBUG)
+
+using WindowsDefaultEnv = SingletonEnv<WindowsEnv>;
+
+} // namespace
+
+void EnvWindowsTestHelper::SetReadOnlyMMapLimit(int limit) {
+ WindowsDefaultEnv::AssertEnvNotInitialized();
+ g_mmap_limit = limit;
+}
+
+Env* Env::Default() {
+ static WindowsDefaultEnv env_container;
+ return env_container.env();
+}
+
+} // namespace leveldb
diff --git a/src/leveldb/util/env_windows_test.cc b/src/leveldb/util/env_windows_test.cc
new file mode 100644
index 0000000000..3c22133891
--- /dev/null
+++ b/src/leveldb/util/env_windows_test.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2018 The LevelDB Authors. All rights reserved.
+// 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.
+
+#include "leveldb/env.h"
+
+#include "port/port.h"
+#include "util/env_windows_test_helper.h"
+#include "util/testharness.h"
+
+namespace leveldb {
+
+static const int kMMapLimit = 4;
+
+class EnvWindowsTest {
+ public:
+ static void SetFileLimits(int mmap_limit) {
+ EnvWindowsTestHelper::SetReadOnlyMMapLimit(mmap_limit);
+ }
+
+ EnvWindowsTest() : env_(Env::Default()) {}
+
+ Env* env_;
+};
+
+TEST(EnvWindowsTest, TestOpenOnRead) {
+ // Write some test data to a single file that will be opened |n| times.
+ std::string test_dir;
+ ASSERT_OK(env_->GetTestDirectory(&test_dir));
+ std::string test_file = test_dir + "/open_on_read.txt";
+
+ FILE* f = fopen(test_file.c_str(), "w");
+ ASSERT_TRUE(f != nullptr);
+ const char kFileData[] = "abcdefghijklmnopqrstuvwxyz";
+ fputs(kFileData, f);
+ fclose(f);
+
+ // Open test file some number above the sum of the two limits to force
+ // leveldb::WindowsEnv to switch from mapping the file into memory
+ // to basic file reading.
+ const int kNumFiles = kMMapLimit + 5;
+ leveldb::RandomAccessFile* files[kNumFiles] = {0};
+ for (int i = 0; i < kNumFiles; i++) {
+ ASSERT_OK(env_->NewRandomAccessFile(test_file, &files[i]));
+ }
+ char scratch;
+ Slice read_result;
+ for (int i = 0; i < kNumFiles; i++) {
+ ASSERT_OK(files[i]->Read(i, 1, &read_result, &scratch));
+ ASSERT_EQ(kFileData[i], read_result[0]);
+ }
+ for (int i = 0; i < kNumFiles; i++) {
+ delete files[i];
+ }
+ ASSERT_OK(env_->DeleteFile(test_file));
+}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) {
+ // All tests currently run with the same read-only file limits.
+ leveldb::EnvWindowsTest::SetFileLimits(leveldb::kMMapLimit);
+ return leveldb::test::RunAllTests();
+}
diff --git a/src/leveldb/util/env_windows_test_helper.h b/src/leveldb/util/env_windows_test_helper.h
new file mode 100644
index 0000000000..e6f6020561
--- /dev/null
+++ b/src/leveldb/util/env_windows_test_helper.h
@@ -0,0 +1,25 @@
+// Copyright 2018 (c) The LevelDB Authors. All rights reserved.
+// 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.
+
+#ifndef STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_
+#define STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_
+
+namespace leveldb {
+
+class EnvWindowsTest;
+
+// A helper for the Windows Env to facilitate testing.
+class EnvWindowsTestHelper {
+ private:
+ friend class CorruptionTest;
+ friend class EnvWindowsTest;
+
+ // Set the maximum number of read-only files that will be mapped via mmap.
+ // Must be called before creating an Env.
+ static void SetReadOnlyMMapLimit(int limit);
+};
+
+} // namespace leveldb
+
+#endif // STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_
diff --git a/src/leveldb/util/filter_policy.cc b/src/leveldb/util/filter_policy.cc
index 7b045c8c91..90fd754d64 100644
--- a/src/leveldb/util/filter_policy.cc
+++ b/src/leveldb/util/filter_policy.cc
@@ -6,6 +6,6 @@
namespace leveldb {
-FilterPolicy::~FilterPolicy() { }
+FilterPolicy::~FilterPolicy() {}
} // namespace leveldb
diff --git a/src/leveldb/util/hash.cc b/src/leveldb/util/hash.cc
index ed439ce7a2..dd47c110ee 100644
--- a/src/leveldb/util/hash.cc
+++ b/src/leveldb/util/hash.cc
@@ -2,15 +2,19 @@
// 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.
+#include "util/hash.h"
+
#include <string.h>
+
#include "util/coding.h"
-#include "util/hash.h"
// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
// between switch labels. The real definition should be provided externally.
// This one is a fallback version for unsupported compilers.
#ifndef FALLTHROUGH_INTENDED
-#define FALLTHROUGH_INTENDED do { } while (0)
+#define FALLTHROUGH_INTENDED \
+ do { \
+ } while (0)
#endif
namespace leveldb {
@@ -34,13 +38,13 @@ uint32_t Hash(const char* data, size_t n, uint32_t seed) {
// Pick up remaining bytes
switch (limit - data) {
case 3:
- h += static_cast<unsigned char>(data[2]) << 16;
+ h += static_cast<uint8_t>(data[2]) << 16;
FALLTHROUGH_INTENDED;
case 2:
- h += static_cast<unsigned char>(data[1]) << 8;
+ h += static_cast<uint8_t>(data[1]) << 8;
FALLTHROUGH_INTENDED;
case 1:
- h += static_cast<unsigned char>(data[0]);
+ h += static_cast<uint8_t>(data[0]);
h *= m;
h ^= (h >> r);
break;
@@ -48,5 +52,4 @@ uint32_t Hash(const char* data, size_t n, uint32_t seed) {
return h;
}
-
} // namespace leveldb
diff --git a/src/leveldb/util/hash.h b/src/leveldb/util/hash.h
index 8889d56be8..74bdb6e7b2 100644
--- a/src/leveldb/util/hash.h
+++ b/src/leveldb/util/hash.h
@@ -12,8 +12,8 @@
namespace leveldb {
-extern uint32_t Hash(const char* data, size_t n, uint32_t seed);
+uint32_t Hash(const char* data, size_t n, uint32_t seed);
-}
+} // namespace leveldb
#endif // STORAGE_LEVELDB_UTIL_HASH_H_
diff --git a/src/leveldb/util/hash_test.cc b/src/leveldb/util/hash_test.cc
index eaa1c92c23..21f8171da6 100644
--- a/src/leveldb/util/hash_test.cc
+++ b/src/leveldb/util/hash_test.cc
@@ -7,26 +7,18 @@
namespace leveldb {
-class HASH { };
+class HASH {};
TEST(HASH, SignedUnsignedIssue) {
- const unsigned char data1[1] = {0x62};
- const unsigned char data2[2] = {0xc3, 0x97};
- const unsigned char data3[3] = {0xe2, 0x99, 0xa5};
- const unsigned char data4[4] = {0xe1, 0x80, 0xb9, 0x32};
- const unsigned char data5[48] = {
- 0x01, 0xc0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x14,
- 0x00, 0x00, 0x00, 0x18,
- 0x28, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
+ const uint8_t data1[1] = {0x62};
+ const uint8_t data2[2] = {0xc3, 0x97};
+ const uint8_t data3[3] = {0xe2, 0x99, 0xa5};
+ const uint8_t data4[4] = {0xe1, 0x80, 0xb9, 0x32};
+ const uint8_t data5[48] = {
+ 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
ASSERT_EQ(Hash(0, 0, 0xbc9f1d34), 0xbc9f1d34);
@@ -49,6 +41,4 @@ TEST(HASH, SignedUnsignedIssue) {
} // namespace leveldb
-int main(int argc, char** argv) {
- return leveldb::test::RunAllTests();
-}
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/histogram.cc b/src/leveldb/util/histogram.cc
index bb95f583ea..65092c88f2 100644
--- a/src/leveldb/util/histogram.cc
+++ b/src/leveldb/util/histogram.cc
@@ -2,36 +2,174 @@
// 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.
+#include "util/histogram.h"
+
#include <math.h>
#include <stdio.h>
+
#include "port/port.h"
-#include "util/histogram.h"
namespace leveldb {
const double Histogram::kBucketLimit[kNumBuckets] = {
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 25, 30, 35, 40, 45,
- 50, 60, 70, 80, 90, 100, 120, 140, 160, 180, 200, 250, 300, 350, 400, 450,
- 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000, 2500, 3000,
- 3500, 4000, 4500, 5000, 6000, 7000, 8000, 9000, 10000, 12000, 14000,
- 16000, 18000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 60000,
- 70000, 80000, 90000, 100000, 120000, 140000, 160000, 180000, 200000,
- 250000, 300000, 350000, 400000, 450000, 500000, 600000, 700000, 800000,
- 900000, 1000000, 1200000, 1400000, 1600000, 1800000, 2000000, 2500000,
- 3000000, 3500000, 4000000, 4500000, 5000000, 6000000, 7000000, 8000000,
- 9000000, 10000000, 12000000, 14000000, 16000000, 18000000, 20000000,
- 25000000, 30000000, 35000000, 40000000, 45000000, 50000000, 60000000,
- 70000000, 80000000, 90000000, 100000000, 120000000, 140000000, 160000000,
- 180000000, 200000000, 250000000, 300000000, 350000000, 400000000,
- 450000000, 500000000, 600000000, 700000000, 800000000, 900000000,
- 1000000000, 1200000000, 1400000000, 1600000000, 1800000000, 2000000000,
- 2500000000.0, 3000000000.0, 3500000000.0, 4000000000.0, 4500000000.0,
- 5000000000.0, 6000000000.0, 7000000000.0, 8000000000.0, 9000000000.0,
- 1e200,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 12,
+ 14,
+ 16,
+ 18,
+ 20,
+ 25,
+ 30,
+ 35,
+ 40,
+ 45,
+ 50,
+ 60,
+ 70,
+ 80,
+ 90,
+ 100,
+ 120,
+ 140,
+ 160,
+ 180,
+ 200,
+ 250,
+ 300,
+ 350,
+ 400,
+ 450,
+ 500,
+ 600,
+ 700,
+ 800,
+ 900,
+ 1000,
+ 1200,
+ 1400,
+ 1600,
+ 1800,
+ 2000,
+ 2500,
+ 3000,
+ 3500,
+ 4000,
+ 4500,
+ 5000,
+ 6000,
+ 7000,
+ 8000,
+ 9000,
+ 10000,
+ 12000,
+ 14000,
+ 16000,
+ 18000,
+ 20000,
+ 25000,
+ 30000,
+ 35000,
+ 40000,
+ 45000,
+ 50000,
+ 60000,
+ 70000,
+ 80000,
+ 90000,
+ 100000,
+ 120000,
+ 140000,
+ 160000,
+ 180000,
+ 200000,
+ 250000,
+ 300000,
+ 350000,
+ 400000,
+ 450000,
+ 500000,
+ 600000,
+ 700000,
+ 800000,
+ 900000,
+ 1000000,
+ 1200000,
+ 1400000,
+ 1600000,
+ 1800000,
+ 2000000,
+ 2500000,
+ 3000000,
+ 3500000,
+ 4000000,
+ 4500000,
+ 5000000,
+ 6000000,
+ 7000000,
+ 8000000,
+ 9000000,
+ 10000000,
+ 12000000,
+ 14000000,
+ 16000000,
+ 18000000,
+ 20000000,
+ 25000000,
+ 30000000,
+ 35000000,
+ 40000000,
+ 45000000,
+ 50000000,
+ 60000000,
+ 70000000,
+ 80000000,
+ 90000000,
+ 100000000,
+ 120000000,
+ 140000000,
+ 160000000,
+ 180000000,
+ 200000000,
+ 250000000,
+ 300000000,
+ 350000000,
+ 400000000,
+ 450000000,
+ 500000000,
+ 600000000,
+ 700000000,
+ 800000000,
+ 900000000,
+ 1000000000,
+ 1200000000,
+ 1400000000,
+ 1600000000,
+ 1800000000,
+ 2000000000,
+ 2500000000.0,
+ 3000000000.0,
+ 3500000000.0,
+ 4000000000.0,
+ 4500000000.0,
+ 5000000000.0,
+ 6000000000.0,
+ 7000000000.0,
+ 8000000000.0,
+ 9000000000.0,
+ 1e200,
};
void Histogram::Clear() {
- min_ = kBucketLimit[kNumBuckets-1];
+ min_ = kBucketLimit[kNumBuckets - 1];
max_ = 0;
num_ = 0;
sum_ = 0;
@@ -66,9 +204,7 @@ void Histogram::Merge(const Histogram& other) {
}
}
-double Histogram::Median() const {
- return Percentile(50.0);
-}
+double Histogram::Median() const { return Percentile(50.0); }
double Histogram::Percentile(double p) const {
double threshold = num_ * (p / 100.0);
@@ -77,7 +213,7 @@ double Histogram::Percentile(double p) const {
sum += buckets_[b];
if (sum >= threshold) {
// Scale linearly within this bucket
- double left_point = (b == 0) ? 0 : kBucketLimit[b-1];
+ double left_point = (b == 0) ? 0 : kBucketLimit[b - 1];
double right_point = kBucketLimit[b];
double left_sum = sum - buckets_[b];
double right_sum = sum;
@@ -105,12 +241,10 @@ double Histogram::StandardDeviation() const {
std::string Histogram::ToString() const {
std::string r;
char buf[200];
- snprintf(buf, sizeof(buf),
- "Count: %.0f Average: %.4f StdDev: %.2f\n",
- num_, Average(), StandardDeviation());
+ snprintf(buf, sizeof(buf), "Count: %.0f Average: %.4f StdDev: %.2f\n", num_,
+ Average(), StandardDeviation());
r.append(buf);
- snprintf(buf, sizeof(buf),
- "Min: %.4f Median: %.4f Max: %.4f\n",
+ snprintf(buf, sizeof(buf), "Min: %.4f Median: %.4f Max: %.4f\n",
(num_ == 0.0 ? 0.0 : min_), Median(), max_);
r.append(buf);
r.append("------------------------------------------------------\n");
@@ -119,17 +253,16 @@ std::string Histogram::ToString() const {
for (int b = 0; b < kNumBuckets; b++) {
if (buckets_[b] <= 0.0) continue;
sum += buckets_[b];
- snprintf(buf, sizeof(buf),
- "[ %7.0f, %7.0f ) %7.0f %7.3f%% %7.3f%% ",
- ((b == 0) ? 0.0 : kBucketLimit[b-1]), // left
- kBucketLimit[b], // right
- buckets_[b], // count
- mult * buckets_[b], // percentage
- mult * sum); // cumulative percentage
+ snprintf(buf, sizeof(buf), "[ %7.0f, %7.0f ) %7.0f %7.3f%% %7.3f%% ",
+ ((b == 0) ? 0.0 : kBucketLimit[b - 1]), // left
+ kBucketLimit[b], // right
+ buckets_[b], // count
+ mult * buckets_[b], // percentage
+ mult * sum); // cumulative percentage
r.append(buf);
// Add hash marks based on percentage; 20 marks for 100%.
- int marks = static_cast<int>(20*(buckets_[b] / num_) + 0.5);
+ int marks = static_cast<int>(20 * (buckets_[b] / num_) + 0.5);
r.append(marks, '#');
r.push_back('\n');
}
diff --git a/src/leveldb/util/histogram.h b/src/leveldb/util/histogram.h
index 1ef9f3c8ab..4da60fba45 100644
--- a/src/leveldb/util/histogram.h
+++ b/src/leveldb/util/histogram.h
@@ -11,8 +11,8 @@ namespace leveldb {
class Histogram {
public:
- Histogram() { }
- ~Histogram() { }
+ Histogram() {}
+ ~Histogram() {}
void Clear();
void Add(double value);
@@ -21,20 +21,22 @@ class Histogram {
std::string ToString() const;
private:
+ enum { kNumBuckets = 154 };
+
+ double Median() const;
+ double Percentile(double p) const;
+ double Average() const;
+ double StandardDeviation() const;
+
+ static const double kBucketLimit[kNumBuckets];
+
double min_;
double max_;
double num_;
double sum_;
double sum_squares_;
- enum { kNumBuckets = 154 };
- static const double kBucketLimit[kNumBuckets];
double buckets_[kNumBuckets];
-
- double Median() const;
- double Percentile(double p) const;
- double Average() const;
- double StandardDeviation() const;
};
} // namespace leveldb
diff --git a/src/leveldb/util/logging.cc b/src/leveldb/util/logging.cc
index db6160c8f1..75e9d037d3 100644
--- a/src/leveldb/util/logging.cc
+++ b/src/leveldb/util/logging.cc
@@ -8,6 +8,9 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+
+#include <limits>
+
#include "leveldb/env.h"
#include "leveldb/slice.h"
@@ -15,7 +18,7 @@ namespace leveldb {
void AppendNumberTo(std::string* str, uint64_t num) {
char buf[30];
- snprintf(buf, sizeof(buf), "%llu", (unsigned long long) num);
+ snprintf(buf, sizeof(buf), "%llu", (unsigned long long)num);
str->append(buf);
}
@@ -46,27 +49,36 @@ std::string EscapeString(const Slice& value) {
}
bool ConsumeDecimalNumber(Slice* in, uint64_t* val) {
- uint64_t v = 0;
- int digits = 0;
- while (!in->empty()) {
- unsigned char c = (*in)[0];
- if (c >= '0' && c <= '9') {
- ++digits;
- const int delta = (c - '0');
- static const uint64_t kMaxUint64 = ~static_cast<uint64_t>(0);
- if (v > kMaxUint64/10 ||
- (v == kMaxUint64/10 && delta > kMaxUint64%10)) {
- // Overflow
- return false;
- }
- v = (v * 10) + delta;
- in->remove_prefix(1);
- } else {
- break;
+ // Constants that will be optimized away.
+ constexpr const uint64_t kMaxUint64 = std::numeric_limits<uint64_t>::max();
+ constexpr const char kLastDigitOfMaxUint64 =
+ '0' + static_cast<char>(kMaxUint64 % 10);
+
+ uint64_t value = 0;
+
+ // reinterpret_cast-ing from char* to uint8_t* to avoid signedness.
+ const uint8_t* start = reinterpret_cast<const uint8_t*>(in->data());
+
+ const uint8_t* end = start + in->size();
+ const uint8_t* current = start;
+ for (; current != end; ++current) {
+ const uint8_t ch = *current;
+ if (ch < '0' || ch > '9') break;
+
+ // Overflow check.
+ // kMaxUint64 / 10 is also constant and will be optimized away.
+ if (value > kMaxUint64 / 10 ||
+ (value == kMaxUint64 / 10 && ch > kLastDigitOfMaxUint64)) {
+ return false;
}
+
+ value = (value * 10) + (ch - '0');
}
- *val = v;
- return (digits > 0);
+
+ *val = value;
+ const size_t digits_consumed = current - start;
+ in->remove_prefix(digits_consumed);
+ return digits_consumed != 0;
}
} // namespace leveldb
diff --git a/src/leveldb/util/logging.h b/src/leveldb/util/logging.h
index 1b450d2480..8ff2da86b4 100644
--- a/src/leveldb/util/logging.h
+++ b/src/leveldb/util/logging.h
@@ -8,9 +8,11 @@
#ifndef STORAGE_LEVELDB_UTIL_LOGGING_H_
#define STORAGE_LEVELDB_UTIL_LOGGING_H_
-#include <stdio.h>
#include <stdint.h>
+#include <stdio.h>
+
#include <string>
+
#include "port/port.h"
namespace leveldb {
@@ -19,24 +21,24 @@ class Slice;
class WritableFile;
// Append a human-readable printout of "num" to *str
-extern void AppendNumberTo(std::string* str, uint64_t num);
+void AppendNumberTo(std::string* str, uint64_t num);
// Append a human-readable printout of "value" to *str.
// Escapes any non-printable characters found in "value".
-extern void AppendEscapedStringTo(std::string* str, const Slice& value);
+void AppendEscapedStringTo(std::string* str, const Slice& value);
// Return a human-readable printout of "num"
-extern std::string NumberToString(uint64_t num);
+std::string NumberToString(uint64_t num);
// Return a human-readable version of "value".
// Escapes any non-printable characters found in "value".
-extern std::string EscapeString(const Slice& value);
+std::string EscapeString(const Slice& value);
// Parse a human-readable number from "*in" into *value. On success,
// advances "*in" past the consumed number and sets "*val" to the
// numeric value. Otherwise, returns false and leaves *in in an
// unspecified state.
-extern bool ConsumeDecimalNumber(Slice* in, uint64_t* val);
+bool ConsumeDecimalNumber(Slice* in, uint64_t* val);
} // namespace leveldb
diff --git a/src/leveldb/util/logging_test.cc b/src/leveldb/util/logging_test.cc
new file mode 100644
index 0000000000..389cbeb14f
--- /dev/null
+++ b/src/leveldb/util/logging_test.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2018 The LevelDB Authors. All rights reserved.
+// 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.
+
+#include <limits>
+#include <string>
+
+#include "leveldb/slice.h"
+#include "util/logging.h"
+#include "util/testharness.h"
+
+namespace leveldb {
+
+class Logging {};
+
+TEST(Logging, NumberToString) {
+ ASSERT_EQ("0", NumberToString(0));
+ ASSERT_EQ("1", NumberToString(1));
+ ASSERT_EQ("9", NumberToString(9));
+
+ ASSERT_EQ("10", NumberToString(10));
+ ASSERT_EQ("11", NumberToString(11));
+ ASSERT_EQ("19", NumberToString(19));
+ ASSERT_EQ("99", NumberToString(99));
+
+ ASSERT_EQ("100", NumberToString(100));
+ ASSERT_EQ("109", NumberToString(109));
+ ASSERT_EQ("190", NumberToString(190));
+ ASSERT_EQ("123", NumberToString(123));
+ ASSERT_EQ("12345678", NumberToString(12345678));
+
+ static_assert(std::numeric_limits<uint64_t>::max() == 18446744073709551615U,
+ "Test consistency check");
+ ASSERT_EQ("18446744073709551000", NumberToString(18446744073709551000U));
+ ASSERT_EQ("18446744073709551600", NumberToString(18446744073709551600U));
+ ASSERT_EQ("18446744073709551610", NumberToString(18446744073709551610U));
+ ASSERT_EQ("18446744073709551614", NumberToString(18446744073709551614U));
+ ASSERT_EQ("18446744073709551615", NumberToString(18446744073709551615U));
+}
+
+void ConsumeDecimalNumberRoundtripTest(uint64_t number,
+ const std::string& padding = "") {
+ std::string decimal_number = NumberToString(number);
+ std::string input_string = decimal_number + padding;
+ Slice input(input_string);
+ Slice output = input;
+ uint64_t result;
+ ASSERT_TRUE(ConsumeDecimalNumber(&output, &result));
+ ASSERT_EQ(number, result);
+ ASSERT_EQ(decimal_number.size(), output.data() - input.data());
+ ASSERT_EQ(padding.size(), output.size());
+}
+
+TEST(Logging, ConsumeDecimalNumberRoundtrip) {
+ ConsumeDecimalNumberRoundtripTest(0);
+ ConsumeDecimalNumberRoundtripTest(1);
+ ConsumeDecimalNumberRoundtripTest(9);
+
+ ConsumeDecimalNumberRoundtripTest(10);
+ ConsumeDecimalNumberRoundtripTest(11);
+ ConsumeDecimalNumberRoundtripTest(19);
+ ConsumeDecimalNumberRoundtripTest(99);
+
+ ConsumeDecimalNumberRoundtripTest(100);
+ ConsumeDecimalNumberRoundtripTest(109);
+ ConsumeDecimalNumberRoundtripTest(190);
+ ConsumeDecimalNumberRoundtripTest(123);
+ ASSERT_EQ("12345678", NumberToString(12345678));
+
+ for (uint64_t i = 0; i < 100; ++i) {
+ uint64_t large_number = std::numeric_limits<uint64_t>::max() - i;
+ ConsumeDecimalNumberRoundtripTest(large_number);
+ }
+}
+
+TEST(Logging, ConsumeDecimalNumberRoundtripWithPadding) {
+ ConsumeDecimalNumberRoundtripTest(0, " ");
+ ConsumeDecimalNumberRoundtripTest(1, "abc");
+ ConsumeDecimalNumberRoundtripTest(9, "x");
+
+ ConsumeDecimalNumberRoundtripTest(10, "_");
+ ConsumeDecimalNumberRoundtripTest(11, std::string("\0\0\0", 3));
+ ConsumeDecimalNumberRoundtripTest(19, "abc");
+ ConsumeDecimalNumberRoundtripTest(99, "padding");
+
+ ConsumeDecimalNumberRoundtripTest(100, " ");
+
+ for (uint64_t i = 0; i < 100; ++i) {
+ uint64_t large_number = std::numeric_limits<uint64_t>::max() - i;
+ ConsumeDecimalNumberRoundtripTest(large_number, "pad");
+ }
+}
+
+void ConsumeDecimalNumberOverflowTest(const std::string& input_string) {
+ Slice input(input_string);
+ Slice output = input;
+ uint64_t result;
+ ASSERT_EQ(false, ConsumeDecimalNumber(&output, &result));
+}
+
+TEST(Logging, ConsumeDecimalNumberOverflow) {
+ static_assert(std::numeric_limits<uint64_t>::max() == 18446744073709551615U,
+ "Test consistency check");
+ ConsumeDecimalNumberOverflowTest("18446744073709551616");
+ ConsumeDecimalNumberOverflowTest("18446744073709551617");
+ ConsumeDecimalNumberOverflowTest("18446744073709551618");
+ ConsumeDecimalNumberOverflowTest("18446744073709551619");
+ ConsumeDecimalNumberOverflowTest("18446744073709551620");
+ ConsumeDecimalNumberOverflowTest("18446744073709551621");
+ ConsumeDecimalNumberOverflowTest("18446744073709551622");
+ ConsumeDecimalNumberOverflowTest("18446744073709551623");
+ ConsumeDecimalNumberOverflowTest("18446744073709551624");
+ ConsumeDecimalNumberOverflowTest("18446744073709551625");
+ ConsumeDecimalNumberOverflowTest("18446744073709551626");
+
+ ConsumeDecimalNumberOverflowTest("18446744073709551700");
+
+ ConsumeDecimalNumberOverflowTest("99999999999999999999");
+}
+
+void ConsumeDecimalNumberNoDigitsTest(const std::string& input_string) {
+ Slice input(input_string);
+ Slice output = input;
+ uint64_t result;
+ ASSERT_EQ(false, ConsumeDecimalNumber(&output, &result));
+ ASSERT_EQ(input.data(), output.data());
+ ASSERT_EQ(input.size(), output.size());
+}
+
+TEST(Logging, ConsumeDecimalNumberNoDigits) {
+ ConsumeDecimalNumberNoDigitsTest("");
+ ConsumeDecimalNumberNoDigitsTest(" ");
+ ConsumeDecimalNumberNoDigitsTest("a");
+ ConsumeDecimalNumberNoDigitsTest(" 123");
+ ConsumeDecimalNumberNoDigitsTest("a123");
+ ConsumeDecimalNumberNoDigitsTest(std::string("\000123", 4));
+ ConsumeDecimalNumberNoDigitsTest(std::string("\177123", 4));
+ ConsumeDecimalNumberNoDigitsTest(std::string("\377123", 4));
+}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/mutexlock.h b/src/leveldb/util/mutexlock.h
index 1ff5a9efa1..0cb2e250fb 100644
--- a/src/leveldb/util/mutexlock.h
+++ b/src/leveldb/util/mutexlock.h
@@ -22,20 +22,18 @@ namespace leveldb {
class SCOPED_LOCKABLE MutexLock {
public:
- explicit MutexLock(port::Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
- : mu_(mu) {
+ explicit MutexLock(port::Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
this->mu_->Lock();
}
~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); }
+ MutexLock(const MutexLock&) = delete;
+ MutexLock& operator=(const MutexLock&) = delete;
+
private:
- port::Mutex *const mu_;
- // No copying allowed
- MutexLock(const MutexLock&);
- void operator=(const MutexLock&);
+ port::Mutex* const mu_;
};
} // namespace leveldb
-
#endif // STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_
diff --git a/src/leveldb/util/no_destructor.h b/src/leveldb/util/no_destructor.h
new file mode 100644
index 0000000000..a0d3b8703d
--- /dev/null
+++ b/src/leveldb/util/no_destructor.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2018 The LevelDB Authors. All rights reserved.
+// 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.
+
+#ifndef STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_
+#define STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_
+
+#include <type_traits>
+#include <utility>
+
+namespace leveldb {
+
+// Wraps an instance whose destructor is never called.
+//
+// This is intended for use with function-level static variables.
+template <typename InstanceType>
+class NoDestructor {
+ public:
+ template <typename... ConstructorArgTypes>
+ explicit NoDestructor(ConstructorArgTypes&&... constructor_args) {
+ static_assert(sizeof(instance_storage_) >= sizeof(InstanceType),
+ "instance_storage_ is not large enough to hold the instance");
+ static_assert(
+ alignof(decltype(instance_storage_)) >= alignof(InstanceType),
+ "instance_storage_ does not meet the instance's alignment requirement");
+ new (&instance_storage_)
+ InstanceType(std::forward<ConstructorArgTypes>(constructor_args)...);
+ }
+
+ ~NoDestructor() = default;
+
+ NoDestructor(const NoDestructor&) = delete;
+ NoDestructor& operator=(const NoDestructor&) = delete;
+
+ InstanceType* get() {
+ return reinterpret_cast<InstanceType*>(&instance_storage_);
+ }
+
+ private:
+ typename std::aligned_storage<sizeof(InstanceType),
+ alignof(InstanceType)>::type instance_storage_;
+};
+
+} // namespace leveldb
+
+#endif // STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_
diff --git a/src/leveldb/util/no_destructor_test.cc b/src/leveldb/util/no_destructor_test.cc
new file mode 100644
index 0000000000..b41caca694
--- /dev/null
+++ b/src/leveldb/util/no_destructor_test.cc
@@ -0,0 +1,47 @@
+// Copyright (c) 2018 The LevelDB Authors. All rights reserved.
+// 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.
+
+#include <cstdint>
+#include <cstdlib>
+#include <utility>
+
+#include "util/no_destructor.h"
+#include "util/testharness.h"
+
+namespace leveldb {
+
+namespace {
+
+struct DoNotDestruct {
+ public:
+ DoNotDestruct(uint32_t a, uint64_t b) : a(a), b(b) {}
+ ~DoNotDestruct() { std::abort(); }
+
+ // Used to check constructor argument forwarding.
+ uint32_t a;
+ uint64_t b;
+};
+
+constexpr const uint32_t kGoldenA = 0xdeadbeef;
+constexpr const uint64_t kGoldenB = 0xaabbccddeeffaabb;
+
+} // namespace
+
+class NoDestructorTest {};
+
+TEST(NoDestructorTest, StackInstance) {
+ NoDestructor<DoNotDestruct> instance(kGoldenA, kGoldenB);
+ ASSERT_EQ(kGoldenA, instance.get()->a);
+ ASSERT_EQ(kGoldenB, instance.get()->b);
+}
+
+TEST(NoDestructorTest, StaticInstance) {
+ static NoDestructor<DoNotDestruct> instance(kGoldenA, kGoldenB);
+ ASSERT_EQ(kGoldenA, instance.get()->a);
+ ASSERT_EQ(kGoldenB, instance.get()->b);
+}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/options.cc b/src/leveldb/util/options.cc
index b5e6227613..62de5bf0d2 100644
--- a/src/leveldb/util/options.cc
+++ b/src/leveldb/util/options.cc
@@ -9,22 +9,6 @@
namespace leveldb {
-Options::Options()
- : comparator(BytewiseComparator()),
- create_if_missing(false),
- error_if_exists(false),
- paranoid_checks(false),
- env(Env::Default()),
- info_log(NULL),
- write_buffer_size(4<<20),
- max_open_files(1000),
- block_cache(NULL),
- block_size(4096),
- block_restart_interval(16),
- max_file_size(2<<20),
- compression(kSnappyCompression),
- reuse_logs(false),
- filter_policy(NULL) {
-}
+Options::Options() : comparator(BytewiseComparator()), env(Env::Default()) {}
} // namespace leveldb
diff --git a/src/leveldb/util/posix_logger.h b/src/leveldb/util/posix_logger.h
index c063c2b7cb..28e15d10b4 100644
--- a/src/leveldb/util/posix_logger.h
+++ b/src/leveldb/util/posix_logger.h
@@ -3,94 +3,126 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// Logger implementation that can be shared by all environments
-// where enough Posix functionality is available.
+// where enough posix functionality is available.
#ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
#define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
-#include <algorithm>
-#include <stdio.h>
#include <sys/time.h>
-#include <time.h>
+
+#include <cassert>
+#include <cstdarg>
+#include <cstdio>
+#include <ctime>
+#include <sstream>
+#include <thread>
+
#include "leveldb/env.h"
namespace leveldb {
-class PosixLogger : public Logger {
- private:
- FILE* file_;
- uint64_t (*gettid_)(); // Return the thread id for the current thread
+class PosixLogger final : public Logger {
public:
- PosixLogger(FILE* f, uint64_t (*gettid)()) : file_(f), gettid_(gettid) { }
- virtual ~PosixLogger() {
- fclose(file_);
- }
- virtual void Logv(const char* format, va_list ap) {
- const uint64_t thread_id = (*gettid_)();
-
- // We try twice: the first time with a fixed-size stack allocated buffer,
- // and the second time with a much larger dynamically allocated buffer.
- char buffer[500];
- for (int iter = 0; iter < 2; iter++) {
- char* base;
- int bufsize;
- if (iter == 0) {
- bufsize = sizeof(buffer);
- base = buffer;
- } else {
- bufsize = 30000;
- base = new char[bufsize];
- }
- char* p = base;
- char* limit = base + bufsize;
-
- struct timeval now_tv;
- gettimeofday(&now_tv, NULL);
- const time_t seconds = now_tv.tv_sec;
- struct tm t;
- localtime_r(&seconds, &t);
- p += snprintf(p, limit - p,
- "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
- t.tm_year + 1900,
- t.tm_mon + 1,
- t.tm_mday,
- t.tm_hour,
- t.tm_min,
- t.tm_sec,
- static_cast<int>(now_tv.tv_usec),
- static_cast<long long unsigned int>(thread_id));
-
- // Print the message
- if (p < limit) {
- va_list backup_ap;
- va_copy(backup_ap, ap);
- p += vsnprintf(p, limit - p, format, backup_ap);
- va_end(backup_ap);
- }
+ // Creates a logger that writes to the given file.
+ //
+ // The PosixLogger instance takes ownership of the file handle.
+ explicit PosixLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); }
+
+ ~PosixLogger() override { std::fclose(fp_); }
+
+ void Logv(const char* format, va_list arguments) override {
+ // Record the time as close to the Logv() call as possible.
+ struct ::timeval now_timeval;
+ ::gettimeofday(&now_timeval, nullptr);
+ const std::time_t now_seconds = now_timeval.tv_sec;
+ struct std::tm now_components;
+ ::localtime_r(&now_seconds, &now_components);
+
+ // Record the thread ID.
+ constexpr const int kMaxThreadIdSize = 32;
+ std::ostringstream thread_stream;
+ thread_stream << std::this_thread::get_id();
+ std::string thread_id = thread_stream.str();
+ if (thread_id.size() > kMaxThreadIdSize) {
+ thread_id.resize(kMaxThreadIdSize);
+ }
- // Truncate to available space if necessary
- if (p >= limit) {
- if (iter == 0) {
- continue; // Try again with larger buffer
- } else {
- p = limit - 1;
+ // We first attempt to print into a stack-allocated buffer. If this attempt
+ // fails, we make a second attempt with a dynamically allocated buffer.
+ constexpr const int kStackBufferSize = 512;
+ char stack_buffer[kStackBufferSize];
+ static_assert(sizeof(stack_buffer) == static_cast<size_t>(kStackBufferSize),
+ "sizeof(char) is expected to be 1 in C++");
+
+ int dynamic_buffer_size = 0; // Computed in the first iteration.
+ for (int iteration = 0; iteration < 2; ++iteration) {
+ const int buffer_size =
+ (iteration == 0) ? kStackBufferSize : dynamic_buffer_size;
+ char* const buffer =
+ (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size];
+
+ // Print the header into the buffer.
+ int buffer_offset = snprintf(
+ buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ",
+ now_components.tm_year + 1900, now_components.tm_mon + 1,
+ now_components.tm_mday, now_components.tm_hour, now_components.tm_min,
+ now_components.tm_sec, static_cast<int>(now_timeval.tv_usec),
+ thread_id.c_str());
+
+ // The header can be at most 28 characters (10 date + 15 time +
+ // 3 delimiters) plus the thread ID, which should fit comfortably into the
+ // static buffer.
+ assert(buffer_offset <= 28 + kMaxThreadIdSize);
+ static_assert(28 + kMaxThreadIdSize < kStackBufferSize,
+ "stack-allocated buffer may not fit the message header");
+ assert(buffer_offset < buffer_size);
+
+ // Print the message into the buffer.
+ std::va_list arguments_copy;
+ va_copy(arguments_copy, arguments);
+ buffer_offset +=
+ std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset,
+ format, arguments_copy);
+ va_end(arguments_copy);
+
+ // The code below may append a newline at the end of the buffer, which
+ // requires an extra character.
+ if (buffer_offset >= buffer_size - 1) {
+ // The message did not fit into the buffer.
+ if (iteration == 0) {
+ // Re-run the loop and use a dynamically-allocated buffer. The buffer
+ // will be large enough for the log message, an extra newline and a
+ // null terminator.
+ dynamic_buffer_size = buffer_offset + 2;
+ continue;
}
+
+ // The dynamically-allocated buffer was incorrectly sized. This should
+ // not happen, assuming a correct implementation of (v)snprintf. Fail
+ // in tests, recover by truncating the log message in production.
+ assert(false);
+ buffer_offset = buffer_size - 1;
}
- // Add newline if necessary
- if (p == base || p[-1] != '\n') {
- *p++ = '\n';
+ // Add a newline if necessary.
+ if (buffer[buffer_offset - 1] != '\n') {
+ buffer[buffer_offset] = '\n';
+ ++buffer_offset;
}
- assert(p <= limit);
- fwrite(base, 1, p - base, file_);
- fflush(file_);
- if (base != buffer) {
- delete[] base;
+ assert(buffer_offset <= buffer_size);
+ std::fwrite(buffer, 1, buffer_offset, fp_);
+ std::fflush(fp_);
+
+ if (iteration != 0) {
+ delete[] buffer;
}
break;
}
}
+
+ private:
+ std::FILE* const fp_;
};
} // namespace leveldb
diff --git a/src/leveldb/util/random.h b/src/leveldb/util/random.h
index ddd51b1c7b..76f7daf52a 100644
--- a/src/leveldb/util/random.h
+++ b/src/leveldb/util/random.h
@@ -15,6 +15,7 @@ namespace leveldb {
class Random {
private:
uint32_t seed_;
+
public:
explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) {
// Avoid bad seeds.
@@ -23,8 +24,8 @@ class Random {
}
}
uint32_t Next() {
- static const uint32_t M = 2147483647L; // 2^31-1
- static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0
+ static const uint32_t M = 2147483647L; // 2^31-1
+ static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0
// We are computing
// seed_ = (seed_ * A) % M, where M = 2^31-1
//
@@ -54,9 +55,7 @@ class Random {
// Skewed: pick "base" uniformly from range [0,max_log] and then
// return "base" random bits. The effect is to pick a number in the
// range [0,2^max_log-1] with exponential bias towards smaller numbers.
- uint32_t Skewed(int max_log) {
- return Uniform(1 << Uniform(max_log + 1));
- }
+ uint32_t Skewed(int max_log) { return Uniform(1 << Uniform(max_log + 1)); }
};
} // namespace leveldb
diff --git a/src/leveldb/util/status.cc b/src/leveldb/util/status.cc
index a44f35b314..15ce747d80 100644
--- a/src/leveldb/util/status.cc
+++ b/src/leveldb/util/status.cc
@@ -2,9 +2,11 @@
// 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.
+#include "leveldb/status.h"
+
#include <stdio.h>
+
#include "port/port.h"
-#include "leveldb/status.h"
namespace leveldb {
@@ -18,8 +20,8 @@ const char* Status::CopyState(const char* state) {
Status::Status(Code code, const Slice& msg, const Slice& msg2) {
assert(code != kOk);
- const uint32_t len1 = msg.size();
- const uint32_t len2 = msg2.size();
+ const uint32_t len1 = static_cast<uint32_t>(msg.size());
+ const uint32_t len2 = static_cast<uint32_t>(msg2.size());
const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
char* result = new char[size + 5];
memcpy(result, &size, sizeof(size));
@@ -34,7 +36,7 @@ Status::Status(Code code, const Slice& msg, const Slice& msg2) {
}
std::string Status::ToString() const {
- if (state_ == NULL) {
+ if (state_ == nullptr) {
return "OK";
} else {
char tmp[30];
@@ -59,8 +61,8 @@ std::string Status::ToString() const {
type = "IO error: ";
break;
default:
- snprintf(tmp, sizeof(tmp), "Unknown code(%d): ",
- static_cast<int>(code()));
+ snprintf(tmp, sizeof(tmp),
+ "Unknown code(%d): ", static_cast<int>(code()));
type = tmp;
break;
}
diff --git a/src/leveldb/util/status_test.cc b/src/leveldb/util/status_test.cc
new file mode 100644
index 0000000000..2842319fbd
--- /dev/null
+++ b/src/leveldb/util/status_test.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2018 The LevelDB Authors. All rights reserved.
+// 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.
+
+#include <utility>
+
+#include "leveldb/slice.h"
+#include "leveldb/status.h"
+#include "util/testharness.h"
+
+namespace leveldb {
+
+TEST(Status, MoveConstructor) {
+ {
+ Status ok = Status::OK();
+ Status ok2 = std::move(ok);
+
+ ASSERT_TRUE(ok2.ok());
+ }
+
+ {
+ Status status = Status::NotFound("custom NotFound status message");
+ Status status2 = std::move(status);
+
+ ASSERT_TRUE(status2.IsNotFound());
+ ASSERT_EQ("NotFound: custom NotFound status message", status2.ToString());
+ }
+
+ {
+ Status self_moved = Status::IOError("custom IOError status message");
+
+ // Needed to bypass compiler warning about explicit move-assignment.
+ Status& self_moved_reference = self_moved;
+ self_moved_reference = std::move(self_moved);
+ }
+}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
diff --git a/src/leveldb/util/testharness.cc b/src/leveldb/util/testharness.cc
index 402fab34d7..318ecfa3b7 100644
--- a/src/leveldb/util/testharness.cc
+++ b/src/leveldb/util/testharness.cc
@@ -4,11 +4,15 @@
#include "util/testharness.h"
-#include <string>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <string>
+#include <vector>
+
+#include "leveldb/env.h"
+
namespace leveldb {
namespace test {
@@ -19,10 +23,10 @@ struct Test {
void (*func)();
};
std::vector<Test>* tests;
-}
+} // namespace
bool RegisterTest(const char* base, const char* name, void (*func)()) {
- if (tests == NULL) {
+ if (tests == nullptr) {
tests = new std::vector<Test>;
}
Test t;
@@ -37,14 +41,14 @@ int RunAllTests() {
const char* matcher = getenv("LEVELDB_TESTS");
int num = 0;
- if (tests != NULL) {
+ if (tests != nullptr) {
for (size_t i = 0; i < tests->size(); i++) {
const Test& t = (*tests)[i];
- if (matcher != NULL) {
+ if (matcher != nullptr) {
std::string name = t.base;
name.push_back('.');
name.append(t.name);
- if (strstr(name.c_str(), matcher) == NULL) {
+ if (strstr(name.c_str(), matcher) == nullptr) {
continue;
}
}
@@ -66,7 +70,7 @@ std::string TmpDir() {
int RandomSeed() {
const char* env = getenv("TEST_RANDOM_SEED");
- int result = (env != NULL ? atoi(env) : 301);
+ int result = (env != nullptr ? atoi(env) : 301);
if (result <= 0) {
result = 301;
}
diff --git a/src/leveldb/util/testharness.h b/src/leveldb/util/testharness.h
index da4fe68bb4..72cd1629eb 100644
--- a/src/leveldb/util/testharness.h
+++ b/src/leveldb/util/testharness.h
@@ -7,10 +7,10 @@
#include <stdio.h>
#include <stdlib.h>
+
#include <sstream>
-#include "leveldb/env.h"
-#include "leveldb/slice.h"
-#include "util/random.h"
+
+#include "leveldb/status.h"
namespace leveldb {
namespace test {
@@ -27,15 +27,15 @@ namespace test {
//
// Returns 0 if all tests pass.
// Dies or returns a non-zero value if some test fails.
-extern int RunAllTests();
+int RunAllTests();
// Return the directory to use for temporary storage.
-extern std::string TmpDir();
+std::string TmpDir();
// Return a randomization seed for this run. Typically returns the
// same number on repeated invocations of this binary, but automated
// runs may be able to vary the seed.
-extern int RandomSeed();
+int RandomSeed();
// An instance of Tester is allocated to hold temporary state during
// the execution of an assertion.
@@ -47,9 +47,7 @@ class Tester {
std::stringstream ss_;
public:
- Tester(const char* f, int l)
- : ok_(true), fname_(f), line_(l) {
- }
+ Tester(const char* f, int l) : ok_(true), fname_(f), line_(l) {}
~Tester() {
if (!ok_) {
@@ -74,14 +72,14 @@ class Tester {
return *this;
}
-#define BINARY_OP(name,op) \
- template <class X, class Y> \
- Tester& name(const X& x, const Y& y) { \
- if (! (x op y)) { \
- ss_ << " failed: " << x << (" " #op " ") << y; \
- ok_ = false; \
- } \
- return *this; \
+#define BINARY_OP(name, op) \
+ template <class X, class Y> \
+ Tester& name(const X& x, const Y& y) { \
+ if (!(x op y)) { \
+ ss_ << " failed: " << x << (" " #op " ") << y; \
+ ok_ = false; \
+ } \
+ return *this; \
}
BINARY_OP(IsEq, ==)
@@ -104,33 +102,38 @@ class Tester {
#define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c)
#define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s))
-#define ASSERT_EQ(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a),(b))
-#define ASSERT_NE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a),(b))
-#define ASSERT_GE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a),(b))
-#define ASSERT_GT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a),(b))
-#define ASSERT_LE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a),(b))
-#define ASSERT_LT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a),(b))
-
-#define TCONCAT(a,b) TCONCAT1(a,b)
-#define TCONCAT1(a,b) a##b
-
-#define TEST(base,name) \
-class TCONCAT(_Test_,name) : public base { \
- public: \
- void _Run(); \
- static void _RunIt() { \
- TCONCAT(_Test_,name) t; \
- t._Run(); \
- } \
-}; \
-bool TCONCAT(_Test_ignored_,name) = \
- ::leveldb::test::RegisterTest(#base, #name, &TCONCAT(_Test_,name)::_RunIt); \
-void TCONCAT(_Test_,name)::_Run()
+#define ASSERT_EQ(a, b) \
+ ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a), (b))
+#define ASSERT_NE(a, b) \
+ ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a), (b))
+#define ASSERT_GE(a, b) \
+ ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a), (b))
+#define ASSERT_GT(a, b) \
+ ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a), (b))
+#define ASSERT_LE(a, b) \
+ ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a), (b))
+#define ASSERT_LT(a, b) \
+ ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a), (b))
+
+#define TCONCAT(a, b) TCONCAT1(a, b)
+#define TCONCAT1(a, b) a##b
+
+#define TEST(base, name) \
+ class TCONCAT(_Test_, name) : public base { \
+ public: \
+ void _Run(); \
+ static void _RunIt() { \
+ TCONCAT(_Test_, name) t; \
+ t._Run(); \
+ } \
+ }; \
+ bool TCONCAT(_Test_ignored_, name) = ::leveldb::test::RegisterTest( \
+ #base, #name, &TCONCAT(_Test_, name)::_RunIt); \
+ void TCONCAT(_Test_, name)::_Run()
// Register the specified test. Typically not used directly, but
// invoked via the macro expansion of TEST.
-extern bool RegisterTest(const char* base, const char* name, void (*func)());
-
+bool RegisterTest(const char* base, const char* name, void (*func)());
} // namespace test
} // namespace leveldb
diff --git a/src/leveldb/util/testutil.cc b/src/leveldb/util/testutil.cc
index bee56bf75f..6b151b9e64 100644
--- a/src/leveldb/util/testutil.cc
+++ b/src/leveldb/util/testutil.cc
@@ -12,7 +12,7 @@ namespace test {
Slice RandomString(Random* rnd, int len, std::string* dst) {
dst->resize(len);
for (int i = 0; i < len; i++) {
- (*dst)[i] = static_cast<char>(' ' + rnd->Uniform(95)); // ' ' .. '~'
+ (*dst)[i] = static_cast<char>(' ' + rnd->Uniform(95)); // ' ' .. '~'
}
return Slice(*dst);
}
@@ -20,9 +20,8 @@ Slice RandomString(Random* rnd, int len, std::string* dst) {
std::string RandomKey(Random* rnd, int len) {
// Make sure to generate a wide variety of characters so we
// test the boundary conditions for short-key optimizations.
- static const char kTestChars[] = {
- '\0', '\1', 'a', 'b', 'c', 'd', 'e', '\xfd', '\xfe', '\xff'
- };
+ static const char kTestChars[] = {'\0', '\1', 'a', 'b', 'c',
+ 'd', 'e', '\xfd', '\xfe', '\xff'};
std::string result;
for (int i = 0; i < len; i++) {
result += kTestChars[rnd->Uniform(sizeof(kTestChars))];
@@ -30,9 +29,8 @@ std::string RandomKey(Random* rnd, int len) {
return result;
}
-
-extern Slice CompressibleString(Random* rnd, double compressed_fraction,
- size_t len, std::string* dst) {
+Slice CompressibleString(Random* rnd, double compressed_fraction, size_t len,
+ std::string* dst) {
int raw = static_cast<int>(len * compressed_fraction);
if (raw < 1) raw = 1;
std::string raw_data;
diff --git a/src/leveldb/util/testutil.h b/src/leveldb/util/testutil.h
index d7e4583702..bb4051ba07 100644
--- a/src/leveldb/util/testutil.h
+++ b/src/leveldb/util/testutil.h
@@ -5,6 +5,7 @@
#ifndef STORAGE_LEVELDB_UTIL_TESTUTIL_H_
#define STORAGE_LEVELDB_UTIL_TESTUTIL_H_
+#include "helpers/memenv/memenv.h"
#include "leveldb/env.h"
#include "leveldb/slice.h"
#include "util/random.h"
@@ -14,17 +15,17 @@ namespace test {
// Store in *dst a random string of length "len" and return a Slice that
// references the generated data.
-extern Slice RandomString(Random* rnd, int len, std::string* dst);
+Slice RandomString(Random* rnd, int len, std::string* dst);
// Return a random key with the specified length that may contain interesting
// characters (e.g. \x00, \xff, etc.).
-extern std::string RandomKey(Random* rnd, int len);
+std::string RandomKey(Random* rnd, int len);
// Store in *dst a string of length "len" that will compress to
// "N*compressed_fraction" bytes and return a Slice that references
// the generated data.
-extern Slice CompressibleString(Random* rnd, double compressed_fraction,
- size_t len, std::string* dst);
+Slice CompressibleString(Random* rnd, double compressed_fraction, size_t len,
+ std::string* dst);
// A wrapper that allows injection of errors.
class ErrorEnv : public EnvWrapper {
@@ -32,25 +33,27 @@ class ErrorEnv : public EnvWrapper {
bool writable_file_error_;
int num_writable_file_errors_;
- ErrorEnv() : EnvWrapper(Env::Default()),
- writable_file_error_(false),
- num_writable_file_errors_(0) { }
+ ErrorEnv()
+ : EnvWrapper(NewMemEnv(Env::Default())),
+ writable_file_error_(false),
+ num_writable_file_errors_(0) {}
+ ~ErrorEnv() override { delete target(); }
- virtual Status NewWritableFile(const std::string& fname,
- WritableFile** result) {
+ Status NewWritableFile(const std::string& fname,
+ WritableFile** result) override {
if (writable_file_error_) {
++num_writable_file_errors_;
- *result = NULL;
+ *result = nullptr;
return Status::IOError(fname, "fake error");
}
return target()->NewWritableFile(fname, result);
}
- virtual Status NewAppendableFile(const std::string& fname,
- WritableFile** result) {
+ Status NewAppendableFile(const std::string& fname,
+ WritableFile** result) override {
if (writable_file_error_) {
++num_writable_file_errors_;
- *result = NULL;
+ *result = nullptr;
return Status::IOError(fname, "fake error");
}
return target()->NewAppendableFile(fname, result);
diff --git a/src/leveldb/util/windows_logger.h b/src/leveldb/util/windows_logger.h
new file mode 100644
index 0000000000..92960638d1
--- /dev/null
+++ b/src/leveldb/util/windows_logger.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2018 The LevelDB Authors. All rights reserved.
+// 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.
+//
+// Logger implementation for the Windows platform.
+
+#ifndef STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_
+#define STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_
+
+#include <cassert>
+#include <cstdarg>
+#include <cstdio>
+#include <ctime>
+#include <sstream>
+#include <thread>
+
+#include "leveldb/env.h"
+
+namespace leveldb {
+
+class WindowsLogger final : public Logger {
+ public:
+ // Creates a logger that writes to the given file.
+ //
+ // The PosixLogger instance takes ownership of the file handle.
+ explicit WindowsLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); }
+
+ ~WindowsLogger() override { std::fclose(fp_); }
+
+ void Logv(const char* format, va_list arguments) override {
+ // Record the time as close to the Logv() call as possible.
+ SYSTEMTIME now_components;
+ ::GetLocalTime(&now_components);
+
+ // Record the thread ID.
+ constexpr const int kMaxThreadIdSize = 32;
+ std::ostringstream thread_stream;
+ thread_stream << std::this_thread::get_id();
+ std::string thread_id = thread_stream.str();
+ if (thread_id.size() > kMaxThreadIdSize) {
+ thread_id.resize(kMaxThreadIdSize);
+ }
+
+ // We first attempt to print into a stack-allocated buffer. If this attempt
+ // fails, we make a second attempt with a dynamically allocated buffer.
+ constexpr const int kStackBufferSize = 512;
+ char stack_buffer[kStackBufferSize];
+ static_assert(sizeof(stack_buffer) == static_cast<size_t>(kStackBufferSize),
+ "sizeof(char) is expected to be 1 in C++");
+
+ int dynamic_buffer_size = 0; // Computed in the first iteration.
+ for (int iteration = 0; iteration < 2; ++iteration) {
+ const int buffer_size =
+ (iteration == 0) ? kStackBufferSize : dynamic_buffer_size;
+ char* const buffer =
+ (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size];
+
+ // Print the header into the buffer.
+ int buffer_offset = snprintf(
+ buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ",
+ now_components.wYear, now_components.wMonth, now_components.wDay,
+ now_components.wHour, now_components.wMinute, now_components.wSecond,
+ static_cast<int>(now_components.wMilliseconds * 1000),
+ thread_id.c_str());
+
+ // The header can be at most 28 characters (10 date + 15 time +
+ // 3 delimiters) plus the thread ID, which should fit comfortably into the
+ // static buffer.
+ assert(buffer_offset <= 28 + kMaxThreadIdSize);
+ static_assert(28 + kMaxThreadIdSize < kStackBufferSize,
+ "stack-allocated buffer may not fit the message header");
+ assert(buffer_offset < buffer_size);
+
+ // Print the message into the buffer.
+ std::va_list arguments_copy;
+ va_copy(arguments_copy, arguments);
+ buffer_offset +=
+ std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset,
+ format, arguments_copy);
+ va_end(arguments_copy);
+
+ // The code below may append a newline at the end of the buffer, which
+ // requires an extra character.
+ if (buffer_offset >= buffer_size - 1) {
+ // The message did not fit into the buffer.
+ if (iteration == 0) {
+ // Re-run the loop and use a dynamically-allocated buffer. The buffer
+ // will be large enough for the log message, an extra newline and a
+ // null terminator.
+ dynamic_buffer_size = buffer_offset + 2;
+ continue;
+ }
+
+ // The dynamically-allocated buffer was incorrectly sized. This should
+ // not happen, assuming a correct implementation of (v)snprintf. Fail
+ // in tests, recover by truncating the log message in production.
+ assert(false);
+ buffer_offset = buffer_size - 1;
+ }
+
+ // Add a newline if necessary.
+ if (buffer[buffer_offset - 1] != '\n') {
+ buffer[buffer_offset] = '\n';
+ ++buffer_offset;
+ }
+
+ assert(buffer_offset <= buffer_size);
+ std::fwrite(buffer, 1, buffer_offset, fp_);
+ std::fflush(fp_);
+
+ if (iteration != 0) {
+ delete[] buffer;
+ }
+ break;
+ }
+ }
+
+ private:
+ std::FILE* const fp_;
+};
+
+} // namespace leveldb
+
+#endif // STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_
diff --git a/src/logging.cpp b/src/logging.cpp
index 6fd916b603..eb9da06d9b 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -182,30 +182,15 @@ bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str)
return false;
}
-std::string ListLogCategories()
+std::vector<LogCategory> BCLog::Logger::LogCategoriesList()
{
- std::string ret;
- int outcount = 0;
+ std::vector<LogCategory> ret;
for (const CLogCategoryDesc& category_desc : LogCategories) {
// Omit the special cases.
if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL) {
- if (outcount != 0) ret += ", ";
- ret += category_desc.category;
- outcount++;
- }
- }
- return ret;
-}
-
-std::vector<CLogCategoryActive> ListActiveLogCategories()
-{
- std::vector<CLogCategoryActive> ret;
- for (const CLogCategoryDesc& category_desc : LogCategories) {
- // Omit the special cases.
- if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL) {
- CLogCategoryActive catActive;
+ LogCategory catActive;
catActive.category = category_desc.category;
- catActive.active = LogAcceptCategory(category_desc.flag);
+ catActive.active = WillLogCategory(category_desc.flag);
ret.push_back(catActive);
}
}
diff --git a/src/logging.h b/src/logging.h
index b2fde1b9ea..ab07010316 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -8,6 +8,7 @@
#include <fs.h>
#include <tinyformat.h>
+#include <util/string.h>
#include <atomic>
#include <cstdint>
@@ -24,8 +25,7 @@ extern const char * const DEFAULT_DEBUGLOGFILE;
extern bool fLogIPs;
-struct CLogCategoryActive
-{
+struct LogCategory {
std::string category;
bool active;
};
@@ -132,6 +132,13 @@ namespace BCLog {
bool DisableCategory(const std::string& str);
bool WillLogCategory(LogFlags category) const;
+ /** Returns a vector of the log categories */
+ std::vector<LogCategory> LogCategoriesList();
+ /** Returns a string with the log categories */
+ std::string LogCategoriesString()
+ {
+ return Join(LogCategoriesList(), ", ", [&](const LogCategory& i) { return i.category; });
+ };
bool DefaultShrinkDebugFile() const;
};
@@ -146,12 +153,6 @@ static inline bool LogAcceptCategory(BCLog::LogFlags category)
return LogInstance().WillLogCategory(category);
}
-/** Returns a string with the log categories. */
-std::string ListLogCategories();
-
-/** Returns a vector of the active log categories. */
-std::vector<CLogCategoryActive> ListActiveLogCategories();
-
/** Return true if str parses as a log category and set the flag */
bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str);
diff --git a/src/logging/timer.h b/src/logging/timer.h
index 45bfc4aa65..21bb3d121e 100644
--- a/src/logging/timer.h
+++ b/src/logging/timer.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -85,7 +85,7 @@ private:
const std::string m_title{};
//! Forwarded on to LogPrint if specified - has the effect of only
- //! outputing the timing log when a particular debug= category is specified.
+ //! outputting the timing log when a particular debug= category is specified.
const BCLog::LogFlags m_log_category{};
};
diff --git a/src/memusage.h b/src/memusage.h
index 3ae9face15..a6e894129a 100644
--- a/src/memusage.h
+++ b/src/memusage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -6,9 +6,11 @@
#define BITCOIN_MEMUSAGE_H
#include <indirectmap.h>
+#include <prevector.h>
#include <stdlib.h>
+#include <cassert>
#include <map>
#include <memory>
#include <set>
diff --git a/src/miner.cpp b/src/miner.cpp
index 6f4e10b6ed..d9dcbe8a70 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -20,7 +20,6 @@
#include <timedata.h>
#include <util/moneystr.h>
#include <util/system.h>
-#include <util/validation.h>
#include <algorithm>
#include <utility>
@@ -40,6 +39,17 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
return nNewTime - nOldTime;
}
+void RegenerateCommitments(CBlock& block)
+{
+ CMutableTransaction tx{*block.vtx.at(0)};
+ tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block));
+ block.vtx.at(0) = MakeTransactionRef(tx);
+
+ GenerateCoinbaseCommitment(block, WITH_LOCK(cs_main, return LookupBlockIndex(block.hashPrevBlock)), Params().GetConsensus());
+
+ block.hashMerkleRoot = BlockMerkleRoot(block);
+}
+
BlockAssembler::Options::Options() {
blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
@@ -167,7 +177,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
BlockValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
- throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
+ throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString()));
}
int64_t nTime2 = GetTimeMicros();
diff --git a/src/miner.h b/src/miner.h
index cc8fc31a9f..69296f9078 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -203,4 +203,7 @@ private:
void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
+/** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */
+void RegenerateCommitments(CBlock& block);
+
#endif // BITCOIN_MINER_H
diff --git a/src/net.cpp b/src/net.cpp
index 9cd2d30d9d..dcc613ba88 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -45,8 +45,8 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"
#include <math.h>
-// Dump addresses to peers.dat every 15 minutes (900s)
-static constexpr int DUMP_PEERS_INTERVAL = 15 * 60;
+// How often to dump addresses to peers.dat
+static constexpr std::chrono::minutes DUMP_PEERS_INTERVAL{15};
/** Number of DNS seeds to query when the number of connections is low. */
static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3;
@@ -498,7 +498,7 @@ void CNode::SetAddrLocal(const CService& addrLocalIn) {
#undef X
#define X(name) stats.name = name
-void CNode::copyStats(CNodeStats &stats, std::vector<bool> &m_asmap)
+void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
{
stats.nodeid = this->GetId();
X(nServices);
@@ -555,9 +555,9 @@ void CNode::copyStats(CNodeStats &stats, std::vector<bool> &m_asmap)
}
// Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
- stats.dPingTime = (((double)nPingUsecTime) / 1e6);
- stats.dMinPing = (((double)nMinPingUsecTime) / 1e6);
- stats.dPingWait = (((double)nPingUsecWait) / 1e6);
+ stats.m_ping_usec = nPingUsecTime;
+ stats.m_min_ping_usec = nMinPingUsecTime;
+ stats.m_ping_wait_usec = nPingUsecWait;
// Leave string empty if addrLocal invalid (not filled in yet)
CService addrLocalUnlocked = GetAddrLocal();
@@ -718,6 +718,19 @@ CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageSta
return msg;
}
+void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) {
+ // create dbl-sha256 checksum
+ uint256 hash = Hash(msg.data.begin(), msg.data.end());
+
+ // create header
+ CMessageHeader hdr(Params().MessageStart(), msg.command.c_str(), msg.data.size());
+ memcpy(hdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
+
+ // serialize header
+ header.reserve(CMessageHeader::HEADER_SIZE);
+ CVectorWriter{SER_NETWORK, INIT_PROTO_VERSION, header, 0, hdr};
+}
+
size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pnode->cs_vSend)
{
auto it = pnode->vSendMsg.begin();
@@ -2330,7 +2343,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
threadMessageHandler = std::thread(&TraceThread<std::function<void()> >, "msghand", std::function<void()>(std::bind(&CConnman::ThreadMessageHandler, this)));
// Dump network addresses
- scheduler.scheduleEvery(std::bind(&CConnman::DumpAddresses, this), DUMP_PEERS_INTERVAL * 1000);
+ scheduler.scheduleEvery([this] { DumpAddresses(); }, DUMP_PEERS_INTERVAL);
return true;
}
@@ -2374,7 +2387,7 @@ void CConnman::Interrupt()
}
}
-void CConnman::Stop()
+void CConnman::StopThreads()
{
if (threadMessageHandler.joinable())
threadMessageHandler.join();
@@ -2386,14 +2399,17 @@ void CConnman::Stop()
threadDNSAddressSeed.join();
if (threadSocketHandler.joinable())
threadSocketHandler.join();
+}
- if (fAddressesInitialized)
- {
+void CConnman::StopNodes()
+{
+ if (fAddressesInitialized) {
DumpAddresses();
fAddressesInitialized = false;
}
// Close sockets
+ LOCK(cs_vNodes);
for (CNode* pnode : vNodes)
pnode->CloseSocketDisconnect();
for (ListenSocket& hListenSocket : vhListenSocket)
@@ -2402,10 +2418,10 @@ void CConnman::Stop()
LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
// clean up some globals (to help leak detection)
- for (CNode *pnode : vNodes) {
+ for (CNode* pnode : vNodes) {
DeleteNode(pnode);
}
- for (CNode *pnode : vNodesDisconnected) {
+ for (CNode* pnode : vNodesDisconnected) {
DeleteNode(pnode);
}
vNodes.clear();
@@ -2420,7 +2436,7 @@ void CConnman::DeleteNode(CNode* pnode)
assert(pnode);
bool fUpdateConnectionTime = false;
m_msgproc->FinalizeNode(pnode->GetId(), fUpdateConnectionTime);
- if(fUpdateConnectionTime) {
+ if (fUpdateConnectionTime) {
addrman.Connected(pnode->addr);
}
delete pnode;
@@ -2705,6 +2721,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
}
m_deserializer = MakeUnique<V1TransportDeserializer>(V1TransportDeserializer(Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION));
+ m_serializer = MakeUnique<V1TransportSerializer>(V1TransportSerializer());
}
CNode::~CNode()
@@ -2720,16 +2737,12 @@ bool CConnman::NodeFullyConnected(const CNode* pnode)
void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
{
size_t nMessageSize = msg.data.size();
- size_t nTotalSize = nMessageSize + CMessageHeader::HEADER_SIZE;
LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command), nMessageSize, pnode->GetId());
+ // make sure we use the appropriate network transport format
std::vector<unsigned char> serializedHeader;
- serializedHeader.reserve(CMessageHeader::HEADER_SIZE);
- uint256 hash = Hash(msg.data.data(), msg.data.data() + nMessageSize);
- CMessageHeader hdr(Params().MessageStart(), msg.command.c_str(), nMessageSize);
- memcpy(hdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
-
- CVectorWriter{SER_NETWORK, INIT_PROTO_VERSION, serializedHeader, 0, hdr};
+ pnode->m_serializer->prepareForTransport(msg, serializedHeader);
+ size_t nTotalSize = nMessageSize + serializedHeader.size();
size_t nBytesSent = 0;
{
diff --git a/src/net.h b/src/net.h
index f23cae323e..0d79efbba7 100644
--- a/src/net.h
+++ b/src/net.h
@@ -45,16 +45,10 @@ static const bool DEFAULT_WHITELISTRELAY = true;
/** Default for -whitelistforcerelay. */
static const bool DEFAULT_WHITELISTFORCERELAY = false;
-/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
-static const int PING_INTERVAL = 2 * 60;
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
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;
-/** The maximum number of entries in an 'inv' protocol message */
-static const unsigned int MAX_INV_SZ = 50000;
-/** The maximum number of entries in a locator */
-static const unsigned int MAX_LOCATOR_SZ = 101;
/** The maximum number of new addresses to accumulate before announcing. */
static const unsigned int MAX_ADDR_TO_SEND = 1000;
/** Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable). */
@@ -188,16 +182,13 @@ public:
~CConnman();
bool Start(CScheduler& scheduler, const Options& options);
- // TODO: Remove NO_THREAD_SAFETY_ANALYSIS. Lock cs_vNodes before reading the variable vNodes.
- //
- // When removing NO_THREAD_SAFETY_ANALYSIS be aware of the following lock order requirements:
- // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount
- // which locks cs_vNodes.
- // * ProcessMessage locks cs_main and g_cs_orphans before indirectly calling ForEachNode which
- // locks cs_vNodes.
- //
- // Thus the implicit locking order requirement is: (1) cs_main, (2) g_cs_orphans, (3) cs_vNodes.
- void Stop() NO_THREAD_SAFETY_ANALYSIS;
+ void StopThreads();
+ void StopNodes();
+ void Stop()
+ {
+ StopThreads();
+ StopNodes();
+ };
void Interrupt();
bool GetNetworkActive() const { return fNetworkActive; };
@@ -331,7 +322,7 @@ public:
*/
int64_t PoissonNextSendInbound(int64_t now, int average_interval_seconds);
- void SetAsmap(std::vector<bool> asmap) { addrman.m_asmap = asmap; }
+ void SetAsmap(std::vector<bool> asmap) { addrman.m_asmap = std::move(asmap); }
private:
struct ListenSocket {
@@ -482,6 +473,7 @@ private:
std::atomic<int64_t> m_next_send_inv_to_incoming{0};
friend struct CConnmanTest;
+ friend struct ConnmanTestMsg;
};
void Discover();
void StartMapPort();
@@ -596,9 +588,9 @@ public:
mapMsgCmdSize mapRecvBytesPerMsgCmd;
NetPermissionFlags m_permissionFlags;
bool m_legacyWhitelisted;
- double dPingTime;
- double dPingWait;
- double dMinPing;
+ int64_t m_ping_usec;
+ int64_t m_ping_wait_usec;
+ int64_t m_min_ping_usec;
CAmount minFeeFilter;
// Our address, as reported by the peer
std::string addrLocal;
@@ -703,12 +695,29 @@ public:
CNetMessage GetMessage(const CMessageHeader::MessageStartChars& message_start, int64_t time) override;
};
+/** The TransportSerializer prepares messages for the network transport
+ */
+class TransportSerializer {
+public:
+ // prepare message for transport (header construction, error-correction computation, payload encryption, etc.)
+ virtual void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) = 0;
+ virtual ~TransportSerializer() {}
+};
+
+class V1TransportSerializer : public TransportSerializer {
+public:
+ void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) override;
+};
+
/** Information about a peer */
class CNode
{
friend class CConnman;
+ friend struct ConnmanTestMsg;
+
public:
std::unique_ptr<TransportDeserializer> m_deserializer;
+ std::unique_ptr<TransportSerializer> m_serializer;
// socket
std::atomic<ServiceFlags> nServices{NODE_NONE};
@@ -782,8 +791,8 @@ public:
std::vector<CAddress> vAddrToSend;
const std::unique_ptr<CRollingBloomFilter> m_addr_known;
bool fGetAddr{false};
- int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0};
- int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0};
+ std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0};
+ std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0};
bool IsAddrRelayPeer() const { return m_addr_known != nullptr; }
@@ -794,14 +803,13 @@ public:
RecursiveMutex cs_inventory;
struct TxRelay {
- TxRelay() { pfilter = MakeUnique<CBloomFilter>(); }
mutable RecursiveMutex cs_filter;
// We use fRelayTxes for two purposes -
// a) it allows us to not relay tx invs before receiving the peer's version message
// b) the peer may tell us in its version message that we should not relay tx invs
// unless it loads a bloom filter.
bool fRelayTxes GUARDED_BY(cs_filter){false};
- std::unique_ptr<CBloomFilter> pfilter PT_GUARDED_BY(cs_filter) GUARDED_BY(cs_filter);
+ std::unique_ptr<CBloomFilter> pfilter PT_GUARDED_BY(cs_filter) GUARDED_BY(cs_filter){nullptr};
mutable RecursiveMutex cs_tx_inventory;
CRollingBloomFilter filterInventoryKnown GUARDED_BY(cs_tx_inventory){50000, 0.000001};
@@ -983,7 +991,7 @@ public:
void CloseSocketDisconnect();
- void copyStats(CNodeStats &stats, std::vector<bool> &m_asmap);
+ void copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap);
ServiceFlags GetLocalServices() const
{
diff --git a/src/net_permissions.h b/src/net_permissions.h
index a06d2f544d..962a2159fc 100644
--- a/src/net_permissions.h
+++ b/src/net_permissions.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -15,7 +15,7 @@ enum NetPermissionFlags
PF_BLOOMFILTER = (1U << 1),
// Relay and accept transactions from this peer, even if -blocksonly is true
PF_RELAY = (1U << 3),
- // Always relay transactions from this peer, even if already in mempool or rejected from policy
+ // Always relay transactions from this peer, even if already in mempool
// Keep parameter interaction: forcerelay implies relay
PF_FORCERELAY = (1U << 2) | PF_RELAY,
// Can't be banned for misbehavior
@@ -59,4 +59,4 @@ public:
CSubNet m_subnet;
};
-#endif // BITCOIN_NET_PERMISSIONS_H \ No newline at end of file
+#endif // BITCOIN_NET_PERMISSIONS_H
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index cf4aee0647..50a8a8a882 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -26,7 +26,6 @@
#include <txmempool.h>
#include <util/system.h>
#include <util/strencodings.h>
-#include <util/validation.h>
#include <memory>
#include <typeinfo>
@@ -65,6 +64,12 @@ static constexpr int STALE_RELAY_AGE_LIMIT = 30 * 24 * 60 * 60;
/// Age after which a block is considered historical for purposes of rate
/// limiting block relay. Set to one week, denominated in seconds.
static constexpr int HISTORICAL_BLOCK_AGE = 7 * 24 * 60 * 60;
+/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
+static const int PING_INTERVAL = 2 * 60;
+/** The maximum number of entries in a locator */
+static const unsigned int MAX_LOCATOR_SZ = 101;
+/** The maximum number of entries in an 'inv' protocol message */
+static const unsigned int MAX_INV_SZ = 50000;
/** Maximum number of in-flight transactions from a peer */
static constexpr int32_t MAX_PEER_TX_IN_FLIGHT = 100;
/** Maximum number of announced transactions from a peer */
@@ -81,7 +86,47 @@ static_assert(INBOUND_PEER_TX_DELAY >= MAX_GETDATA_RANDOM_DELAY,
"To preserve security, MAX_GETDATA_RANDOM_DELAY should not exceed INBOUND_PEER_DELAY");
/** Limit to avoid sending big packets. Not used in processing incoming GETDATA for compatibility */
static const unsigned int MAX_GETDATA_SZ = 1000;
-
+/** Number of blocks that can be requested at any given time from a single peer. */
+static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
+/** Timeout in seconds during which a peer must stall block download progress before being disconnected. */
+static const unsigned int BLOCK_STALLING_TIMEOUT = 2;
+/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
+ * less than this number, we reached its tip. Changing this value is a protocol upgrade. */
+static const unsigned int MAX_HEADERS_RESULTS = 2000;
+/** Maximum depth of blocks we're willing to serve as compact blocks to peers
+ * when requested. For older blocks, a regular BLOCK response will be sent. */
+static const int MAX_CMPCTBLOCK_DEPTH = 5;
+/** Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for. */
+static const int MAX_BLOCKTXN_DEPTH = 10;
+/** Size of the "block download window": how far ahead of our current height do we fetch?
+ * Larger windows tolerate larger download speed differences between peer, but increase the potential
+ * degree of disordering of blocks on disk (which make reindexing and pruning harder). We'll probably
+ * want to make this a per-peer adaptive value at some point. */
+static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
+/** Block download timeout base, expressed in millionths of the block interval (i.e. 10 min) */
+static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000;
+/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
+static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000;
+/** Maximum number of headers to announce when relaying blocks with headers message.*/
+static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
+/** Maximum number of unconnecting headers announcements before DoS score */
+static const int MAX_UNCONNECTING_HEADERS = 10;
+/** Minimum blocks required to signal NODE_NETWORK_LIMITED */
+static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
+/** Average delay between local address broadcasts */
+static constexpr std::chrono::hours AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24};
+/** Average delay between peer address broadcasts */
+static constexpr std::chrono::seconds AVG_ADDRESS_BROADCAST_INTERVAL{30};
+/** Average delay between trickled inventory transmissions in seconds.
+ * Blocks and whitelisted receivers bypass this, outbound peers get half this delay. */
+static const unsigned int INVENTORY_BROADCAST_INTERVAL = 5;
+/** Maximum number of inventory items to send per transmission.
+ * Limits the impact of low-fee transaction floods. */
+static constexpr unsigned int INVENTORY_BROADCAST_MAX = 7 * INVENTORY_BROADCAST_INTERVAL;
+/** Average delay between feefilter broadcasts in seconds. */
+static constexpr unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60;
+/** Maximum feefilter broadcast delay after significant change. */
+static constexpr unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60;
struct COrphanTx {
// When modifying, adapt the copy of this definition in tests/DoS_tests.
@@ -98,21 +143,6 @@ void EraseOrphansFor(NodeId peer);
/** Increase a node's misbehavior score. */
void Misbehaving(NodeId nodeid, int howmuch, const std::string& message="") EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/** Average delay between local address broadcasts in seconds. */
-static constexpr unsigned int AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24 * 60 * 60;
-/** Average delay between peer address broadcasts in seconds. */
-static const unsigned int AVG_ADDRESS_BROADCAST_INTERVAL = 30;
-/** Average delay between trickled inventory transmissions in seconds.
- * Blocks and whitelisted receivers bypass this, outbound peers get half this delay. */
-static const unsigned int INVENTORY_BROADCAST_INTERVAL = 5;
-/** Maximum number of inventory items to send per transmission.
- * Limits the impact of low-fee transaction floods. */
-static constexpr unsigned int INVENTORY_BROADCAST_MAX = 7 * INVENTORY_BROADCAST_INTERVAL;
-/** Average delay between feefilter broadcasts in seconds. */
-static constexpr unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60;
-/** Maximum feefilter broadcast delay after significant change. */
-static constexpr unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60;
-
// Internal stuff
namespace {
/** Number of nodes with fSyncStarted. */
@@ -466,7 +496,7 @@ static bool MarkBlockAsReceived(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs
// returns false, still setting pit, if the block was already in flight from the same peer
// pit will only be valid as long as the same cs_main lock is being held
-static bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlockIndex* pindex = nullptr, std::list<QueuedBlock>::iterator** pit = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
+static bool MarkBlockAsInFlight(CTxMemPool& mempool, NodeId nodeid, const uint256& hash, const CBlockIndex* pindex = nullptr, std::list<QueuedBlock>::iterator** pit = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
CNodeState *state = State(nodeid);
assert(state != nullptr);
@@ -780,6 +810,19 @@ void PeerLogicValidation::InitializeNode(CNode *pnode) {
PushNodeVersion(pnode, connman, GetTime());
}
+void PeerLogicValidation::ReattemptInitialBroadcast(CScheduler& scheduler) const
+{
+ std::set<uint256> unbroadcast_txids = m_mempool.GetUnbroadcastTxs();
+
+ for (const uint256& txid : unbroadcast_txids) {
+ RelayTransaction(txid, *connman);
+ }
+
+ // schedule next run for 10-15 minutes in the future
+ const std::chrono::milliseconds delta = std::chrono::minutes{10} + GetRandMillis(std::chrono::minutes{5});
+ scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
+}
+
void PeerLogicValidation::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) {
fUpdateConnectionTime = false;
LOCK(cs_main);
@@ -987,15 +1030,6 @@ void Misbehaving(NodeId pnode, int howmuch, const std::string& message) EXCLUSIV
}
/**
- * Returns true if the given validation state result may result in a peer
- * banning/disconnecting us. We use this to determine which unaccepted
- * transactions from a whitelisted peer that we can safely relay.
- */
-static bool TxRelayMayResultInDisconnect(const TxValidationState& state) {
- return state.GetResult() == TxValidationResult::TX_CONSENSUS;
-}
-
-/**
* Potentially ban a node based on the contents of a BlockValidationState object
*
* @param[in] via_compact_block this bool is passed in because net_processing should
@@ -1064,10 +1098,9 @@ static bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& s
* Potentially ban a node based on the contents of a TxValidationState object
*
* @return Returns true if the peer was punished (probably disconnected)
- *
- * Changes here may need to be reflected in TxRelayMayResultInDisconnect().
*/
-static bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = "") {
+static bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = "")
+{
switch (state.GetResult()) {
case TxValidationResult::TX_RESULT_UNSET:
break;
@@ -1095,11 +1128,6 @@ static bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state,
}
-
-
-
-
-
//////////////////////////////////////////////////////////////////////////////
//
// blockchain -> download logic notification
@@ -1118,8 +1146,11 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT);
}
-PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CScheduler& scheduler)
- : connman(connmanIn), m_banman(banman), m_stale_tip_check_time(0)
+PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CScheduler& scheduler, CTxMemPool& pool)
+ : connman(connmanIn),
+ m_banman(banman),
+ m_mempool(pool),
+ m_stale_tip_check_time(0)
{
// Initialize global variables that cannot be constructed at startup.
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
@@ -1140,14 +1171,18 @@ PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CS
// combine them in one function and schedule at the quicker (peer-eviction)
// timer.
static_assert(EXTRA_PEER_CHECK_INTERVAL < STALE_CHECK_INTERVAL, "peer eviction timer should be less than stale tip check timer");
- scheduler.scheduleEvery(std::bind(&PeerLogicValidation::CheckForStaleTipAndEvictPeers, this, consensusParams), EXTRA_PEER_CHECK_INTERVAL * 1000);
+ scheduler.scheduleEvery([this, consensusParams] { this->CheckForStaleTipAndEvictPeers(consensusParams); }, std::chrono::seconds{EXTRA_PEER_CHECK_INTERVAL});
+
+ // schedule next run for 10-15 minutes in the future
+ const std::chrono::milliseconds delta = std::chrono::minutes{10} + GetRandMillis(std::chrono::minutes{5});
+ scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
}
/**
* Evict orphan txn pool entries (EraseOrphanTx) based on a newly connected
* block. Also save the time of the last tip update.
*/
-void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted)
+void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex)
{
{
LOCK(g_cs_orphans);
@@ -1330,7 +1365,7 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const BlockValidatio
//
-bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+bool static AlreadyHave(const CInv& inv, const CTxMemPool& mempool) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
switch (inv.type)
{
@@ -1378,7 +1413,7 @@ void RelayTransaction(const uint256& txid, const CConnman& connman)
});
}
-static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connman)
+static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman& connman)
{
unsigned int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
@@ -1386,7 +1421,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
// Use deterministic randomness to send to the same nodes for 24 hours
// at a time so the m_addr_knowns of the chosen nodes prevent repeats
uint64_t hashAddr = addr.GetHash();
- const CSipHasher hasher = connman->GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
+ const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24 * 60 * 60));
FastRandomContext insecure_rand;
std::array<std::pair<uint64_t, CNode*>,2> best{{{0, nullptr}, {0, nullptr}}};
@@ -1411,7 +1446,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
}
};
- connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
+ connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
}
void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, const CInv& inv, CConnman* connman)
@@ -1447,7 +1482,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
if (need_activate_chain) {
BlockValidationState state;
if (!ActivateBestChain(state, Params(), a_recent_block)) {
- LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state));
+ LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
}
}
@@ -1569,7 +1604,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
}
}
-void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main)
+void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, CTxMemPool& mempool, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main)
{
AssertLockNotHeld(cs_main);
@@ -1618,7 +1653,13 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
push = true;
}
}
- if (!push) {
+
+ if (push) {
+ // We interpret fulfilling a GETDATA for a transaction as a
+ // successful initial broadcast and remove it from our
+ // unbroadcast set.
+ mempool.RemoveUnbroadcastTx(inv.hash);
+ } else {
vNotFound.push_back(inv);
}
}
@@ -1682,7 +1723,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCKTXN, resp));
}
-bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::vector<CBlockHeader>& headers, const CChainParams& chainparams, bool via_compact_block)
+bool static ProcessHeadersMessage(CNode* pfrom, CConnman* connman, CTxMemPool& mempool, const std::vector<CBlockHeader>& headers, const CChainParams& chainparams, bool via_compact_block)
{
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
size_t nCount = headers.size();
@@ -1810,7 +1851,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
}
uint32_t nFetchFlags = GetFetchFlags(pfrom);
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
- MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), pindex);
+ MarkBlockAsInFlight(mempool, pfrom->GetId(), pindex->GetBlockHash(), pindex);
LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
pindex->GetBlockHash().ToString(), pfrom->GetId());
}
@@ -1864,7 +1905,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
return true;
}
-void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_set, std::list<CTransactionRef>& removed_txn) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
+void static ProcessOrphanTx(CConnman* connman, CTxMemPool& mempool, std::set<uint256>& orphan_work_set, std::list<CTransactionRef>& removed_txn) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
{
AssertLockHeld(cs_main);
AssertLockHeld(g_cs_orphans);
@@ -1924,9 +1965,9 @@ void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_se
}
}
-bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc)
+bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc)
{
- LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
+ LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom->GetId());
if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0)
{
LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
@@ -1935,8 +1976,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!(pfrom->GetLocalServices() & NODE_BLOOM) &&
- (strCommand == NetMsgType::FILTERLOAD ||
- strCommand == NetMsgType::FILTERADD))
+ (msg_type == NetMsgType::FILTERLOAD ||
+ msg_type == NetMsgType::FILTERADD))
{
if (pfrom->nVersion >= NO_BLOOM_VERSION) {
LOCK(cs_main);
@@ -1948,7 +1989,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
}
- if (strCommand == NetMsgType::VERSION) {
+ if (msg_type == NetMsgType::VERSION) {
// Each connection can only send one version message
if (pfrom->nVersion != 0)
{
@@ -2120,7 +2161,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// At this point, the outgoing message serialization version can't change.
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
- if (strCommand == NetMsgType::VERACK)
+ if (msg_type == NetMsgType::VERACK)
{
pfrom->SetRecvVersion(std::min(pfrom->nVersion.load(), PROTOCOL_VERSION));
@@ -2165,7 +2206,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return false;
}
- if (strCommand == NetMsgType::ADDR) {
+ if (msg_type == NetMsgType::ADDR) {
std::vector<CAddress> vAddr;
vRecv >> vAddr;
@@ -2205,7 +2246,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
{
// Relay to a limited number of other nodes
- RelayAddress(addr, fReachable, connman);
+ RelayAddress(addr, fReachable, *connman);
}
// Do not store addresses outside our network
if (fReachable)
@@ -2219,13 +2260,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::SENDHEADERS) {
+ if (msg_type == NetMsgType::SENDHEADERS) {
LOCK(cs_main);
State(pfrom->GetId())->fPreferHeaders = true;
return true;
}
- if (strCommand == NetMsgType::SENDCMPCT) {
+ if (msg_type == NetMsgType::SENDCMPCT) {
bool fAnnounceUsingCMPCTBLOCK = false;
uint64_t nCMPCTBLOCKVersion = 0;
vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
@@ -2248,7 +2289,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::INV) {
+ if (msg_type == NetMsgType::INV) {
std::vector<CInv> vInv;
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ)
@@ -2276,7 +2317,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (interruptMsgProc)
return true;
- bool fAlreadyHave = AlreadyHave(inv);
+ bool fAlreadyHave = AlreadyHave(inv, mempool);
LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->GetId());
if (inv.type == MSG_TX) {
@@ -2310,7 +2351,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::GETDATA) {
+ if (msg_type == NetMsgType::GETDATA) {
std::vector<CInv> vInv;
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ)
@@ -2327,11 +2368,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
- ProcessGetData(pfrom, chainparams, connman, interruptMsgProc);
+ ProcessGetData(pfrom, chainparams, connman, mempool, interruptMsgProc);
return true;
}
- if (strCommand == NetMsgType::GETBLOCKS) {
+ if (msg_type == NetMsgType::GETBLOCKS) {
CBlockLocator locator;
uint256 hashStop;
vRecv >> locator >> hashStop;
@@ -2357,7 +2398,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
BlockValidationState state;
if (!ActivateBestChain(state, Params(), a_recent_block)) {
- LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state));
+ LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
}
}
@@ -2399,7 +2440,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::GETBLOCKTXN) {
+ if (msg_type == NetMsgType::GETBLOCKTXN) {
BlockTransactionsRequest req;
vRecv >> req;
@@ -2448,7 +2489,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::GETHEADERS) {
+ if (msg_type == NetMsgType::GETHEADERS) {
CBlockLocator locator;
uint256 hashStop;
vRecv >> locator >> hashStop;
@@ -2515,7 +2556,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::TX) {
+ if (msg_type == NetMsgType::TX) {
// Stop processing the transaction early if
// We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off
// or if this peer is supposed to be a block-relay-only peer
@@ -2544,7 +2585,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
std::list<CTransactionRef> lRemovedTxn;
- if (!AlreadyHave(inv) &&
+ if (!AlreadyHave(inv, mempool) &&
AcceptToMemoryPool(mempool, state, ptx, &lRemovedTxn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
mempool.check(&::ChainstateActive().CoinsTip());
RelayTransaction(tx.GetHash(), *connman);
@@ -2565,7 +2606,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
mempool.size(), mempool.DynamicMemoryUsage() / 1000);
// Recursively process any orphan transactions that depended on this one
- ProcessOrphanTx(connman, pfrom->orphan_work_set, lRemovedTxn);
+ ProcessOrphanTx(connman, mempool, pfrom->orphan_work_set, lRemovedTxn);
}
else if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS)
{
@@ -2583,7 +2624,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
for (const CTxIn& txin : tx.vin) {
CInv _inv(MSG_TX | nFetchFlags, txin.prevout.hash);
pfrom->AddInventoryKnown(_inv);
- if (!AlreadyHave(_inv)) RequestTx(State(pfrom->GetId()), _inv.hash, current_time);
+ if (!AlreadyHave(_inv, mempool)) RequestTx(State(pfrom->GetId()), _inv.hash, current_time);
}
AddOrphanTx(ptx, pfrom->GetId());
@@ -2615,14 +2656,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (pfrom->HasPermission(PF_FORCERELAY)) {
// Always relay transactions received from whitelisted peers, even
- // if they were already in the mempool or rejected from it due
- // to policy, allowing the node to function as a gateway for
+ // if they were already in the mempool,
+ // allowing the node to function as a gateway for
// nodes hidden behind it.
- //
- // Never relay transactions that might result in being
- // disconnected (or banned).
- if (state.IsInvalid() && TxRelayMayResultInDisconnect(state)) {
- LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->GetId(), FormatStateMessage(state));
+ if (!mempool.exists(tx.GetHash())) {
+ LogPrintf("Not relaying non-mempool transaction %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->GetId());
} else {
LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->GetId());
RelayTransaction(tx.GetHash(), *connman);
@@ -2654,13 +2692,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
{
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
pfrom->GetId(),
- FormatStateMessage(state));
+ state.ToString());
MaybePunishNodeForTx(pfrom->GetId(), state);
}
return true;
}
- if (strCommand == NetMsgType::CMPCTBLOCK)
+ if (msg_type == NetMsgType::CMPCTBLOCK)
{
// Ignore cmpctblock received while importing
if (fImporting || fReindex) {
@@ -2761,7 +2799,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if ((!fAlreadyInFlight && nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) ||
(fAlreadyInFlight && blockInFlightIt->second.first == pfrom->GetId())) {
std::list<QueuedBlock>::iterator* queuedBlockIt = nullptr;
- if (!MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), pindex, &queuedBlockIt)) {
+ if (!MarkBlockAsInFlight(mempool, pfrom->GetId(), pindex->GetBlockHash(), pindex, &queuedBlockIt)) {
if (!(*queuedBlockIt)->partialBlock)
(*queuedBlockIt)->partialBlock.reset(new PartiallyDownloadedBlock(&mempool));
else {
@@ -2834,7 +2872,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
} // cs_main
if (fProcessBLOCKTXN)
- return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, connman, banman, interruptMsgProc);
+ return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, mempool, connman, banman, interruptMsgProc);
if (fRevertToHeaderProcessing) {
// Headers received from HB compact block peers are permitted to be
@@ -2842,7 +2880,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// the peer if the header turns out to be for an invalid block.
// Note that if a peer tries to build on an invalid chain, that
// will be detected and the peer will be banned.
- return ProcessHeadersMessage(pfrom, connman, {cmpctblock.header}, chainparams, /*via_compact_block=*/true);
+ return ProcessHeadersMessage(pfrom, connman, mempool, {cmpctblock.header}, chainparams, /*via_compact_block=*/true);
}
if (fBlockReconstructed) {
@@ -2881,7 +2919,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::BLOCKTXN)
+ if (msg_type == NetMsgType::BLOCKTXN)
{
// Ignore blocktxn received while importing
if (fImporting || fReindex) {
@@ -2963,7 +3001,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::HEADERS)
+ if (msg_type == NetMsgType::HEADERS)
{
// Ignore headers received while importing
if (fImporting || fReindex) {
@@ -2986,10 +3024,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
}
- return ProcessHeadersMessage(pfrom, connman, headers, chainparams, /*via_compact_block=*/false);
+ return ProcessHeadersMessage(pfrom, connman, mempool, headers, chainparams, /*via_compact_block=*/false);
}
- if (strCommand == NetMsgType::BLOCK)
+ if (msg_type == NetMsgType::BLOCK)
{
// Ignore block received while importing
if (fImporting || fReindex) {
@@ -3025,7 +3063,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::GETADDR) {
+ if (msg_type == NetMsgType::GETADDR) {
// This asymmetric behavior for inbound and outbound connections was introduced
// to prevent a fingerprinting attack: an attacker can send specific fake addresses
// to users' AddrMan and later request them by sending getaddr messages.
@@ -3059,7 +3097,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::MEMPOOL) {
+ if (msg_type == NetMsgType::MEMPOOL) {
if (!(pfrom->GetLocalServices() & NODE_BLOOM) && !pfrom->HasPermission(PF_MEMPOOL))
{
if (!pfrom->HasPermission(PF_NOBAN))
@@ -3087,7 +3125,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::PING) {
+ if (msg_type == NetMsgType::PING) {
if (pfrom->nVersion > BIP0031_VERSION)
{
uint64_t nonce = 0;
@@ -3108,7 +3146,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::PONG) {
+ if (msg_type == NetMsgType::PONG) {
int64_t pingUsecEnd = nTimeReceived;
uint64_t nonce = 0;
size_t nAvail = vRecv.in_avail();
@@ -3164,7 +3202,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::FILTERLOAD) {
+ if (msg_type == NetMsgType::FILTERLOAD) {
CBloomFilter filter;
vRecv >> filter;
@@ -3184,7 +3222,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::FILTERADD) {
+ if (msg_type == NetMsgType::FILTERADD) {
std::vector<unsigned char> vData;
vRecv >> vData;
@@ -3208,19 +3246,19 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::FILTERCLEAR) {
+ if (msg_type == NetMsgType::FILTERCLEAR) {
if (pfrom->m_tx_relay == nullptr) {
return true;
}
LOCK(pfrom->m_tx_relay->cs_filter);
if (pfrom->GetLocalServices() & NODE_BLOOM) {
- pfrom->m_tx_relay->pfilter.reset(new CBloomFilter());
+ pfrom->m_tx_relay->pfilter = nullptr;
}
pfrom->m_tx_relay->fRelayTxes = true;
return true;
}
- if (strCommand == NetMsgType::FEEFILTER) {
+ if (msg_type == NetMsgType::FEEFILTER) {
CAmount newFeeFilter = 0;
vRecv >> newFeeFilter;
if (MoneyRange(newFeeFilter)) {
@@ -3233,7 +3271,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (strCommand == NetMsgType::NOTFOUND) {
+ if (msg_type == NetMsgType::NOTFOUND) {
// Remove the NOTFOUND transactions from the peer
LOCK(cs_main);
CNodeState *state = State(pfrom->GetId());
@@ -3259,7 +3297,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
// Ignore unknown commands for extensibility
- LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId());
+ LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(msg_type), pfrom->GetId());
return true;
}
@@ -3304,12 +3342,12 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
bool fMoreWork = false;
if (!pfrom->vRecvGetData.empty())
- ProcessGetData(pfrom, chainparams, connman, interruptMsgProc);
+ ProcessGetData(pfrom, chainparams, connman, m_mempool, interruptMsgProc);
if (!pfrom->orphan_work_set.empty()) {
std::list<CTransactionRef> removed_txn;
LOCK2(cs_main, g_cs_orphans);
- ProcessOrphanTx(connman, pfrom->orphan_work_set, removed_txn);
+ ProcessOrphanTx(connman, m_mempool, pfrom->orphan_work_set, removed_txn);
for (const CTransactionRef& removedTx : removed_txn) {
AddToCompactExtraTransactions(removedTx);
}
@@ -3354,7 +3392,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
LogPrint(BCLog::NET, "PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(msg.m_command), pfrom->GetId());
return fMoreWork;
}
- const std::string& strCommand = msg.m_command;
+ const std::string& msg_type = msg.m_command;
// Message size
unsigned int nMessageSize = msg.m_message_size;
@@ -3364,7 +3402,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
if (!msg.m_valid_checksum)
{
LogPrint(BCLog::NET, "%s(%s, %u bytes): CHECKSUM ERROR peer=%d\n", __func__,
- SanitizeString(strCommand), nMessageSize, pfrom->GetId());
+ SanitizeString(msg_type), nMessageSize, pfrom->GetId());
return fMoreWork;
}
@@ -3372,19 +3410,19 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
bool fRet = false;
try
{
- fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.m_time, chainparams, connman, m_banman, interruptMsgProc);
+ fRet = ProcessMessage(pfrom, msg_type, vRecv, msg.m_time, chainparams, m_mempool, connman, m_banman, interruptMsgProc);
if (interruptMsgProc)
return false;
if (!pfrom->vRecvGetData.empty())
fMoreWork = true;
} catch (const std::exception& e) {
- LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' (%s) caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what(), typeid(e).name());
+ LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' (%s) caught\n", __func__, SanitizeString(msg_type), nMessageSize, e.what(), typeid(e).name());
} catch (...) {
- LogPrint(BCLog::NET, "%s(%s, %u bytes): Unknown exception caught\n", __func__, SanitizeString(strCommand), nMessageSize);
+ LogPrint(BCLog::NET, "%s(%s, %u bytes): Unknown exception caught\n", __func__, SanitizeString(msg_type), nMessageSize);
}
if (!fRet) {
- LogPrint(BCLog::NET, "%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->GetId());
+ LogPrint(BCLog::NET, "%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(msg_type), nMessageSize, pfrom->GetId());
}
LOCK(cs_main);
@@ -3599,16 +3637,16 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
int64_t nNow = GetTimeMicros();
auto current_time = GetTime<std::chrono::microseconds>();
- if (pto->IsAddrRelayPeer() && !::ChainstateActive().IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
+ if (pto->IsAddrRelayPeer() && !::ChainstateActive().IsInitialBlockDownload() && pto->m_next_local_addr_send < current_time) {
AdvertiseLocal(pto);
- pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
+ pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}
//
// Message: addr
//
- if (pto->IsAddrRelayPeer() && pto->nNextAddrSend < nNow) {
- pto->nNextAddrSend = PoissonNextSend(nNow, AVG_ADDRESS_BROADCAST_INTERVAL);
+ if (pto->IsAddrRelayPeer() && pto->m_next_addr_send < current_time) {
+ pto->m_next_addr_send = PoissonNextSend(current_time, AVG_ADDRESS_BROADCAST_INTERVAL);
std::vector<CAddress> vAddr;
vAddr.reserve(pto->vAddrToSend.size());
assert(pto->m_addr_known);
@@ -3838,7 +3876,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
// Respond to BIP35 mempool requests
if (fSendTrickle && pto->m_tx_relay->fSendMempool) {
- auto vtxinfo = mempool.infoAll();
+ auto vtxinfo = m_mempool.infoAll();
pto->m_tx_relay->fSendMempool = false;
CFeeRate filterrate;
{
@@ -3884,7 +3922,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
}
// Topologically and fee-rate sort the inventory we send for privacy and priority reasons.
// A heap is used so that not all items need sorting if only a few are being sent.
- CompareInvMempoolOrder compareInvMempoolOrder(&mempool);
+ CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
// No reason to drain out at many times the network's capacity,
// especially since we have many peers and some will draw much shorter delays.
@@ -3903,7 +3941,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
continue;
}
// Not in the mempool anymore? don't bother sending it.
- auto txinfo = mempool.info(hash);
+ auto txinfo = m_mempool.info(hash);
if (!txinfo.tx) {
continue;
}
@@ -4015,7 +4053,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
for (const CBlockIndex *pindex : vToDownload) {
uint32_t nFetchFlags = GetFetchFlags(pto);
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
- MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), pindex);
+ MarkBlockAsInFlight(m_mempool, pto->GetId(), pindex->GetBlockHash(), pindex);
LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
pindex->nHeight, pto->GetId());
}
@@ -4058,7 +4096,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
// processing at a later time, see below)
tx_process_time.erase(tx_process_time.begin());
CInv inv(MSG_TX | GetFetchFlags(pto), txid);
- if (!AlreadyHave(inv)) {
+ if (!AlreadyHave(inv, m_mempool)) {
// If this transaction was last requested more than 1 minute ago,
// then request.
const auto last_request_time = GetTxRequestTime(inv.hash);
@@ -4096,7 +4134,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
// We don't want white listed peers to filter txs to us if we have -whitelistforcerelay
if (pto->m_tx_relay != nullptr && pto->nVersion >= FEEFILTER_VERSION && gArgs.GetBoolArg("-feefilter", DEFAULT_FEEFILTER) &&
!pto->HasPermission(PF_FORCERELAY)) {
- CAmount currentFilter = mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
+ CAmount currentFilter = m_mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
int64_t timeNow = GetTimeMicros();
if (timeNow > pto->m_tx_relay->nextSendTimeFeeFilter) {
static CFeeRate default_feerate(DEFAULT_MIN_RELAY_TX_FEE);
diff --git a/src/net_processing.h b/src/net_processing.h
index 6f26abc209..a85d5e7c70 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -6,12 +6,15 @@
#ifndef BITCOIN_NET_PROCESSING_H
#define BITCOIN_NET_PROCESSING_H
-#include <net.h>
-#include <validationinterface.h>
#include <consensus/params.h>
+#include <net.h>
#include <sync.h>
+#include <validationinterface.h>
+
+class CTxMemPool;
extern RecursiveMutex cs_main;
+extern RecursiveMutex g_cs_orphans;
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
@@ -23,16 +26,17 @@ class PeerLogicValidation final : public CValidationInterface, public NetEventsI
private:
CConnman* const connman;
BanMan* const m_banman;
+ CTxMemPool& m_mempool;
bool CheckIfBanned(CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
public:
- PeerLogicValidation(CConnman* connman, BanMan* banman, CScheduler& scheduler);
+ PeerLogicValidation(CConnman* connman, BanMan* banman, CScheduler& scheduler, CTxMemPool& pool);
/**
* Overridden from CValidationInterface.
*/
- void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted) override;
+ void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override;
void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex) override;
/**
* Overridden from CValidationInterface.
@@ -72,6 +76,8 @@ public:
void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams);
/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */
void EvictExtraOutboundPeers(int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ /** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */
+ void ReattemptInitialBroadcast(CScheduler& scheduler) const;
private:
int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index ce3e17197e..6adb171abd 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -210,6 +210,11 @@ bool CNetAddr::IsRFC7343() const
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x20);
}
+bool CNetAddr::IsHeNet() const
+{
+ return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70);
+}
+
/**
* @returns Whether or not this is a dummy address that maps an onion address
* into IPv6.
@@ -401,6 +406,26 @@ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
return true;
}
+bool CNetAddr::HasLinkedIPv4() const
+{
+ return IsRoutable() && (IsIPv4() || IsRFC6145() || IsRFC6052() || IsRFC3964() || IsRFC4380());
+}
+
+uint32_t CNetAddr::GetLinkedIPv4() const
+{
+ if (IsIPv4() || IsRFC6145() || IsRFC6052()) {
+ // IPv4, mapped IPv4, SIIT translated IPv4: the IPv4 address is the last 4 bytes of the address
+ return ReadBE32(ip + 12);
+ } else if (IsRFC3964()) {
+ // 6to4 tunneled IPv4: the IPv4 address is in bytes 2-6
+ return ReadBE32(ip + 2);
+ } else if (IsRFC4380()) {
+ // Teredo tunneled IPv4: the IPv4 address is in the last 4 bytes of the address, but bitflipped
+ return ~ReadBE32(ip + 12);
+ }
+ assert(false);
+}
+
uint32_t CNetAddr::GetNetClass() const {
uint32_t net_class = NET_IPV6;
if (IsLocal()) {
@@ -410,7 +435,7 @@ uint32_t CNetAddr::GetNetClass() const {
net_class = NET_INTERNAL;
} else if (!IsRoutable()) {
net_class = NET_UNROUTABLE;
- } else if (IsIPv4() || IsRFC6145() || IsRFC6052() || IsRFC3964() || IsRFC4380()) {
+ } else if (HasLinkedIPv4()) {
net_class = NET_IPV4;
} else if (IsTor()) {
net_class = NET_ONION;
@@ -424,10 +449,24 @@ uint32_t CNetAddr::GetMappedAS(const std::vector<bool> &asmap) const {
return 0; // Indicates not found, safe because AS0 is reserved per RFC7607.
}
std::vector<bool> ip_bits(128);
- for (int8_t byte_i = 0; byte_i < 16; ++byte_i) {
- uint8_t cur_byte = GetByte(15 - byte_i);
- for (uint8_t bit_i = 0; bit_i < 8; ++bit_i) {
- ip_bits[byte_i * 8 + bit_i] = (cur_byte >> (7 - bit_i)) & 1;
+ if (HasLinkedIPv4()) {
+ // For lookup, treat as if it was just an IPv4 address (pchIPv4 prefix + IPv4 bits)
+ for (int8_t byte_i = 0; byte_i < 12; ++byte_i) {
+ for (uint8_t bit_i = 0; bit_i < 8; ++bit_i) {
+ ip_bits[byte_i * 8 + bit_i] = (pchIPv4[byte_i] >> (7 - bit_i)) & 1;
+ }
+ }
+ uint32_t ipv4 = GetLinkedIPv4();
+ for (int i = 0; i < 32; ++i) {
+ ip_bits[96 + i] = (ipv4 >> (31 - i)) & 1;
+ }
+ } else {
+ // Use all 128 bits of the IPv6 address otherwise
+ for (int8_t byte_i = 0; byte_i < 16; ++byte_i) {
+ uint8_t cur_byte = GetByte(15 - byte_i);
+ for (uint8_t bit_i = 0; bit_i < 8; ++bit_i) {
+ ip_bits[byte_i * 8 + bit_i] = (cur_byte >> (7 - bit_i)) & 1;
+ }
}
}
uint32_t mapped_as = Interpret(asmap, ip_bits);
@@ -463,51 +502,32 @@ std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) co
int nStartByte = 0;
int nBits = 16;
- // all local addresses belong to the same group
- if (IsLocal())
- {
+ if (IsLocal()) {
+ // all local addresses belong to the same group
nBits = 0;
- }
- // all internal-usage addresses get their own group
- if (IsInternal())
- {
+ } else if (IsInternal()) {
+ // all internal-usage addresses get their own group
nStartByte = sizeof(g_internal_prefix);
nBits = (sizeof(ip) - sizeof(g_internal_prefix)) * 8;
- }
- // all other unroutable addresses belong to the same group
- else if (!IsRoutable())
- {
+ } else if (!IsRoutable()) {
+ // all other unroutable addresses belong to the same group
nBits = 0;
- }
- // for IPv4 addresses, '1' + the 16 higher-order bits of the IP
- // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
- else if (IsIPv4() || IsRFC6145() || IsRFC6052())
- {
- nStartByte = 12;
- }
- // for 6to4 tunnelled addresses, use the encapsulated IPv4 address
- else if (IsRFC3964())
- {
- nStartByte = 2;
- }
- // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
- else if (IsRFC4380())
- {
- vchRet.push_back(GetByte(3) ^ 0xFF);
- vchRet.push_back(GetByte(2) ^ 0xFF);
+ } else if (HasLinkedIPv4()) {
+ // IPv4 addresses (and mapped IPv4 addresses) use /16 groups
+ uint32_t ipv4 = GetLinkedIPv4();
+ vchRet.push_back((ipv4 >> 24) & 0xFF);
+ vchRet.push_back((ipv4 >> 16) & 0xFF);
return vchRet;
- }
- else if (IsTor())
- {
+ } else if (IsTor()) {
nStartByte = 6;
nBits = 4;
- }
- // for he.net, use /36 groups
- else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
+ } else if (IsHeNet()) {
+ // for he.net, use /36 groups
nBits = 36;
- // for the rest of the IPv6 network, use /32 groups
- else
+ } else {
+ // for the rest of the IPv6 network, use /32 groups
nBits = 32;
+ }
// push our ip onto vchRet byte by byte...
while (nBits >= 8)
diff --git a/src/netaddress.h b/src/netaddress.h
index 078234595c..d0ab770379 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -39,14 +39,12 @@ class CNetAddr
explicit CNetAddr(const struct in_addr& ipv4Addr);
void SetIP(const CNetAddr& ip);
- private:
/**
* Set raw IPv4 or IPv6 address (in network byte order)
* @note Only NET_IPV4 and NET_IPV6 are allowed for network.
*/
void SetRaw(Network network, const uint8_t *data);
- public:
bool SetInternal(const std::string& name);
bool SetSpecial(const std::string &strName); // for Tor addresses
@@ -67,6 +65,7 @@ class CNetAddr
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
bool IsRFC6052() const; // IPv6 well-known prefix for IPv4-embedded address (64:FF9B::/96)
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in RFC2765)
+ bool IsHeNet() const; // IPv6 Hurricane Electric - https://he.net (2001:0470::/36)
bool IsTor() const;
bool IsLocal() const;
bool IsRoutable() const;
@@ -80,6 +79,11 @@ class CNetAddr
bool GetInAddr(struct in_addr* pipv4Addr) const;
uint32_t GetNetClass() const;
+ //! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled addresses, return the relevant IPv4 address as a uint32.
+ uint32_t GetLinkedIPv4() const;
+ //! Whether this address has a linked IPv4 address (see GetLinkedIPv4()).
+ bool HasLinkedIPv4() const;
+
// The AS on the BGP path to the node we use to diversify
// peers in AddrMan bucketing based on the AS infrastructure.
// The ip->AS mapping depends on how asmap is constructed.
diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp
index a818f06d51..ec52a08ace 100644
--- a/src/node/coinstats.cpp
+++ b/src/node/coinstats.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -23,7 +23,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash,
for (const auto& output : outputs) {
ss << VARINT(output.first + 1);
ss << output.second.out.scriptPubKey;
- ss << VARINT(output.second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
+ ss << VARINT_MODE(output.second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
stats.nTransactionOutputs++;
stats.nTotalAmount += output.second.out.nValue;
stats.nBogoSize += 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ + 8 /* amount */ +
diff --git a/src/node/context.cpp b/src/node/context.cpp
index 26a01420c8..0238aab0d9 100644
--- a/src/node/context.cpp
+++ b/src/node/context.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -8,6 +8,7 @@
#include <interfaces/chain.h>
#include <net.h>
#include <net_processing.h>
+#include <scheduler.h>
NodeContext::NodeContext() {}
NodeContext::~NodeContext() {}
diff --git a/src/node/context.h b/src/node/context.h
index dab5b5d048..566ff170be 100644
--- a/src/node/context.h
+++ b/src/node/context.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -8,8 +8,10 @@
#include <memory>
#include <vector>
+class ArgsManager;
class BanMan;
class CConnman;
+class CScheduler;
class CTxMemPool;
class PeerLogicValidation;
namespace interfaces {
@@ -32,8 +34,10 @@ struct NodeContext {
CTxMemPool* mempool{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
std::unique_ptr<PeerLogicValidation> peer_logic;
std::unique_ptr<BanMan> banman;
+ ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
std::unique_ptr<interfaces::Chain> chain;
std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
+ std::unique_ptr<CScheduler> scheduler;
//! Declare default constructor and destructor that are not inline, so code
//! instantiating the NodeContext struct doesn't need to #include class
diff --git a/src/node/psbt.cpp b/src/node/psbt.cpp
index 8678b33cf3..c189018268 100644
--- a/src/node/psbt.cpp
+++ b/src/node/psbt.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -18,9 +18,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
PSBTAnalysis result;
bool calc_fee = true;
- bool all_final = true;
- bool only_missing_sigs = true;
- bool only_missing_final = false;
+
CAmount in_amt = 0;
result.inputs.resize(psbtx.tx->vin.size());
@@ -29,6 +27,9 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
PSBTInput& input = psbtx.inputs[i];
PSBTInputAnalysis& input_analysis = result.inputs[i];
+ // We set next role here and ratchet backwards as required
+ input_analysis.next = PSBTRole::EXTRACTOR;
+
// Check for a UTXO
CTxOut utxo;
if (psbtx.GetInputUTXO(utxo, i)) {
@@ -57,7 +58,6 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
// Check if it is final
if (!utxo.IsNull() && !PSBTInputSigned(input)) {
input_analysis.is_final = false;
- all_final = false;
// Figure out what is missing
SignatureData outdata;
@@ -74,11 +74,9 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
if (outdata.missing_pubkeys.empty() && outdata.missing_redeem_script.IsNull() && outdata.missing_witness_script.IsNull() && !outdata.missing_sigs.empty()) {
input_analysis.next = PSBTRole::SIGNER;
} else {
- only_missing_sigs = false;
input_analysis.next = PSBTRole::UPDATER;
}
} else {
- only_missing_final = true;
input_analysis.next = PSBTRole::FINALIZER;
}
} else if (!utxo.IsNull()){
@@ -86,10 +84,14 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
}
}
- if (all_final) {
- only_missing_sigs = false;
- result.next = PSBTRole::EXTRACTOR;
+ // Calculate next role for PSBT by grabbing "minimum" PSBTInput next role
+ result.next = PSBTRole::EXTRACTOR;
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ PSBTInputAnalysis& input_analysis = result.inputs[i];
+ result.next = std::min(result.next, input_analysis.next);
}
+ assert(result.next > PSBTRole::CREATOR);
+
if (calc_fee) {
// Get the output amount
CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmount(0),
@@ -139,17 +141,6 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
result.estimated_feerate = feerate;
}
- if (only_missing_sigs) {
- result.next = PSBTRole::SIGNER;
- } else if (only_missing_final) {
- result.next = PSBTRole::FINALIZER;
- } else if (all_final) {
- result.next = PSBTRole::EXTRACTOR;
- } else {
- result.next = PSBTRole::UPDATER;
- }
- } else {
- result.next = PSBTRole::UPDATER;
}
return result;
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index 1bb9b88d00..3841d8687d 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -7,7 +7,6 @@
#include <net.h>
#include <net_processing.h>
#include <node/context.h>
-#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
#include <node/transaction.h>
@@ -41,7 +40,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
TxValidationState state;
if (!AcceptToMemoryPool(*node.mempool, state, std::move(tx),
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_tx_fee)) {
- err_string = FormatStateMessage(state);
+ err_string = state.ToString();
if (state.IsInvalid()) {
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
return TransactionError::MISSING_INPUTS;
@@ -79,6 +78,10 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
}
if (relay) {
+ // the mempool tracks locally submitted transactions to make a
+ // best-effort of initial broadcast
+ node.mempool->AddUnbroadcastTx(hashTx);
+
RelayTransaction(hashTx, *node.connman);
}
diff --git a/src/node/transaction.h b/src/node/transaction.h
index a85dfb8ace..6491700d44 100644
--- a/src/node/transaction.h
+++ b/src/node/transaction.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -6,11 +6,19 @@
#define BITCOIN_NODE_TRANSACTION_H
#include <attributes.h>
+#include <policy/feerate.h>
#include <primitives/transaction.h>
#include <util/error.h>
struct NodeContext;
+/** Maximum fee rate for sendrawtransaction and testmempoolaccept RPC calls.
+ * Also used by the GUI when broadcasting a completed PSBT.
+ * By default, a transaction with a fee rate higher than this will be rejected
+ * by these RPCs and the GUI. This can be overridden with the maxfeerate argument.
+ */
+static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE{COIN / 10};
+
/**
* Submit a transaction to the mempool and (optionally) relay it to all P2P peers.
*
diff --git a/src/outputtype.cpp b/src/outputtype.cpp
index 567eecb5c9..ea7a86d6d6 100644
--- a/src/outputtype.cpp
+++ b/src/outputtype.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -82,30 +82,22 @@ CTxDestination AddAndGetDestinationForScript(FillableSigningProvider& keystore,
{
// Add script to keystore
keystore.AddCScript(script);
- ScriptHash sh(script);
// Note that scripts over 520 bytes are not yet supported.
switch (type) {
case OutputType::LEGACY:
- keystore.AddCScript(GetScriptForDestination(sh));
- return sh;
+ return ScriptHash(script);
case OutputType::P2SH_SEGWIT:
case OutputType::BECH32: {
CTxDestination witdest = WitnessV0ScriptHash(script);
CScript witprog = GetScriptForDestination(witdest);
// Check if the resulting program is solvable (i.e. doesn't use an uncompressed key)
- if (!IsSolvable(keystore, witprog)) {
- // Since the wsh is invalid, add and return the sh instead.
- keystore.AddCScript(GetScriptForDestination(sh));
- return sh;
- }
+ if (!IsSolvable(keystore, witprog)) return ScriptHash(script);
// Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours.
keystore.AddCScript(witprog);
if (type == OutputType::BECH32) {
return witdest;
} else {
- ScriptHash sh_w = ScriptHash(witprog);
- keystore.AddCScript(GetScriptForDestination(sh_w));
- return sh_w;
+ return ScriptHash(witprog);
}
}
default: assert(false);
diff --git a/src/prevector.h b/src/prevector.h
index f4ece738a8..9f2f7ba2de 100644
--- a/src/prevector.h
+++ b/src/prevector.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -15,7 +15,6 @@
#include <type_traits>
#include <utility>
-#pragma pack(push, 1)
/** Implements a drop-in replacement for std::vector<T> which stores up to N
* elements directly (without heap allocation). The types Size and Diff are
* used to store element counts, and can be any unsigned + signed type.
@@ -147,14 +146,20 @@ public:
};
private:
- size_type _size = 0;
+#pragma pack(push, 1)
union direct_or_indirect {
char direct[sizeof(T) * N];
struct {
- size_type capacity;
char* indirect;
+ size_type capacity;
};
- } _union = {};
+ };
+#pragma pack(pop)
+ alignas(char*) direct_or_indirect _union = {};
+ size_type _size = 0;
+
+ static_assert(alignof(char*) % alignof(size_type) == 0 && sizeof(char*) % alignof(size_type) == 0, "size_type cannot have more restrictive alignment requirement than pointer");
+ static_assert(alignof(char*) % alignof(T) == 0, "value_type T cannot have more restrictive alignment requirement than pointer");
T* direct_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.direct) + pos; }
const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
@@ -419,15 +424,20 @@ public:
return first;
}
- void push_back(const T& value) {
+ template<typename... Args>
+ void emplace_back(Args&&... args) {
size_type new_size = size() + 1;
if (capacity() < new_size) {
change_capacity(new_size + (new_size >> 1));
}
- new(item_ptr(size())) T(value);
+ new(item_ptr(size())) T(std::forward<Args>(args)...);
_size++;
}
+ void push_back(const T& value) {
+ emplace_back(value);
+ }
+
void pop_back() {
erase(end() - 1, end());
}
@@ -523,6 +533,5 @@ public:
return item_ptr(0);
}
};
-#pragma pack(pop)
#endif // BITCOIN_PREVECTOR_H
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 28c145f71d..e6183cf2f4 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -9,6 +9,8 @@
#include <tinyformat.h>
#include <util/strencodings.h>
+#include <assert.h>
+
std::string COutPoint::ToString() const
{
return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n);
@@ -84,10 +86,11 @@ CAmount CTransaction::GetValueOut() const
{
CAmount nValueOut = 0;
for (const auto& tx_out : vout) {
- nValueOut += tx_out.nValue;
- if (!MoneyRange(tx_out.nValue) || !MoneyRange(nValueOut))
+ if (!MoneyRange(tx_out.nValue) || !MoneyRange(nValueOut + tx_out.nValue))
throw std::runtime_error(std::string(__func__) + ": value out of range");
+ nValueOut += tx_out.nValue;
}
+ assert(MoneyRange(nValueOut));
return nValueOut;
}
diff --git a/src/protocol.cpp b/src/protocol.cpp
index e49e5523ac..a3e844e35b 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -85,8 +85,13 @@ CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
{
memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
- memset(pchCommand, 0, sizeof(pchCommand));
- strncpy(pchCommand, pszCommand, COMMAND_SIZE);
+
+ // Copy the command name, zero-padding to COMMAND_SIZE bytes
+ size_t i = 0;
+ for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];
+ assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE
+ for (; i < COMMAND_SIZE; ++i) pchCommand[i] = 0;
+
nMessageSize = nMessageSizeIn;
memset(pchChecksum, 0, CHECKSUM_SIZE);
}
diff --git a/src/protocol.h b/src/protocol.h
index db07efb9f9..6639ae2aac 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -37,6 +37,10 @@ public:
typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
explicit CMessageHeader(const MessageStartChars& pchMessageStartIn);
+
+ /** Construct a P2P message header from message-start characters, a command and the size of the message.
+ * @note Passing in a `pszCommand` longer than COMMAND_SIZE will result in a run-time assertion error.
+ */
CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn);
std::string GetCommand() const;
diff --git a/src/psbt.cpp b/src/psbt.cpp
index e6b6285652..ef9781817a 100644
--- a/src/psbt.cpp
+++ b/src/psbt.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
diff --git a/src/psbt.h b/src/psbt.h
index dfba261961..af57994f3a 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -40,6 +40,10 @@ static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
// as a 0 length key which indicates that this is the separator. The separator has no value.
static constexpr uint8_t PSBT_SEPARATOR = 0x00;
+// BIP 174 does not specify a maximum file size, but we set a limit anyway
+// to prevent reading a stream indefinately and running out of memory.
+const std::streamsize MAX_FILE_SIZE_PSBT = 100000000; // 100 MiB
+
/** A structure for PSBTs which contain per-input information */
struct PSBTInput
{
diff --git a/src/pubkey.h b/src/pubkey.h
index 2fc92c9bc6..261842b7f7 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -219,6 +219,11 @@ struct CExtPubKey {
a.pubkey == b.pubkey;
}
+ friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
+ {
+ return !(a == b);
+ }
+
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtPubKey& out, unsigned int nChild) const;
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 3ac98a5970..8110f4e895 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -55,7 +55,7 @@ struct AddressTableEntryLessThan
static AddressTableEntry::Type translateTransactionType(const QString &strPurpose, bool isMine)
{
AddressTableEntry::Type addressType = AddressTableEntry::Hidden;
- // "refund" addresses aren't shown, and change addresses aren't in mapAddressBook at all.
+ // "refund" addresses aren't shown, and change addresses aren't returned by getAddresses at all.
if (strPurpose == "send")
addressType = AddressTableEntry::Sending;
else if (strPurpose == "receive")
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 72f16bb09f..2739b21a9d 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h
index f01c506a1e..88d5b5811b 100644
--- a/src/qt/bantablemodel.h
+++ b/src/qt/bantablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 4313d6ee7f..8939b566f7 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -336,7 +336,7 @@ void BitcoinApplication::initializeResult(bool success)
window->setClientModel(clientModel);
#ifdef ENABLE_WALLET
if (WalletModel::isWalletEnabled()) {
- m_wallet_controller = new WalletController(m_node, platformStyle, optionsModel, this);
+ m_wallet_controller = new WalletController(*clientModel, platformStyle, this);
window->setWalletController(m_wallet_controller);
if (paymentServer) {
paymentServer->setOptionsModel(optionsModel);
@@ -381,7 +381,7 @@ void BitcoinApplication::shutdownResult()
void BitcoinApplication::handleRunawayException(const QString &message)
{
- QMessageBox::critical(nullptr, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + message);
+ QMessageBox::critical(nullptr, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. %1 can no longer continue safely and will quit.").arg(PACKAGE_NAME) + QString("\n\n") + message);
::exit(EXIT_FAILURE);
}
diff --git a/src/qt/bitcoin_locale.qrc b/src/qt/bitcoin_locale.qrc
index c781072e9b..a35ca15d62 100644
--- a/src/qt/bitcoin_locale.qrc
+++ b/src/qt/bitcoin_locale.qrc
@@ -1,48 +1,40 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/translations">
+ <file alias="af">locale/bitcoin_af.qm</file>
+ <file alias="am">locale/bitcoin_am.qm</file>
<file alias="ar">locale/bitcoin_ar.qm</file>
- <file alias="be_BY">locale/bitcoin_be_BY.qm</file>
+ <file alias="be">locale/bitcoin_be.qm</file>
+ <file alias="bg">locale/bitcoin_bg.qm</file>
+ <file alias="bn">locale/bitcoin_bn.qm</file>
+ <file alias="bs">locale/bitcoin_bs.qm</file>
<file alias="ca">locale/bitcoin_ca.qm</file>
<file alias="cs">locale/bitcoin_cs.qm</file>
- <file alias="cs_CZ">locale/bitcoin_cs_CZ.qm</file>
<file alias="cy">locale/bitcoin_cy.qm</file>
<file alias="da">locale/bitcoin_da.qm</file>
<file alias="de">locale/bitcoin_de.qm</file>
- <file alias="de_DE">locale/bitcoin_de_DE.qm</file>
<file alias="el">locale/bitcoin_el.qm</file>
- <file alias="el_GR">locale/bitcoin_el_GR.qm</file>
<file alias="en">locale/bitcoin_en.qm</file>
- <file alias="en_AU">locale/bitcoin_en_AU.qm</file>
<file alias="en_GB">locale/bitcoin_en_GB.qm</file>
<file alias="eo">locale/bitcoin_eo.qm</file>
<file alias="es">locale/bitcoin_es.qm</file>
<file alias="es_CL">locale/bitcoin_es_CL.qm</file>
<file alias="es_CO">locale/bitcoin_es_CO.qm</file>
<file alias="es_DO">locale/bitcoin_es_DO.qm</file>
- <file alias="es_ES">locale/bitcoin_es_ES.qm</file>
<file alias="es_MX">locale/bitcoin_es_MX.qm</file>
<file alias="es_VE">locale/bitcoin_es_VE.qm</file>
<file alias="et">locale/bitcoin_et.qm</file>
- <file alias="et_EE">locale/bitcoin_et_EE.qm</file>
<file alias="eu">locale/bitcoin_eu.qm</file>
<file alias="fa">locale/bitcoin_fa.qm</file>
<file alias="fi">locale/bitcoin_fi.qm</file>
<file alias="fil">locale/bitcoin_fil.qm</file>
<file alias="fr">locale/bitcoin_fr.qm</file>
- <file alias="fr_CA">locale/bitcoin_fr_CA.qm</file>
- <file alias="fr_FR">locale/bitcoin_fr_FR.qm</file>
- <file alias="gl">locale/bitcoin_gl.qm</file>
<file alias="he">locale/bitcoin_he.qm</file>
- <file alias="he_IL">locale/bitcoin_he_IL.qm</file>
<file alias="hi">locale/bitcoin_hi.qm</file>
<file alias="hr">locale/bitcoin_hr.qm</file>
<file alias="hu">locale/bitcoin_hu.qm</file>
- <file alias="hu_HU">locale/bitcoin_hu_HU.qm</file>
<file alias="id">locale/bitcoin_id.qm</file>
- <file alias="id_ID">locale/bitcoin_id_ID.qm</file>
<file alias="is">locale/bitcoin_is.qm</file>
<file alias="it">locale/bitcoin_it.qm</file>
- <file alias="it_IT">locale/bitcoin_it_IT.qm</file>
<file alias="ja">locale/bitcoin_ja.qm</file>
<file alias="ka">locale/bitcoin_ka.qm</file>
<file alias="kk">locale/bitcoin_kk.qm</file>
@@ -53,32 +45,26 @@
<file alias="la">locale/bitcoin_la.qm</file>
<file alias="lt">locale/bitcoin_lt.qm</file>
<file alias="lv">locale/bitcoin_lv.qm</file>
- <file alias="lv_LV">locale/bitcoin_lv_LV.qm</file>
<file alias="mk">locale/bitcoin_mk.qm</file>
<file alias="ml">locale/bitcoin_ml.qm</file>
<file alias="mn">locale/bitcoin_mn.qm</file>
<file alias="mr_IN">locale/bitcoin_mr_IN.qm</file>
<file alias="ms">locale/bitcoin_ms.qm</file>
- <file alias="ms_MY">locale/bitcoin_ms_MY.qm</file>
+ <file alias="my">locale/bitcoin_my.qm</file>
<file alias="nb">locale/bitcoin_nb.qm</file>
<file alias="ne">locale/bitcoin_ne.qm</file>
<file alias="nl">locale/bitcoin_nl.qm</file>
- <file alias="nl_NL">locale/bitcoin_nl_NL.qm</file>
<file alias="pam">locale/bitcoin_pam.qm</file>
<file alias="pl">locale/bitcoin_pl.qm</file>
<file alias="pt">locale/bitcoin_pt.qm</file>
<file alias="pt_BR">locale/bitcoin_pt_BR.qm</file>
- <file alias="pt_PT">locale/bitcoin_pt_PT.qm</file>
<file alias="ro">locale/bitcoin_ro.qm</file>
- <file alias="ro_RO">locale/bitcoin_ro_RO.qm</file>
<file alias="ru">locale/bitcoin_ru.qm</file>
- <file alias="ru_RU">locale/bitcoin_ru_RU.qm</file>
<file alias="si">locale/bitcoin_si.qm</file>
<file alias="sk">locale/bitcoin_sk.qm</file>
- <file alias="sk_SK">locale/bitcoin_sk_SK.qm</file>
<file alias="sl">locale/bitcoin_sl.qm</file>
- <file alias="sl_SI">locale/bitcoin_sl_SI.qm</file>
<file alias="sn">locale/bitcoin_sn.qm</file>
+ <file alias="sq">locale/bitcoin_sq.qm</file>
<file alias="sr">locale/bitcoin_sr.qm</file>
<file alias="sr@latin">locale/bitcoin_sr@latin.qm</file>
<file alias="sv">locale/bitcoin_sv.qm</file>
@@ -87,15 +73,14 @@
<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="tr_TR">locale/bitcoin_tr_TR.qm</file>
<file alias="uk">locale/bitcoin_uk.qm</file>
- <file alias="uk_UA">locale/bitcoin_uk_UA.qm</file>
<file alias="ur">locale/bitcoin_ur.qm</file>
<file alias="uz@Cyrl">locale/bitcoin_uz@Cyrl.qm</file>
+ <file alias="uz@Latn">locale/bitcoin_uz@Latn.qm</file>
<file alias="vi">locale/bitcoin_vi.qm</file>
- <file alias="vi_VN">locale/bitcoin_vi_VN.qm</file>
<file alias="yo">locale/bitcoin_yo.qm</file>
<file alias="zh-Hans">locale/bitcoin_zh-Hans.qm</file>
+ <file alias="zh">locale/bitcoin_zh.qm</file>
<file alias="zh_CN">locale/bitcoin_zh_CN.qm</file>
<file alias="zh_HK">locale/bitcoin_zh_HK.qm</file>
<file alias="zh_TW">locale/bitcoin_zh_TW.qm</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 98d989f117..cf2de1a417 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -319,6 +319,8 @@ void BitcoinGUI::createActions()
signMessageAction->setStatusTip(tr("Sign messages with your Bitcoin addresses to prove you own them"));
verifyMessageAction = new QAction(tr("&Verify message..."), this);
verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Bitcoin addresses"));
+ m_load_psbt_action = new QAction(tr("Load PSBT..."), this);
+ m_load_psbt_action->setStatusTip(tr("Load Partially Signed Bitcoin Transaction"));
openRPCConsoleAction = new QAction(tr("Node window"), this);
openRPCConsoleAction->setStatusTip(tr("Open node debugging and diagnostic console"));
@@ -368,6 +370,7 @@ void BitcoinGUI::createActions()
connect(changePassphraseAction, &QAction::triggered, walletFrame, &WalletFrame::changePassphrase);
connect(signMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(signMessageAction, &QAction::triggered, [this]{ gotoSignMessageTab(); });
+ connect(m_load_psbt_action, &QAction::triggered, [this]{ gotoLoadPSBT(); });
connect(verifyMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(verifyMessageAction, &QAction::triggered, [this]{ gotoVerifyMessageTab(); });
connect(usedSendingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedSendingAddresses);
@@ -440,6 +443,7 @@ void BitcoinGUI::createMenuBar()
file->addAction(backupWalletAction);
file->addAction(signMessageAction);
file->addAction(verifyMessageAction);
+ file->addAction(m_load_psbt_action);
file->addSeparator();
}
file->addAction(quitAction);
@@ -458,7 +462,7 @@ void BitcoinGUI::createMenuBar()
QAction* minimize_action = window_menu->addAction(tr("Minimize"));
minimize_action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
connect(minimize_action, &QAction::triggered, [] {
- qApp->focusWindow()->showMinimized();
+ QApplication::activeWindow()->showMinimized();
});
connect(qApp, &QApplication::focusWindowChanged, [minimize_action] (QWindow* window) {
minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
@@ -856,6 +860,10 @@ void BitcoinGUI::gotoVerifyMessageTab(QString addr)
{
if (walletFrame) walletFrame->gotoVerifyMessageTab(addr);
}
+void BitcoinGUI::gotoLoadPSBT()
+{
+ if (walletFrame) walletFrame->gotoLoadPSBT();
+}
#endif // ENABLE_WALLET
void BitcoinGUI::updateNetworkState()
@@ -1260,7 +1268,7 @@ void BitcoinGUI::updateWalletStatus()
}
WalletModel * const walletModel = walletView->getWalletModel();
setEncryptionStatus(walletModel->getEncryptionStatus());
- setHDStatus(walletModel->privateKeysDisabled(), walletModel->wallet().hdEnabled());
+ setHDStatus(walletModel->wallet().privateKeysDisabled(), walletModel->wallet().hdEnabled());
}
#endif // ENABLE_WALLET
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 809cf8b4ed..70366e12d1 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -135,6 +135,7 @@ private:
QAction* usedReceivingAddressesAction = nullptr;
QAction* signMessageAction = nullptr;
QAction* verifyMessageAction = nullptr;
+ QAction* m_load_psbt_action = nullptr;
QAction* aboutAction = nullptr;
QAction* receiveCoinsAction = nullptr;
QAction* receiveCoinsMenuAction = nullptr;
@@ -270,6 +271,8 @@ public Q_SLOTS:
void gotoSignMessageTab(QString addr = "");
/** Show Sign/Verify Message dialog and switch to verify message tab */
void gotoVerifyMessageTab(QString addr = "");
+ /** Show load Partially Signed Bitcoin Transaction dialog */
+ void gotoLoadPSBT();
/** Show open dialog */
void openClicked();
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 3d40ee7823..64900a4343 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -51,9 +51,6 @@ 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", ""
-"Rescans are not possible in pruned mode. You will need to use -reindex which "
-"will download the whole blockchain again."),
-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 "
@@ -69,10 +66,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
QT_TRANSLATE_NOOP("bitcoin-core", ""
"This is the transaction fee you may pay when fee estimates are not available."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"This product includes software developed by the OpenSSL Project for use in "
-"the OpenSSL Toolkit %s and cryptographic software written by Eric Young and "
-"UPnP software written by Thomas Bernard."),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
"Total length of network version string (%i) exceeds maximum length (%i). "
"Reduce the number or size of uacomments."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -107,6 +100,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Change index out of range"),
QT_TRANSLATE_NOOP("bitcoin-core", "Config setting for %s only applied on %s network when in [%s] section."),
QT_TRANSLATE_NOOP("bitcoin-core", "Copyright (C) %i-%i"),
QT_TRANSLATE_NOOP("bitcoin-core", "Corrupted block database detected"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Could not find asmap file %s"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Could not parse asmap file %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Do you want to rebuild the block database now?"),
QT_TRANSLATE_NOOP("bitcoin-core", "Done loading"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error initializing block database"),
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index e8146982f9..b94fcc9865 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -105,6 +105,14 @@ int64_t ClientModel::getHeaderTipTime() const
return cachedBestHeaderTime;
}
+int ClientModel::getNumBlocks() const
+{
+ if (m_cached_num_blocks == -1) {
+ m_cached_num_blocks = m_node.getNumBlocks();
+ }
+ return m_cached_num_blocks;
+}
+
void ClientModel::updateNumConnections(int numConnections)
{
Q_EMIT numConnectionsChanged(numConnections);
@@ -241,9 +249,12 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, int heig
// cache best headers time and height to reduce future cs_main locks
clientmodel->cachedBestHeaderHeight = height;
clientmodel->cachedBestHeaderTime = blockTime;
+ } else {
+ clientmodel->m_cached_num_blocks = height;
}
- // if we are in-sync or if we notify a header update, update the UI regardless of last update time
- if (fHeader || !initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
+
+ // During initial sync, block notifications, and header notifications from reindexing are both throttled.
+ if (!initialSync || (fHeader && !clientmodel->node().getReindex()) || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
//pass an async signal to the UI thread
bool invoked = QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection,
Q_ARG(int, height),
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 79175e0af4..7ac4120a8f 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -56,6 +56,7 @@ public:
//! Return number of connections, default is in- and outbound (total)
int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const;
+ int getNumBlocks() const;
int getHeaderTipHeight() const;
int64_t getHeaderTipTime() const;
@@ -73,9 +74,10 @@ public:
bool getProxyInfo(std::string& ip_port) const;
- // caches for the best header
+ // caches for the best header, number of blocks
mutable std::atomic<int> cachedBestHeaderHeight;
mutable std::atomic<int64_t> cachedBestHeaderTime;
+ mutable std::atomic<int> m_cached_num_blocks{-1};
private:
interfaces::Node& m_node;
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 8a84122d9f..b46f416b6c 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -381,14 +381,6 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
if (ui->treeWidget->isEnabled()) // do not update on every click for (un)select all
CoinControlDialog::updateLabels(model, this);
}
-
- // TODO: Remove this temporary qt5 fix after Qt5.3 and Qt5.4 are no longer used.
- // Fixed in Qt5.5 and above: https://bugreports.qt.io/browse/QTBUG-43473
- else if (column == COLUMN_CHECKBOX && item->childCount() > 0)
- {
- if (item->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked && item->child(0)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked)
- item->setCheckState(COLUMN_CHECKBOX, Qt::Checked);
- }
}
// shows count of locked unspent outputs
diff --git a/src/qt/coincontroltreewidget.h b/src/qt/coincontroltreewidget.h
index 39dc9a5e9e..86af555385 100644
--- a/src/qt/coincontroltreewidget.h
+++ b/src/qt/coincontroltreewidget.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp
index 8e6474b0d4..5056e487fc 100644
--- a/src/qt/createwalletdialog.cpp
+++ b/src/qt/createwalletdialog.cpp
@@ -60,3 +60,8 @@ bool CreateWalletDialog::isMakeBlankWalletChecked() const
{
return ui->blank_wallet_checkbox->isChecked();
}
+
+bool CreateWalletDialog::isDescriptorWalletChecked() const
+{
+ return ui->descriptor_checkbox->isChecked();
+}
diff --git a/src/qt/createwalletdialog.h b/src/qt/createwalletdialog.h
index 30766107b9..20cce937c8 100644
--- a/src/qt/createwalletdialog.h
+++ b/src/qt/createwalletdialog.h
@@ -27,6 +27,7 @@ public:
bool isEncryptWalletChecked() const;
bool isDisablePrivateKeysChecked() const;
bool isMakeBlankWalletChecked() const;
+ bool isDescriptorWalletChecked() const;
private:
Ui::CreateWalletDialog *ui;
diff --git a/src/qt/csvmodelwriter.h b/src/qt/csvmodelwriter.h
index e443529335..ad247b6859 100644
--- a/src/qt/csvmodelwriter.h
+++ b/src/qt/csvmodelwriter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/forms/createwalletdialog.ui b/src/qt/forms/createwalletdialog.ui
index e49bab8f3b..b592140dd7 100644
--- a/src/qt/forms/createwalletdialog.ui
+++ b/src/qt/forms/createwalletdialog.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>364</width>
- <height>185</height>
+ <height>213</height>
</rect>
</property>
<property name="windowTitle">
@@ -17,7 +17,7 @@
<property name="geometry">
<rect>
<x>10</x>
- <y>140</y>
+ <y>170</y>
<width>341</width>
<height>32</height>
</rect>
@@ -106,6 +106,22 @@
<string>Make Blank Wallet</string>
</property>
</widget>
+ <widget class="QCheckBox" name="descriptor_checkbox">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>140</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string>Use descriptors for scriptPubKey management</string>
+ </property>
+ <property name="text">
+ <string>Descriptor Wallet</string>
+ </property>
+ </widget>
</widget>
<tabstops>
<tabstop>wallet_name_line_edit</tabstop>
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index ebb6bbd4f5..8b70800838 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -216,17 +216,17 @@
</widget>
</item>
<item row="7" column="0">
- <widget class="QLabel" name="labelNetwork">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Network</string>
- </property>
- </widget>
+ <widget class="QLabel" name="labelNetwork">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Network</string>
+ </property>
+ </widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_8">
@@ -503,12 +503,12 @@
<height>24</height>
</size>
</property>
- <property name="text">
- <string/>
- </property>
<property name="toolTip">
<string>Decrease font size</string>
</property>
+ <property name="text">
+ <string/>
+ </property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
<normaloff>:/icons/fontsmaller</normaloff>:/icons/fontsmaller</iconset>
@@ -652,12 +652,12 @@
</item>
<item>
<widget class="QLineEdit" name="lineEdit">
- <property name="placeholderText">
- <string/>
- </property>
<property name="enabled">
<bool>false</bool>
</property>
+ <property name="placeholderText">
+ <string/>
+ </property>
</widget>
</item>
</layout>
@@ -1503,6 +1503,32 @@
</widget>
</item>
<item row="18" column="0">
+ <widget class="QLabel" name="peerMappedASLabel">
+ <property name="toolTip">
+ <string>The mapped Autonomous System used for diversifying peer selection.</string>
+ </property>
+ <property name="text">
+ <string>Mapped AS</string>
+ </property>
+ </widget>
+ </item>
+ <item row="18" column="1">
+ <widget class="QLabel" name="peerMappedAS">
+ <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="19" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 5ec6fcb7a9..af86fe5d27 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -779,9 +779,9 @@ QString formatServicesStr(quint64 mask)
return QObject::tr("None");
}
-QString formatPingTime(double dPingTime)
+QString formatPingTime(int64_t ping_usec)
{
- return (dPingTime == std::numeric_limits<int64_t>::max()/1e6 || dPingTime == 0) ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(dPingTime * 1000), 10));
+ return (ping_usec == std::numeric_limits<int64_t>::max() || ping_usec == 0) ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(ping_usec / 1000), 10));
}
QString formatTimeOffset(int64_t nTimeOffset)
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 406ce05056..0d9293fbad 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -205,8 +205,8 @@ namespace GUIUtil
/* Format CNodeStats.nServices bitmask into a user-readable string */
QString formatServicesStr(quint64 mask);
- /* Format a CNodeCombinedStats.dPingTime into a user-readable string or display N/A, if 0*/
- QString formatPingTime(double dPingTime);
+ /* Format a CNodeStats.m_ping_usec into a user-readable string or display N/A, if 0*/
+ QString formatPingTime(int64_t ping_usec);
/* Format a CNodeCombinedStats.nTimeOffset into a user-readable string. */
QString formatTimeOffset(int64_t nTimeOffset);
diff --git a/src/qt/locale/bitcoin_af.ts b/src/qt/locale/bitcoin_af.ts
new file mode 100644
index 0000000000..23d0f609d7
--- /dev/null
+++ b/src/qt/locale/bitcoin_af.ts
@@ -0,0 +1,2154 @@
+<TS language="af" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>Regs-klik om die adres of etiket te wysig</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>Skep 'n nuwe adres</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;Nuwe</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>Maak 'n kopie van die huidige adres na die stelsel klipbord</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;Kopie</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>S&amp;luit</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>Verwyder die uitgekiesde adres van die lys</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Voer inligting uit van die huidige blad na n lêer</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;Uitvoer</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;Verwyder</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Kies die address na wie die muntstukke gestuur moet word</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Kies die adres vir die ontvangs van betaaling</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>K&amp;ies</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Stuur adresse</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Ontvang adresse</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>Dit is jou Bitcoin-adresse vir die stuur van betalings. Kontroleer altyd die bedrag en die ontvangsadres voordat u munte stuur.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Kopie Adres</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Kopie &amp;Etiket</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Wysig</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Voer adres lys uit</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Koma geskeide lêer (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Uitvoering Misluk</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Kon nie die adreslys stoor na %1 nie. Probeer asseblief weer.</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>(geen etiket)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation>Wagfrase Dialoog</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>Tik wagfrase in</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>Nuwe wagfrase</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>Herhaal nuwe wagfrase</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Enkripteer beursie</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Hierdie operasie benodig 'n wagwoord om die beursie oop te sluit.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Ontsluit beursie</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Hierdie operasie benodig 'n wagwoord om die beursie oop te sluit.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Dekripteer beursie</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Verander wagfrase</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Bevestig beursie enkripsie.</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Waarskuwing: As jy jou beursie enkripteer en jou wagwoord verloor, sal jy &lt;b&gt;AL JOU BITCOINS VERLOOR&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Is jy seker jy wil jou beursie enkripteer?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Beursie enkriptasie voltooi</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>BELANGRIK: Enige vorige rugsteune wat u gemaak het van u beursie-lêer moet vervang word met die nuut-gegenereerde, versleutelde beursie-lêer. Vir sekuriteitsredes sal vorige rugsteune van die onversleutelde beursie-lêer onbruikbaar word sodra u die nuwe, versleutelde beursie begin gebruik.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Beursie enkriptasie het misluk</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Beursie bewaaking het misluk as gevolg van 'n interne fout. Die beursie is nie bewaak nie!</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Die wagfrase stem nie ooreen nie</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Beursie oopsluiting het misluk</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Die wagfrase wat ingetik was om die beursie oop te sluit, was verkeerd.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Beursie dekripsie het misluk</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Die beursie se wagfrase verandering was suksesvol.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Waarskuwing: Die Caps Lock is aan!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Netmasker</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Verban Tot</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>Teken &amp;Boodskap</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>Sinchroniseer met die netwerk ...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;Oorsig</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>Wys algemene oorsig van die beursie</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;Transaksies</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>Besoek transaksie geskiedenis</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>S&amp;luit af</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>Sluit af</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>&amp;Oor %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Wys inligting oor %1</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>Oor &amp;Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Wys inligting oor Qt</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>&amp;Opsies</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation>Verander konfigurasie opsies vir %1</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;Enkripteer Beursie...</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>&amp;Rugsteun Beursie...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>Verander wagwoord frase...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>Maak &amp;URI oop...</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Klik om netwerk aktiwiteit af te skakel.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Netwerk aktiwiteid afgeskakel.</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Klik om netwerk aktiwiteit weer aan te skakel.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Sinkroniseer tans Hoofde (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Herindekseer blokke op skyf...</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>Stuur muntstukke na 'n Bitcoin adres</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>Rugsteun beursie na 'n ander plek</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>Verander die wagwoordfrase wat vir beursie-versleuteling gebruik word</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;Verifieer boodskap...</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;Stuur</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;Ontvang</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Wys / Versteek</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Wys of versteek die hoof Venster</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Versleutel die private sleutels wat aan u beursie behoort</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Teken boodskappe met u Bitcoin adresse om te bewys dat u hul besit</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Bevestig boodskappe om te verseker dat hulle geteken was met gespesifiseerde Bitcoin adresse</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;Lêer</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>&amp;Instellings</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>&amp;Hulp</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>Blad nutsbalk</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>Versoek betalings (genereer QR kodes en bitcoin: URIs)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Wys die lys van gebruikte stuur adresse en etikette</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Wys die lys van gebruikte ontvangsadresse en etikette</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>&amp;Opdrag lys opsies</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Indekseer tans blokke op skyf...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Prosesseer tans blokke op skyf...</translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 agter</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Ontvangs van laaste blok is %1 terug.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Opvolgende transaksies sal nog nie sigbaar wees nie.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Fout</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Waarskuwing</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Informasie</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation>Op datum</translation>
+ </message>
+ <message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Wys die %1 hulpboodskap om 'n lys met moontlike Bitcoin bevel-lyn opsies te verkry</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;Venster</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 klient</translation>
+ </message>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>Verbind tans aan eweknieë...</translation>
+ </message>
+ <message>
+ <source>Catching up...</source>
+ <translation>Besig om op te vang...</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>Fout: %1</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Datum: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Bedrag: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Tipe: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Etiket: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Adres: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Transaksie gestuur</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>Inkomende transaksie</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>HD sleutel generasie is &lt;b&gt;aangesit&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>HD sleutel generasie is &lt;b&gt;afgesit&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>Beursie is &lt;b&gt;versleutel&lt;/b&gt; en is tans &lt;b&gt;oopgesluit&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>Beursie is &lt;b&gt;versleutel&lt;/b&gt; en is tans &lt;b&gt;gesluit&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>'n Noodlottige fout het voorgekom. Bitcoin kan nie langer voortgaan nie en sal afsluit.</translation>
+ </message>
+</context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Coin Selection</source>
+ <translation>Munt Keuse</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Hoeveelheid:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Grepe:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Bedrag:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Fooi:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Stof:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Na Fooi:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Verander:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>(on)selekteer alles</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>Boom wyse</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>Lys wyse</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Bedrag</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation>Ontvang met etiket</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Ontvang met adres</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Datum</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation>Bevestigings</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Bevestig</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Maak kopie van adres</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopieer etiket</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopieer bedrag</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Kopieer transaksie ID</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Sluit ongespandeerde</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Onsluit ongespandeerde</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Kopieer hoeveelheid</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Kopieer fooi</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Kopieer na fooi</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Kopieer grepe</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Kopieer stof</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Kopieer verandering</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 gesluit)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>ja</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>nee</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>Hierdie etiket verander na rooi as enige ontvanger 'n bedrag kleiner as die huidige stof drempelwaarde ontvang.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Kan wissel met +/- %1 satoshi(s) per inset.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(geen etiket)</translation>
+ </message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>Verander vanaf %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(verander)</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation>Wysig Adres</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;Etiket</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation>Die etiket geassosieer met hierdie adreslys inskrywing</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>Die adres geassosieer met hierdie adreslys inskrywing. Dié kan slegs gewysig word vir stuur-adresse.</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;Adres</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>Nuwe stuurende adres</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Wysig ontvangende adres</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Wysig stuurende adres</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>Die ingeskrewe adres "%1" is nie 'n geldige Bitcoin adres nie.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Kon nie die beursie oopsluit nie.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Nuwe sleutel genereering het misluk.</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation>n Nuwe data lêer sal geskep word.</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation>naam</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Lêer bestaan reeds. Voeg %1 indien u van plan is om n nuwe lêer hier te skep.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>Pad bestaan reeds en is nie 'n lêergids nie.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>Kan nie data gids hier skep nie.</translation>
+ </message>
+</context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation>weergawe</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation>Oor %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>Opdrag lys opsies</translation>
+ </message>
+</context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Welcome</source>
+ <translation>Welkom</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation>Welkom by %1.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>Gebruik die standaard data gids</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>Gebruik 'n persoonlike data gids:</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Die beursie sal ook gestoor word in hierdie lêer.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation>Fout: Gespesifiseerde dataleêr "%1" kon nie geskep word nie.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Fout</translation>
+ </message>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation>Vorm</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Aantal blokke oor</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Onbekend...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Laaste blok tyd</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation>Vorderering</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>Vorderingstoename per uur</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>besig met bereken...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>Geskatte tyd oor totdat gesinkroniseer</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Steek weg</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ <message>
+ <source>URI:</source>
+ <translation>URI:</translation>
+ </message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>Options</source>
+ <translation>Opsies</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation>&amp;Hoof</translation>
+ </message>
+ <message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Begin %1 outomaties nadat jy aangemeld is by die stelsel.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>&amp;Begin %1 op stelsel aanmelding</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Grootte van &amp;databasis kas</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation>Aantal skrip &amp;verifikasie drade</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Maak die %1 konfigurasie lêer oop van die werk gids.</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>Open Konfigurasie Lêer</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>Alle kliëntopsies na verstek terugstel.</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation>&amp;Herstel Opsies</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation>&amp;Netwerk</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation>&amp;Beursie</translation>
+ </message>
+ <message>
+ <source>Expert</source>
+ <translation>Kenner</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation>Bemagtig munt &amp;beheer funksies.</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation>&amp;Spandeer onbevestigde kleingeld</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation>&amp;Port:</translation>
+ </message>
+ <message>
+ <source>Used for reaching peers via:</source>
+ <translation>Word gebruik vir die bereik van eweknieë 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;Venster</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation>V&amp;erminder op toemaak</translation>
+ </message>
+ <message>
+ <source>&amp;Display</source>
+ <translation>&amp;Vertoon</translation>
+ </message>
+ <message>
+ <source>User Interface &amp;language:</source>
+ <translation>Gebruikers Koppelvlak &amp;taal:</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation>&amp;Eenheid om bedrae te toon in:</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>Of om munt beheer funksies te wys of nie.</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>&amp;OK</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>&amp;Kanselleer</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation>standaard</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation>niks</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <translation>Bevestig terugstel van opsies</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>Kliënt moet herbegin word om veranderinge te aktiveer.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>Kliënt sal toegemaak word. Wil u voortgaan?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Konfigurasie opsies</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Fout</translation>
+ </message>
+ <message>
+ <source>The configuration file could not be opened.</source>
+ <translation>Die konfigurasie lêer kon nie oopgemaak word nie.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>Hierdie verandering sal 'n herbegin van die kliënt vereis. </translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>Die verskafde volmag adres is ongeldig.</translation>
+ </message>
+</context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Form</source>
+ <translation>Vorm</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>Kyk-net:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>Beskikbaar:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>U huidige bruikbare balans</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>Hangend:</translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation>Onvolwasse:</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>Balans</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>Totaal:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation>U huidige totale balans</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>Besteebaar:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Onlangse transaksies</translation>
+ </message>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Betalings versoek fout</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>URI hantering</translation>
+ </message>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ <message>
+ <source>User Agent</source>
+ <translation>Gebruikeragent</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>NodusId</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Gestuur</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Ontvang</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>Bedrag</translation>
+ </message>
+ <message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Voer in 'n Bitcoin adres (bv. %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>Geen</translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation>n.v.t.</translation>
+ </message>
+ <message>
+ <source>%1 ms</source>
+ <translation>%1 ms</translation>
+ </message>
+ <message>
+ <source>%1 and %2</source>
+ <translation>%1 en %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: %1</source>
+ <translation>Fout: %1</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>onbekend</translation>
+ </message>
+</context>
+<context>
+ <name>QRImageWidget</name>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Stoor beeld</translation>
+ </message>
+ <message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation>Gevolglike URI te lank, probeer teks verkort vir etiket/boodskap</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>Fout met enkodering van URI na QR kode</translation>
+ </message>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>N/A</source>
+ <translation>n.v.t.</translation>
+ </message>
+ <message>
+ <source>Client version</source>
+ <translation>Kliëntweergawe</translation>
+ </message>
+ <message>
+ <source>&amp;Information</source>
+ <translation>Informasie</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>Algemeen</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>Netwerk</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>Naam</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation>Aantal verbindings</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation>Blokketting</translation>
+ </message>
+ <message>
+ <source>Current number of blocks</source>
+ <translation>Huidige aantal blokke</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Ontvang</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Gestuur</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation>Verbanne porture</translation>
+ </message>
+ <message>
+ <source>Whitelisted</source>
+ <translation>Gewitlys</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Rigting</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>Weergawe</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>Gebruikeragent</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Laaste blok tyd</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation>In:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>Uit:</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;uur</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;dag</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp;week</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp;jaar</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;Ontkoppel</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>Verbied vir</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>&amp;Toegelaat</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>Netwerk aktiewiteit gedeaktiveer</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(nodus id: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>via %1</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>nooit</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>Inkomende</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>Uitgaande</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>
+</context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Amount:</source>
+ <translation>&amp;Bedrag:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etiket:</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation>&amp;Boodskap:</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Vee alle velde op die vorm skoon</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>Skoonmaak</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>Wys</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Verwyder</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopieer etiket</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Kopieer boodskap</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopieer bedrag</translation>
+ </message>
+</context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>QR Code</source>
+ <translation>QR Kode</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation>Kopieer &amp;URI</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Address</source>
+ <translation>Kopieer &amp;Address</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Stoor beeld</translation>
+ </message>
+ <message>
+ <source>Request payment to %1</source>
+ <translation>Versoek betaling van %1</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>Betaling informasie</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>Etiket</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Boodskap</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Beursie</translation>
+ </message>
+</context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Datum</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Boodskap</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(geen etiket)</translation>
+ </message>
+ <message>
+ <source>(no message)</source>
+ <translation>(geen boodskap)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(geen bedrag versoek)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>Versoekte</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>Stuur Munstukke</translation>
+ </message>
+ <message>
+ <source>Coin Control Features</source>
+ <translation>Munt Beheer Kenmerke</translation>
+ </message>
+ <message>
+ <source>Inputs...</source>
+ <translation>Insette...</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>outomaties gekies</translation>
+ </message>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation>Onvoldoende fondse</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Hoeveelheid:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Grepe:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Bedrag:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Fooi:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Na Fooi:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Verander:</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation>Transaksie fooi:</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>Kies...</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>Die verstekfooi kan veroorsaak dat 'n transaksie gestuur word wat
+etlike ure of dae (of nooit) sal neem om te bevestig. Oorweeg om
+'n fooi met die hand te kies, of wag tot jy die hele ketting bevestig het.</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Waarskuwing: fooiskatting is tans onbeskikbaar</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>per kilogreep</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Steek weg</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>Aanbeveel:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>Aangepaste:</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(Slimfooi nog nie opgestel nie. Dit neem gewoonlik 'n paar blokke...)</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation>Stuur aan vele ontvangers op eens</translation>
+ </message>
+ <message>
+ <source>Add &amp;Recipient</source>
+ <translation>Voeg by &amp;Ontvanger</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Vee alle velde op die vorm skoon</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Stof:</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>Bevestigingstyd teiken:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Bemoontlik vervang-deur-fooi</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>Met Vervang-Met-Fooi (BIP-125) kan jy 'n transaskiefooi verhoog nadat dit gestuur is.
+Daarsonder mag 'n hoër fooi dalk aanbeveel word om te kompenseer vir 'n verhoogde
+transaksievertragingsrisiko.</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Vee &amp;Alles skoon</translation>
+ </message>
+ <message>
+ <source>Balance:</source>
+ <translation>Balans:</translation>
+ </message>
+ <message>
+ <source>Confirm the send action</source>
+ <translation>Bevestig stuuraksie</translation>
+ </message>
+ <message>
+ <source>S&amp;end</source>
+ <translation>S&amp;tuur</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Kopieer hoeveelheid</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopieer bedrag</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Kopieer fooi</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Kopieer na fooi</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Kopieer grepe</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Kopieer stof</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Kopieer verandering</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 blokke)</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 tot %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Is u seker u wil verstuur?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>of</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>U kan die fooi later verhoog (sein Vervang-met-Fooi, BIP-125)</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transaksie fooi</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Sein nie Vervang-Met-Fooi nie, BIP-25</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Bevestig versending van munte</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>Die ontvangeradres is ongeldig. Kyk asseblief weer mooi.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Bedrag moet groter as nul wees</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Die bedrag oorskry jou saldo</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>Die somtotaal oorskry jou saldo as die %1 transaksiefooi ingereken word</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>Duplikaatadres: adresse behoort slegs eenkeer gebruik te word</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Transaksieopstelling het gefaal</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>'n Fooi hoër as %1 word as buitensporig beskou</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Betalings versoek verstryk.</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Waarskuwing: Ongeldige Bitcoinadres</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>Die adres wat u gekies het vir verandering is nie deel van hierdie
+beursie nie. Enige of alle fondse mag dalk daarheen gestuur word.
+Is u seker?</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(geen etiket)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ <message>
+ <source>A&amp;mount:</source>
+ <translation>&amp;Bedrag:</translation>
+ </message>
+ <message>
+ <source>Pay &amp;To:</source>
+ <translation>Betaal &amp;Vir:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etiket:</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Kies voorheen gebruikte adres</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>Die Bitcoinadres waarheen die betaling gestuur word</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Plak adres van aanknipbord af</translation>
+ </message>
+ <message>
+ <source>Remove this entry</source>
+ <translation>Verwyder hierdie inskrywing</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>De fooi word afgetrek van die gestuurde bedrag.
+Die ontvanger sal minder ontvang as wat u in die
+bedrag opgee. As daar meer as een ontvanger is,
+word die fooi eweredig verdeel.</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>Bedrag &amp;Sonder fooi </translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>Gebruik beskikbare saldo</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Boodskap:</translation>
+ </message>
+ <message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>Hierdie is 'n ongemagtigde uitbetalingsversoek</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>Hierdie is 'n gemagtigde uitbetalingsversoek
+</translation>
+ </message>
+ <message>
+ <source>Pay To:</source>
+ <translation>Betaal Vir:</translation>
+ </message>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ <message>
+ <source>&amp;Sign Message</source>
+ <translation>&amp;Teken boodskap</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Kies voorheen gebruikte adres</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Plak adres van aanknipbord af</translation>
+ </message>
+ <message>
+ <source>Signature</source>
+ <translation>Handtekening</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation>Teken &amp;Boodskap</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Vee &amp;Alles skoon</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation>&amp;Verifieer Boodskap</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation>Verifieer &amp;Boodskap</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Boodskap geteken.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Boodskap geverifieer.</translation>
+ </message>
+</context>
+<context>
+ <name>TrafficGraphWidget</name>
+ <message>
+ <source>KB/s</source>
+ <translation>KB/s</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Date</source>
+ <translation>Datum</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>Van</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>onbekend</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>Na</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>eie adres</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>kyk-net</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>etiket</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Krediet</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>nie aanvaar nie</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Debiet</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>Totale debiet</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Totale crediet</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transaksie fooi</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation>Netto bedrag</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Boodskap</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Kommentaar</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>Transaksie ID</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation>Transaksie totale grootte</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transaksie</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Bedrag</translation>
+ </message>
+ <message>
+ <source>true</source>
+ <translation>waar</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>onwaar</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Datum</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Tipe</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Ontvang met</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Ontvang van</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Gestuur na</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Betalings Aan/na jouself</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Gemyn</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>kyk-net</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n.v.t)</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(geen etiket)</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Datum en tyd wat die transaksie ontvang was.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Tipe transaksie.</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>All</source>
+ <translation>Alles</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Vandag</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Hierdie week</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Hierdie maand</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Verlede maand</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Hierdie jaar</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Reeks...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Ontvang met</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Gestuur na</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Aan/na jouself</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Gemyn</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Ander</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Min bedrag</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Maak kopie van adres</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopieer etiket</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopieer bedrag</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Kopieer transaksie ID</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Koma geskeide lêer (*.csv)</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Bevestig</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Datum</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Tipe</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Adres</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Uitvoering Misluk</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Reeks:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>aan</translation>
+ </message>
+</context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletController</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>Stuur Munstukke</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>Nuwe fooi:</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;Uitvoer</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Voer inligting uit van die huidige blad na n lêer</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Error loading %s</source>
+ <translation>Fout met laai %s</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>Invoer proses tans besig..</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation>Teken van transaksie het misluk</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>Dié is eksperimentele sagteware.</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>Transaksie bedrag te klein</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>Transaksie te groot</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>Besig met verifieer van beursie(s)...</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation>%s is baie hoog gestel!</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>Begin tans netwerkdrade...</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>Dit is die minimum transaksie fooi wat u betaal op elke transaksie.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>Dit is die transaksie fooi wat u sal betaal as u 'n transaksie stuur.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>Transaksies bedrae moet nie negatief wees nie</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>Transaksie se mempool ketting is te lank</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>Transaksie moet ten minste een ontvanger hê</translation>
+ </message>
+ <message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation>Onbekende netwerk gespesifiseer in -onlynet: '%s'</translation>
+ </message>
+ <message>
+ <source>Insufficient funds</source>
+ <translation>Onvoldoende fondse</translation>
+ </message>
+ <message>
+ <source>Loading block index...</source>
+ <translation>Laai blok indeks...</translation>
+ </message>
+ <message>
+ <source>Loading wallet...</source>
+ <translation>Laai beursie...</translation>
+ </message>
+ <message>
+ <source>Cannot downgrade wallet</source>
+ <translation>Kan nie beursie afgradeer nie</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>Word herskandeer...</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation>Klaar gelaai</translation>
+ </message>
+</context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_am.ts b/src/qt/locale/bitcoin_am.ts
new file mode 100644
index 0000000000..f78d4b970c
--- /dev/null
+++ b/src/qt/locale/bitcoin_am.ts
@@ -0,0 +1,434 @@
+<TS language="am" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>አድራሻ ወይም መለያ ስም ለመቀየር ቀኙን ጠቅ ያድርጉ</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>አዲስ አድራሻ ፍጠር</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;አዲስ</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>አሁን የተመረጠውን አድራሻ ወደ ሲስተሙ ቅንጥብ ሰሌዳ ቅዳ</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;ቅዳ</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>ዝጋ</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>አሁን የተመረጠውን አድራሻ ከዝርዝሩ ውስጥ ሰርዝ</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>በአሁኑ ማውጫ ውስጥ ያለውን መረጃ ወደ አንድ ፋይል ላክ</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;ላክ</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;ሰርዝ</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>ገንዘብ/ኮይኖች የሚልኩለትን አድራሻ ይምረጡ</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>ገንዘብ/ኮይኖች የሚቀበሉበትን አድራሻ ይምረጡ</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>ምረጥ</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>የመላኪያ አድራሻዎች</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <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>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>ቅዳ &amp;መለያ ስም</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation> &amp;ቀይር</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>የአድራሻ ዝርዝር ላክ</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>ኮማ ሴፓሬትድ ፋይል (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>ወደ ውጪ መላክ አልተሳካም</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>የአድራሻ ዝርዝሩን ወደ %1 ለማስቀመጥ ሲሞከር ስህተት አጋጥሟል:: እባክዎ መልሰው ይሞክሩ::</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>አድራሻ</translation>
+ </message>
+ <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>
+ <message>
+ <source>New passphrase</source>
+ <translation>አዲስ የይለፍ-ሐረግ</translation>
+ </message>
+ <message>
+ <source>Repeat new 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>
+ <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>
+ <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>ማስጠንቀቂያ: የቢትኮይን ቦርሳዎን አመስጥረው የይለፍ-ሐረግዎን ካጡት&lt;b&gt;ቢትኮይኖቾን በሙሉ ያጣሉ&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>እርግጠኛ ነዎት ቦርሳዎን ማመስጠር ይፈልጋሉ?</translation>
+ </message>
+ <message>
+ <source>Wallet 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>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>የቦርሳ ማመስጠር አልተሳካም</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>የቦርሳ ማመስጠር በውስጣዊ ስህተት ምክንያት አልተሳካም:: ቦርሳዎ አልተመሰጠረም::</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>የተሰጡት የይለፍ-ሐረግዎች አይዛመዱም::</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>ቦርሳ መክፈት አልተሳካም</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>ቦርሳ ለመፍታት ያስገቡት የይለፍ-ሐረግ ትክክል አልነበረም::</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>ቦርሳ መፍታት አልተሳካም </translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>የቦርሳ የይለፍ-ሐረግ በተሳካ ሁኔታ ተቀይሯል.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>ማስጠንቀቂያ: የ "Caps Lock" ቁልፍ በርቷል!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>አይፒ/ኔትማስክ IP/Netmask</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>ታግደዋል እስከ</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>ምልክትና መልእክት...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>ከኔትወርክ ጋራ በማመሳሰል ላይ ነው...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;አጠቃላይ እይታ</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>የቦርሳ አጠቃላይ እይታ ኣሳይ</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;ግብይቶች</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>የግብይት ታሪክ ያስሱ</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>ውጣ</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>አፕሊኬሽኑን አቁም</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>&amp;ስለ %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>ስለ %1 መረጃ አሳይ</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>ስለ &amp;Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>ስለ Qt መረጃ አሳይ</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>&amp;አማራጮች...</translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>(no label)</source>
+ <translation>(መለያ ስም የለም)</translation>
+ </message>
+ </context>
+<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ </context>
+<context>
+ <name>Intro</name>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Address</source>
+ <translation>አድራሻ</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(መለያ ስም የለም)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>(no label)</source>
+ <translation>(መለያ ስም የለም)</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>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(መለያ ስም የለም)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>ኮማ ሴፓሬትድ ፋይል (*.csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>አድራሻ</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>ወደ ውጪ መላክ አልተሳካም</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletController</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;ላክ</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>በአሁኑ ማውጫ ውስጥ ያለውን መረጃ ወደ አንድ ፋይል ላክ</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts
index 3cb4628c42..0d138d353c 100644
--- a/src/qt/locale/bitcoin_ar.ts
+++ b/src/qt/locale/bitcoin_ar.ts
@@ -47,7 +47,7 @@
</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>
@@ -66,10 +66,30 @@
<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>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>
<message>
+ <source>Copy &amp;Label</source>
+ <translation>نسخ&amp;تسمية</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>تحرير</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>تصدير قائمة العناوين</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>ملف مفصول بفاصلة (*.csv)</translation>
</message>
@@ -80,51 +100,872 @@
</context>
<context>
<name>AddressTableModel</name>
- </context>
+ <message>
+ <source>Label</source>
+ <translation>وسم</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>عنوان</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(بدون وسم)</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
- </context>
+ <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>
+ <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>
+ <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>إذا شفرت محفظتك وفقدت كلمة المرور، ستفقد كل ما تملك من البيتكوين.</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>هل انت متأكد بأنك تريد تشفير محفظتك؟</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <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; عشرة أحرف عشوائية أو أكثر &lt;/b&gt; ، أو &lt;b&gt; ثماني كلمات أو أكثر&lt;/b&gt; .</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>ادخل كملة المرور القديمة وكلمة المرور الجديدة للمحفظة.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>سوف يتم تشفير محفظتك</translation>
+ </message>
+ <message>
+ <source>Your wallet is about 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>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>خطأ في تشفير المحفظة</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>فشل تشفير المحفظة بسبب خطأ داخلي. لم يتم تشفير محفظتك.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>كلمتي المرور ليستا متطابقتان</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>فشل فتح المحفظة</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>كلمة المرور التي تم إدخالها لفك تشفير المحفظة غير صحيحة.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>فشل فك التشفير المحفظة</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>لقد تم تغير عبارة مرور المحفظة بنجاح</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>تحذير: مفتاح الحروف الكبيرة مفعل</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
- </context>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>عنوان البروتوكول/قناع</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>محظور حتى</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
+ <source>Sign &amp;message...</source>
+ <translation>التوقيع و الرسائل</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>مزامنة مع الشبكة ...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;نظرة عامة</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>إظهار نظرة عامة على المحفظة</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;المعاملات</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>تصفح تاريخ العمليات</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>خروج</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>إغلاق التطبيق</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>حوالي %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>أظهر المعلومات حولة %1</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>عن &amp;Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>اظهر المعلومات</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>&amp;خيارات ...</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation>تغيير خيارات الإعداد لأساس ل%1</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;تشفير المحفظة</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>&amp;نسخ احتياط للمحفظة</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>&amp;تغيير كلمة المرور</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>افتح &amp;URI...</translation>
+ </message>
+ <message>
+ <source>Create Wallet...</source>
+ <translation>إنشاء محفظة...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>إنشاء محفظة جديدة</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>المحفظة:</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>اضغط لإلغاء تفعيل الشبكه</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>تم إلغاء تفعيل الشبكه</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>اضغط لتفعيل الشبكه مره أخرى</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>مزامنة الرؤوس (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>إعادة فهرسة الكتل على القرص ...</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>%1 اتصال نشط بشبكة البيتكوين</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>ارسل عملات الى عنوان بيتكوين</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>احفظ نسخة احتياطية للمحفظة في مكان آخر</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>تغيير كلمة المرور المستخدمة لتشفير المحفظة</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;التحقق من الرسالة...</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;ارسل</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;استقبل</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;عرض / اخفاء</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>عرض او اخفاء النافذة الرئيسية</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>تشفير المفتاح الخاص بمحفظتك</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>وقَع الرسائل بواسطة ال: Bitcoin الخاص بك لإثبات امتلاكك لهم</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>تحقق من الرسائل للتأكد من أنَها وُقعت برسائل Bitcoin محدَدة</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;ملف</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>&amp;الاعدادات</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>&amp;مساعدة</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>شريط أدوات علامات التبويب</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>أطلب دفعات (يولد كودات الرمز المربع وبيت كوين: العناوين المعطاة)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>عرض قائمة عناوين الإرسال المستخدمة والملصقات</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>عرض قائمة عناوين الإستقبال المستخدمة والملصقات</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>&amp;خيارات سطر الأوامر</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>ترتيب فهرسة الكتل على القرص...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>معالجة الكتل على القرص...</translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>خلف %1</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>تم توليد الكتلة المستقبلة الأخيرة منذ %1.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>المعاملات بعد ذلك لن تكون مريئة بعد.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>خطأ</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>تحذير</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>المعلومات</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation>محدث</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation>&amp;عناوين الإرسال</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation>&amp;عناوين الإستقبال</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <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>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>بين اشارة المساعدة %1 للحصول على قائمة من خيارات اوامر البت كوين المحتملة </translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>المحفظة الإفتراضية</translation>
+ </message>
+ <message>
<source>No wallets available</source>
<translation>المحفظة الرقمية غير متوفرة</translation>
</message>
<message>
+ <source>&amp;Window</source>
+ <translation>نافذه</translation>
+ </message>
+ <message>
+ <source>Minimize</source>
+ <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>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>اتصال إلي القرناء...</translation>
+ </message>
+ <message>
+ <source>Catching up...</source>
+ <translation>اللحاق بالركب ...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>خطأ: %1</translation>
</message>
- </context>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>التاريخ %1
+
+
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>الكمية %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>المحفظة: %1</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>نوع %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>علامه: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>عنوان %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>إرسال المعاملة</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>المعاملات الواردة</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>توليد المفاتيح الهرمية الحتمية HD &lt;b&gt;مفعل&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>توليد المفاتيح الهرمية الحتمية HD &lt;b&gt;معطل&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <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>
+ <translation>المحفظة &lt;b&gt;مشفرة&lt;/b&gt; و &lt;b&gt;مفتوحة&lt;/b&gt; حاليا</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation>المحفظة &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>
<name>CoinControlDialog</name>
- </context>
+ <message>
+ <source>Coin Selection</source>
+ <translation>اختيار العمله</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>الكمية:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>بايت</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>القيمة :</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>الرسوم:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>غبار:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>بعد الرسوم :</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>تعديل :</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>عدم اختيار الجميع</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>صيغة الشجرة</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>صيغة القائمة</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>مبلغ</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation>مستقبل مع ملصق</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>مستقبل مع عنوان</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>التاريخ</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation>التأكيدات</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>تأكيد</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>نسخ العنوان</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation> انسخ التسمية</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>نسخ الكمية</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>نسخ رقم العملية</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>قفل غير المنفق</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>فتح غير المنفق</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>نسخ الكمية </translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>نسخ الرسوم</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>نسخ بعد الرسوم</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>نسخ البايتات </translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>نسخ الغبار</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>نسخ التعديل</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 تم قفله)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>نعم</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>لا</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>يتحول هذا الملصق إلى اللون الأحمر إذا تلقى أي مستلم كمية أصغر من عتبة الغبار الحالية.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>يمكن أن يختلف +/- %1 من ساتوشي(s) لكل إدخال.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(بدون وسم)</translation>
+ </message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>تغير من %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(تغير)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create</source>
+ <translation>إنشاء</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
- </context>
+ <message>
+ <source>Edit Address</source>
+ <translation>تعديل العنوان</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;وصف</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation>الملصق المرتبط بقائمة العناوين المدخلة</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>العنوان المرتبط بقائمة العناوين المدخلة. و التي يمكن تعديلها فقط بواسطة ارسال العناوين</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;العنوان</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>عنوان إرسال جديد</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>تعديل عنوان الأستلام</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>تعديل عنوان الارسال</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>العنوان المدخل "%1" ليس عنوان بيت كوين صحيح.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation> يمكن فتح المحفظة.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>فشل توليد مفتاح جديد.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
- </context>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation>سيتم انشاء دليل بيانات جديد.</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation>الإسم</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>الدليل موجوج بالفعل. أضف %1 اذا نويت إنشاء دليل جديد هنا.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>المسار موجود بالفعل، وهو ليس دليلاً.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>لا يمكن انشاء دليل بيانات هنا .</translation>
+ </message>
+</context>
<context>
<name>HelpMessageDialog</name>
- </context>
+ <message>
+ <source>version</source>
+ <translation>النسخة</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation>حوالي %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>خيارات سطر الأوامر</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
+ <message>
+ <source>Welcome</source>
+ <translation>أهلا</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation> اهلا بكم في %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>بما انه هذه اول مرة لانطلاق هذا البرنامج, فيمكنك ان تختار اين سيخزن %1 بياناته</translation>
+ </message>
+ <message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>عند النقر على "موافق" ، سيبدأ %1 في تنزيل ومعالجة سلسلة الكتل %4 الكاملة (%2 جيجابايت) بدءًا من المعاملات الأقدم في %3 عند تشغيل %4 في البداية.</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>
+ <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>إذا كنت قد اخترت تقييد تخزين سلسلة الكتل (التجريد)، فيجب تحميل البيانات القديمة ومعالجتها، ولكن سيتم حذفها بعد ذلك للحفاظ على انخفاض استخدام القرص.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>استخدام دليل البانات الافتراضي</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>استخدام دليل بيانات مخصص:</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>بتكوين</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>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>سيتم تخزين %1 جيجابايت تقريباً من البيانات في هذا الدليل.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>سيقوم %1 بتنزيل نسخة من سلسلة كتل بتكوين وتخزينها.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <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>
</context>
<context>
<name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation>نمودج</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>قد لا تكون المعاملات الأخيرة مرئية بعد، وبالتالي قد يكون رصيد محفظتك غير صحيح. ستكون هذه المعلومات صحيحة بمجرد الانتهاء من محفظتك مع شبكة البيتكوين، كما هو مفصل أدناه.</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>لن تقبل الشبكة محاولة إنفاق البتكوين المتأثرة بالمعاملات التي لم يتم عرضها بعد.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>عدد الكتل الفاضلة</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>غير معرف</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>اخر وقت الكتلة</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation>تقدم</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>تقدم يزيد بلساعة</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>تحسب الان...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>الوقت المتبقي للمزامنة</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>إخفاء</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
- </context>
+ <message>
+ <source>URI:</source>
+ <translation>العنوان:</translation>
+ </message>
+</context>
<context>
<name>OpenWalletActivity</name>
<message>
@@ -139,6 +980,70 @@
<context>
<name>OptionsDialog</name>
<message>
+ <source>Options</source>
+ <translation>خيارات ...</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation>&amp;الرئيسي</translation>
+ </message>
+ <message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>ابدأ تلقائيًا %1 بعد تسجيل الدخول إلى النظام.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>تشغيل %1 عند الدخول إلى النظام</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>حجم ذاكرة التخزين المؤقت لقاعدة البيانات</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <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>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>استخدام وكيل SOCKS5 منفصل للوصول إلى الأقران عبر خدمات Tor المخفية:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>إخفاء الآيقونة من صينية النظام.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>اخفاء آيقونة الصينية</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>التصغير بدلاً من الخروج من التطبيق عند إغلاق النافذة. عند تفعيل هذا الخيار، سيتم إغلاق التطبيق فقط بعد اختيار الخروج من القائمة.</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>فتح ملف الإعدادات %1 من الدليل العامل.</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>فتح ملف الإعدادات</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>إعادة تعيين كل إعدادات العميل للحالة الإفتراضية.</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation>&amp;استعادة الخيارات</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation>&amp;الشبكة</translation>
+ </message>
+ <message>
<source>GB</source>
<translation>جب</translation>
</message>
@@ -146,19 +1051,351 @@
<source>MiB</source>
<translation>ميجا بايت</translation>
</message>
- </context>
+ <message>
+ <source>W&amp;allet</source>
+ <translation>&amp;محفظة</translation>
+ </message>
+ <message>
+ <source>Expert</source>
+ <translation>تصدير</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation>تفعيل ميزات التحكم في العملة</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation>دفع الفكة غير المؤكدة</translation>
+ </message>
+ <message>
+ <source>Map port using &amp;UPnP</source>
+ <translation>ربط المنفذ باستخدام UPnP</translation>
+ </message>
+ <message>
+ <source>Accept connections from outside.</source>
+ <translation>قبول الاتصالات من الخارج.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>السماح بالاتصالات الواردة.</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation>الاتصال بشبكة البتكوين عبر وكيل SOCKS5.</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>الاتصال من خلال وكيل SOCKS5 (الوكيل الافتراضي):</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation>بروكسي &amp;اي بي:</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation>&amp;المنفذ:</translation>
+ </message>
+ <message>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation>منفذ البروكسي (مثلا 9050)</translation>
+ </message>
+ <message>
+ <source>Used for reaching peers via:</source>
+ <translation>مستخدم للاتصال بالاصدقاء من خلال:</translation>
+ </message>
+ <message>
+ <source>IPv4</source>
+ <translation>IPv4</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <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>
+ <message>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation>إظهار آيقونة الصينية فقط بعد تصغير النافذة.</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize to the tray instead of the taskbar</source>
+ <translation>التصغير إلى صينية النظام بدلاً من شريط المهام</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation>تصغير عند الإغلاق</translation>
+ </message>
+ <message>
+ <source>&amp;Display</source>
+ <translation>&amp;عرض</translation>
+ </message>
+ <message>
+ <source>User Interface &amp;language:</source>
+ <translation>واجهة المستخدم &amp;اللغة:</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation>الوحدة لإظهار المبالغ فيها:</translation>
+ </message>
+ <message>
+ <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
+ <translation>اختر وحدة التقسيم الفرعية الافتراضية للعرض في الواجهة وعند إرسال العملات.</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>ما اذا أردت إظهار ميزات التحكم في العملة أم لا.</translation>
+ </message>
+ <message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>العناوين (URL) لجهات خارجية</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>تم</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>الغاء</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation>الافتراضي</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation>لا شيء</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <translation>تأكيد استعادة الخيارات</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>يتطلب إعادة تشغيل العميل لتفعيل التغييرات.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>سوف يتم إيقاف العميل تماماً. هل تريد الإستمرار؟</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>إعداد الخيارات</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>خطأ</translation>
+ </message>
+ <message>
+ <source>The configuration file could not be opened.</source>
+ <translation>لم تتمكن من فتح ملف الإعدادات.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>هذا التغيير يتطلب إعادة تشغيل العميل بشكل كامل.</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>عنوان الوكيل توفيره غير صالح.</translation>
+ </message>
+</context>
<context>
<name>OverviewPage</name>
- </context>
+ <message>
+ <source>Form</source>
+ <translation>نمودج</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>قد تكون المعلومات المعروضة قديمة. تتزامن محفظتك تلقائيًا مع شبكة البتكوين بعد إنشاء الاتصال، ولكن هذه العملية لم تكتمل بعد.</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>مشاهدة فقط:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>متوفر</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>رصيدك القابل للصرف</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>معلق:</translation>
+ </message>
+ <message>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation>إجمالي المعاملات التي لم يتم تأكيدها بعد ولا تحتسب ضمن الرصيد القابل للانفاق</translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation>غير ناضجة</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>الرصيد المعدّن الذي لم ينضج بعد</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>الأرصدة</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>المجموع:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation>رصيدك الكلي الحالي</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>رصيدك الحالي في العناوين المشاهدة فقط</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>قابل للصرف:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>أحدث المعاملات</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>معاملات غير مؤكدة للعناوين المشاهدة فقط</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation>الرصيد المعدّن في العناوين المشاهدة فقط التي لم تنضج بعد</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation>الرصيد الإجمالي الحالي في العناوين المشاهدة فقط</translation>
+ </message>
+</context>
<context>
<name>PaymentServer</name>
- </context>
+ <message>
+ <source>Payment request error</source>
+ <translation>خطأ في طلب الدفع</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>لا يمكن تشغيل بتكوين: معالج النقر للدفع</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>التعامل مع العنوان</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <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)! يمكن أن يحدث هذا بسبب عنوان بتكوين غير صالح أو معلمات عنوان (URI) غير صحيحة.</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>التعامل مع ملف طلب الدفع</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
- </context>
+ <message>
+ <source>User Agent</source>
+ <translation>وكيل المستخدم</translation>
+ </message>
+ <message>
+ <source>Node/Service</source>
+ <translation>عقدة/خدمة</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>رقم العقدة</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>رنين</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>تم الإرسال</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>إستقبل</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
+ <source>Amount</source>
+ <translation>مبلغ</translation>
+ </message>
+ <message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>ادخل عنوان محفطة البتكوين (مثال %1)</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation>%1 يوم</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 ساعة</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 دقيقة</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 ثانية</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>لا شيء</translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation>غير معروف</translation>
+ </message>
+ <message>
+ <source>%1 ms</source>
+ <translation>%1 جزء من الثانية</translation>
+ </message>
+ <message>
+ <source>%1 and %2</source>
+ <translation>%1 و %2</translation>
+ </message>
+ <message>
+ <source>%1 B</source>
+ <translation>%1 بايت</translation>
+ </message>
+ <message>
+ <source>%1 KB</source>
+ <translation>%1 كيلو بايت</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation>%1 ميقا بايت</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation>%1 قيقا بايت</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>خطأ: دليل البيانات المحدد "%1" غير موجود.</translation>
</message>
@@ -166,10 +1403,26 @@
<source>Error: %1</source>
<translation>خطأ: %1</translation>
</message>
- </context>
+ <message>
+ <source>%1 didn't yet exit safely...</source>
+ <translation>%1 لم يخرج بعد بأمان...</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>غير معروف</translation>
+ </message>
+</context>
<context>
<name>QRImageWidget</name>
<message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;حفظ الصورة</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;نسخ الصورة</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>العنوان المستخدم طويل جدًا، حاول أن تقوم بتقليل نص التسمية / الرسالة.</translation>
</message>
@@ -177,73 +1430,1406 @@
<source>Error encoding URI into QR Code.</source>
<translation>خطأ في ترميز العنوان إلى الرمز المربع.</translation>
</message>
- </context>
+ <message>
+ <source>Save QR Code</source>
+ <translation>حفظ رمز الاستجابة السريعة QR</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>صورة PNG (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
- </context>
+ <message>
+ <source>N/A</source>
+ <translation>غير معروف</translation>
+ </message>
+ <message>
+ <source>Client version</source>
+ <translation>نسخه العميل</translation>
+ </message>
+ <message>
+ <source>&amp;Information</source>
+ <translation>المعلومات</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>عام</translation>
+ </message>
+ <message>
+ <source>Using BerkeleyDB version</source>
+ <translation>باستخدام BerkeleyDB إصدار</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation>دليل البيانات</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation>وقت البدء</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>الشبكه</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>الاسم</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation>عدد الاتصالات</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation>سلسلة الكتل</translation>
+ </message>
+ <message>
+ <source>Current number of blocks</source>
+ <translation>عدد الكتل الحالي</translation>
+ </message>
+ <message>
+ <source>Memory Pool</source>
+ <translation>تجمع الذاكرة</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>عدد المعاملات الحالي</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>استخدام الذاكرة</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>إعادة تعيين</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>إستقبل</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>تم الإرسال</translation>
+ </message>
+ <message>
+ <source>&amp;Peers</source>
+ <translation>&amp;اصدقاء</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation>الأقران الممنوعين</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation>حدد نظير لعرض معلومات مفصلة.</translation>
+ </message>
+ <message>
+ <source>Whitelisted</source>
+ <translation>اللائحة البيضاء</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>جهة</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>الإصدار</translation>
+ </message>
+ <message>
+ <source>Starting Block</source>
+ <translation>كتلة البداية</translation>
+ </message>
+ <message>
+ <source>Synced Headers</source>
+ <translation>رؤوس متزامنة</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>كتل متزامنة</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>وكيل المستخدم</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation>تصغير حجم الخط</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>تكبير حجم الخط</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>خدمات</translation>
+ </message>
+ <message>
+ <source>Ban Score</source>
+ <translation>نقاط الحظر</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation>مدة الاتصال</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation>آخر استقبال</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation>آخر إرسال</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation>وقت الرنين</translation>
+ </message>
+ <message>
+ <source>The duration of a currently outstanding ping.</source>
+ <translation>مدة الرنين المعلقة حالياً.</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>انتظار الرنين</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>أقل رنين</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation>إزاحة الوقت</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>اخر وقت الكتلة</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation>الفتح</translation>
+ </message>
+ <message>
+ <source>&amp;Console</source>
+ <translation>وحدة التحكم</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation>&amp;حركة مرور الشبكة</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation>المجاميع</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation>داخل:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>خارج:</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation>تصحيح ملف السجل</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation>مسح وحدة التحكم</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;ساعة</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp; يوم</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp; اسبوع</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp; سنة</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>قطع الاتصال</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>حظر ل</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>رفع الحظر</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>مرحبًا بك في وحدة التحكم %1 RPC.</translation>
+ </message>
+ <message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>استخدم السهمين لأعلى ولأسفل لتصفح السجل، و%1 لمسح الشاشة.</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>اكتب %1 للحصول على نظرة عامة على الأوامر المتوفرة.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>لمزيد من المعلومات حول استخدام نوع وحدة التحكم هذه اكتب %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>تحذير: المخادعون نشطون، ويطلبون من المستخدمين كتابة الأوامر هنا، من أجل سرقة محتويات محفظتهم. لا تستخدم وحدة التحكم هذه بدون فهم تبعات الأمر بشكل كامل.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>تم تعطيل نشاط الشبكة</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(معرف العقدة: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>خلال %1</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>ابدا</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>داخل</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>خارجي</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation>نعم</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation>لا</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>غير معرف</translation>
+ </message>
+</context>
<context>
<name>ReceiveCoinsDialog</name>
- </context>
+ <message>
+ <source>&amp;Amount:</source>
+ <translation>&amp;القيمة</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;وصف :</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation>&amp;رسالة:</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>رسالة اختيارية لإرفاقها بطلب الدفع، والتي سيتم عرضها عند فتح الطلب. ملاحظة: لن يتم إرسال الرسالة مع الدفعة عبر شبكة البتكوين.</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation>تسمية اختيارية لربطها بعنوان المستلم الجديد.</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation>استخدم هذا النموذج لطلب الدفعات. جميع الحقول &lt;b&gt;اختيارية&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
+ <translation>مبلغ اختياري للطلب. اترك هذا فارغًا أو صفراً لعدم طلب مبلغ محدد.</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>مسح كل حقول النموذج المطلوبة</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>مسح</translation>
+ </message>
+ <message>
+ <source>Requested payments history</source>
+ <translation>سجل طلبات الدفع</translation>
+ </message>
+ <message>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation>إظهار الطلب المحدد (يقوم بنفس نتيجة النقر المزدوج على أي إدخال)</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>عرض</translation>
+ </message>
+ <message>
+ <source>Remove the selected entries from the list</source>
+ <translation>قم بإزالة الإدخالات المحددة من القائمة</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>ازل</translation>
+ </message>
+ <message>
+ <source>Copy URI</source>
+ <translation>نسخ العنوان</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation> انسخ التسمية</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>انسخ الرسالة</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>نسخ الكمية</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
- </context>
+ <message>
+ <source>QR Code</source>
+ <translation>رمز كيو ار</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation>نسخ &amp;URI</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Address</source>
+ <translation>نسخ &amp;العنوان</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;حفظ الصورة</translation>
+ </message>
+ <message>
+ <source>Request payment to %1</source>
+ <translation>طلب الدفعة إلى %1</translation>
+ </message>
+ <message>
+ <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>
- </context>
+ <message>
+ <source>Date</source>
+ <translation>التاريخ</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>وسم</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>رسالة </translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(بدون وسم)</translation>
+ </message>
+ <message>
+ <source>(no message)</source>
+ <translation>( لا رسائل )</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(لا يوجد مبلغ مطلوب)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>تم الطلب</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
- </context>
+ <message>
+ <source>Send Coins</source>
+ <translation>إرسال العملات</translation>
+ </message>
+ <message>
+ <source>Coin Control Features</source>
+ <translation>ميزات التحكم بالعملة</translation>
+ </message>
+ <message>
+ <source>Inputs...</source>
+ <translation>المدخلات...</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>اختيار تلقائيا</translation>
+ </message>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation>الرصيد غير كافي!</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>الكمية:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>بايت</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>القيمة :</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>الرسوم:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>بعد الرسوم :</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>تعديل :</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>إذا تم تنشيط هذا، ولكن عنوان الفكة فارغ أو غير صالح، فسيتم إرسال الفكة إلى عنوان تم إنشاؤه حديثًا.</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation>تغيير عنوان الفكة</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation>رسوم المعاملة:</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>إختر …</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>تحذير: تقدير الرسوم غير ممكن في الوقت الحالي.</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>لكل كيلوبايت</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>إخفاء</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>موصى به:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>تخصيص:</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(الرسوم الذكية لم يتم تهيئتها بعد. عادة ما يستغرق ذلك بضع كتل ...)</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation>إرسال إلى عدة مستلمين في وقت واحد</translation>
+ </message>
+ <message>
+ <source>Add &amp;Recipient</source>
+ <translation>أضافة &amp;مستلم</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>مسح كل حقول النموذج المطلوبة</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>غبار:</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>هدف وقت التأكيد:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>تفعيل الإستبدال بواسطة الرسوم</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>مع الإستبدال بواسطة الرسوم (BIP-125) يمكنك زيادة رسوم المعاملة بعد إرسالها. وبدون ذلك، قد نوصي برسوم أعلى للتعويض عن مخاطر تأخير المعاملة المتزايدة.</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>مسح الكل</translation>
+ </message>
+ <message>
+ <source>Balance:</source>
+ <translation>الرصيد:</translation>
+ </message>
+ <message>
+ <source>Confirm the send action</source>
+ <translation>تأكيد الإرسال</translation>
+ </message>
+ <message>
+ <source>S&amp;end</source>
+ <translation>&amp;ارسال</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>نسخ الكمية </translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>نسخ الكمية</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>نسخ الرسوم</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>نسخ بعد الرسوم</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>نسخ البايتات </translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>نسخ الغبار</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>نسخ التعديل</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 كثلة)</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 الى %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>هل أنت متأكد من أنك تريد أن ترسل؟</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>أو</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>يمكنك زيادة الرسوم لاحقًا (بإشارة الإستبدال بواسطة الرسوم، BIP-125).</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>رسوم المعاملة</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>لا يشير إلى الإستبدال بواسطة الرسوم، BIP-125.</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>تأكيد الإرسال Coins</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>عنوان المستلم غير صالح. يرجى إعادة الفحص.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>المبلغ المدفوع يجب ان يكون اكبر من 0</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>القيمة تتجاوز رصيدك</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>المجموع يتجاوز رصيدك عندما يتم اضافة %1 رسوم العملية</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>تم العثور على عنوان مكرر: يجب استخدام العناوين مرة واحدة فقط.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>فشل في إنشاء المعاملة!</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>تعتبر الرسوم الأعلى من %1 رسوماً باهظة.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>انتهاء صلاحية طلب الدفع.</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>تحذير: عنوان بتكوين غير صالح</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>تحذير: عنوان الفكة غير معروف</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation>تأكيد تغيير العنوان الفكة</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(بدون وسم)</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
+ <message>
+ <source>A&amp;mount:</source>
+ <translation>&amp;القيمة</translation>
+ </message>
+ <message>
+ <source>Pay &amp;To:</source>
+ <translation>ادفع &amp;الى :</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;وصف :</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>اختر عنوانا مستخدم سابقا</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>عنوان البت كوين المرسل اليه الدفع</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>انسخ العنوان من لوحة المفاتيح</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Remove this entry</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>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>طرح الرسوم من المبلغ</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>استخدام الرصيد المتاح</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>الرسائل</translation>
+ </message>
+ <message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>هذا طلب دفع لم يتم مصادقته.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>هذا طلب دفع تمت مصادقته.</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <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>
+ <translation>الرسالة التي تم إرفاقها مع البتكوين: العنوان الذي سيتم تخزينه مع المعاملة للرجوع إليه. ملاحظة: لن يتم إرسال هذه الرسالة عبر شبكة البتكوين.</translation>
+ </message>
+ <message>
+ <source>Pay To:</source>
+ <translation>ادفع &amp;الى :</translation>
+ </message>
+ <message>
+ <source>Memo:</source>
+ <translation>مذكرة:</translation>
+ </message>
+</context>
<context>
<name>ShutdownWindow</name>
- </context>
+ <message>
+ <source>%1 is shutting down...</source>
+ <translation>اتمام إيقاف %1...</translation>
+ </message>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation>لا توقف عمل الكمبيوتر حتى تختفي هذه النافذة</translation>
+ </message>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
- </context>
+ <message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>التواقيع - التوقيع / التحقق من الرسالة</translation>
+ </message>
+ <message>
+ <source>&amp;Sign Message</source>
+ <translation>&amp;توقيع الرسالة</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation>عنوان البتكوين لتوقيع الرسالة به</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>اختر عنوانا مستخدم سابقا</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>انسخ العنوان من لوحة المفاتيح</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Enter the message you want to sign here</source>
+ <translation>ادخل الرسالة التي تريد توقيعها هنا</translation>
+ </message>
+ <message>
+ <source>Signature</source>
+ <translation>التوقيع</translation>
+ </message>
+ <message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>نسخ التوقيع الحالي إلى حافظة النظام</translation>
+ </message>
+ <message>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation>وقع الرسالة لتثبت انك تمتلك عنوان البت كوين هذا</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation>توقيع $الرسالة</translation>
+ </message>
+ <message>
+ <source>Reset all sign message fields</source>
+ <translation>إعادة تعيين كافة حقول رسالة التوقيع</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>مسح الكل</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation>&amp;تحقق رسالة</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation>عنوان البتكوين الذي تم توقيع الرسالة به</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>تحقق من الرسالة للتأكد من توقيعها مع عنوان البتكوين المحدد</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation>تحقق &amp;الرسالة</translation>
+ </message>
+ <message>
+ <source>Reset all verify message fields</source>
+ <translation>إعادة تعيين جميع حقول التحقق من الرسالة</translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>اضغط "توقيع الرسالة" لتوليد التوقيع</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>العنوان المدخل غير صالح</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>الرجاء التأكد من العنوان والمحاولة مرة اخرى</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>العنوان المدخل لا يشير الى مفتاح</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>تم الغاء عملية فتح المحفظة</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>المفتاح الخاص للعنوان المدخل غير موجود.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>فشل توقيع الرسالة.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>الرسالة موقعة.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>لا يمكن فك تشفير التوقيع.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>فضلا تاكد من التوقيع وحاول مرة اخرى</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>لم يتطابق التوقيع مع ملخص الرسالة.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>فشلت عملية التأكد من الرسالة.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>تم تأكيد الرسالة.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
- </context>
+ <message>
+ <source>KB/s</source>
+ <translation>كيلوبايت/ث</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
- </context>
+ <message>
+ <source>Open until %1</source>
+ <translation>مفتوح حتى %1</translation>
+ </message>
+ <message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>تعارضت مع معاملة لديها %1 تأكيدات</translation>
+ </message>
+ <message>
+ <source>in memory pool</source>
+ <translation>في تجمع الذاكرة</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>ليس في تجمع الذاكرة</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>مهجور</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>غير مؤكدة/%1</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>تأكيد %1</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>الحالة.</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>التاريخ</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>المصدر</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>تم اصداره.</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>من</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>غير معروف</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>الى</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>عنوانه</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>مشاهدة فقط</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>علامة</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>رصيد</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>غير مقبولة</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>دين</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>إجمالي الخصم</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>إجمالي الرصيد</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>رسوم المعاملة</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation>صافي المبلغ</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>رسالة </translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>تعليق</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>رقم المعاملة</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation>الحجم الكلي للمعاملات</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>مؤشر المخرجات</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>تاجر</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>معلومات التصحيح</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>معاملة</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>المدخلات</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>مبلغ</translation>
+ </message>
+ <message>
+ <source>true</source>
+ <translation>صحيح</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>خاطئ</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
- </context>
+ <message>
+ <source>This pane shows a detailed description of the transaction</source>
+ <translation>يبين هذا الجزء وصفا مفصلا لهده المعاملة</translation>
+ </message>
+ <message>
+ <source>Details for %1</source>
+ <translation>تفاصيل عن %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
- </context>
+ <message>
+ <source>Date</source>
+ <translation>التاريخ</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>النوع</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>وسم</translation>
+ </message>
+ <message>
+ <source>Open until %1</source>
+ <translation>مفتوح حتى %1</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>غير مؤكد</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation>مهجور</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>قيد التأكيد (%1 من %2 تأكيد موصى به)</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>مؤكد (%1 تأكيدات)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation>يتعارض</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>غير ناضجة (تأكيدات %1 ، ستكون متوفرة بعد %2)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>ولدت ولكن لم تقبل</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>استقبل مع</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>استقبل من</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>أرسل إلى</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>دفع لنفسك</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Mined</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>مشاهدة فقط</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>غير متوفر</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(بدون وسم)</translation>
+ </message>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>حالة التحويل. مرر فوق هذا الحقل لعرض عدد التأكيدات.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>التاريخ والوقت الذي تم فيه تلقي المعاملة.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>نوع المعاملات</translation>
+ </message>
+ <message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>ما إذا كان العنوان المشاهدة فقط متضمنًا في هذه المعاملة أم لا.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>المبلغ الذي أزيل أو أضيف الى الرصيد</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>الكل</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>اليوم</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>هدا الاسبوع</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>هدا الشهر</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>الشهر الماضي</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>هدا العام</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>المدى...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>استقبل مع</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>أرسل إلى</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>إليك</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Mined</translation>
+ </message>
+ <message>
<source>Other</source>
<translation>أخرى</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>أدخل العنوان أو معرف المعاملة أو التصنيف للبحث</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>الحد الأدنى</translation>
+ </message>
+ <message>
+ <source>Abandon transaction</source>
+ <translation>التخلي عن المعاملة</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>زيادة رسوم المعاملة</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>نسخ العنوان</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation> انسخ التسمية</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>نسخ الكمية</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>نسخ رقم العملية</translation>
+ </message>
+ <message>
+ <source>Copy raw transaction</source>
+ <translation>نسخ المعاملة الخام</translation>
+ </message>
+ <message>
+ <source>Copy full transaction details</source>
+ <translation>نسخ كامل تفاصيل المعاملة</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>عدل الوصف</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>عرض تفاصيل المعاملة</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>تصدير تفاصيل المعاملات</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>ملف مفصول بفاصلة (*.csv)</translation>
</message>
<message>
+ <source>Confirmed</source>
+ <translation>تأكيد</translation>
+ </message>
+ <message>
+ <source>Watch-only</source>
+ <translation>مشاهدة فقط</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>التاريخ</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>النوع</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>وسم</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>عنوان</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>العنوان</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>لقد فشل التصدير</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>حدث خطأ أثناء محاولة حفظ محفوظات المعاملة إلى %1.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>نجح التصدير</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>تم حفظ محفوظات المعاملة بنجاح إلى %1.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>المدى:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>إلى</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
- </context>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation>الوحدة لإظهار المبالغ فيها. انقر لتحديد وحدة أخرى.</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation>اغلق المحفظة</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>لا يوجد محفظة تم تحميلها.</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
- </context>
+ <message>
+ <source>Send Coins</source>
+ <translation>إرسال العملات</translation>
+ </message>
+ <message>
+ <source>Fee bump error</source>
+ <translation>خطأ في زيادة الرسوم</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>فشل في زيادة رسوم المعاملة</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>هل تريد زيادة الرسوم؟</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>الأجر الحالي:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>زيادة:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>أجر جديد:</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation>تأكيد زيادة الرسوم</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>لا يمكن توقيع المعاملة.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>لا يمكن تنفيذ المعاملة</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>المحفظة إفتراضية</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
@@ -254,8 +2840,289 @@
<source>Export the data in the current tab to a file</source>
<translation>استخراج البيانات في علامة التبويب الحالية إلى ملف</translation>
</message>
- </context>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>نسخ احتياط للمحفظة</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>بيانات المحفظة (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>فشل النسخ الاحتياطي</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>نجاح النسخ الاحتياطي</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>تم حفظ بيانات المحفظة بنجاح إلى %1.</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>إلغاء</translation>
+ </message>
+</context>
<context>
<name>bitcoin-core</name>
- </context>
+ <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>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>غير قادر على بدء خادم ال HTTP. راجع سجل تصحيح الأخطاء للحصول على التفاصيل.</translation>
+ </message>
+ <message>
+ <source>The %s developers</source>
+ <translation>%s المبرمجون</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>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <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>
+ <message>
+ <source>Change index out of range</source>
+ <translation>فهرس الفكة خارج النطاق</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>حقوق الطبع والنشر (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation>تم الكشف عن قاعدة بيانات كتل تالفة</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>هل تريد إعادة بناء قاعدة بيانات الكتل الآن؟</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>خطأ في تحميل %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>خطأ في تحميل %s: لا يمكن تعطيل المفاتيح الخاصة إلا أثناء الإنشاء.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>خطأ في التحميل %s: المحفظة تالفة.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>خطا تحميل %s: المحفظة تتطلب النسخة الجديدة من %s.</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation>خطأ في تحميل قاعدة بيانات الكتل</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation>خطأ في فتح قاعدة بيانات الكتل</translation>
+ </message>
+ <message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation>فشل في الاستماع على أي منفذ. استخدام الاستماع = 0 إذا كنت تريد هذا.</translation>
+ </message>
+ <message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>فشل في اعادة مسح المحفظة خلال عملية التهيئة.</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>إستيراد...</translation>
+ </message>
+ <message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation>لم يتم العثور على كتلة تكوين أو لم تكون صحيحة. datadir خاطئة للشبكة؟</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>فشل بالتحقق في اختبار التعقل. تم إيقاف %s.</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>تحميل عناوين P2P...</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>جاري تحميل قائمة الحظر...</translation>
+ </message>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation>لا تتوفر واصفات ملفات كافية.</translation>
+ </message>
+ <message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation>لا يمكن تهيئة التجريد بقيمة سالبة.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation>وضع التجريد غير متوافق مع -txindex.</translation>
+ </message>
+ <message>
+ <source>Replaying blocks...</source>
+ <translation>إعادة لعب الكتل...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>العودة بالكتل...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation>شفرة المصدر متاحة من %s.</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation> غير قادر على توليد مفاتيح.</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>ترقية قاعدة بيانات UTXO</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>التحقق من الكتل...</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>يلزم إعادة كتابة المحفظة: إعادة تشغيل %s لإكمال العملية</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</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>Error reading from database, shutting down.</source>
+ <translation>خطأ في القراءة من قاعدة البيانات ، والتوقف.</translation>
+ </message>
+ <message>
+ <source>Error upgrading chainstate database</source>
+ <translation>خطأ في ترقية قاعدة بيانات chainstate</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation>فشل توقيع المعاملة</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation>قيمة المعاملة صغيرة جدا لدفع الأجر</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>هذا برنامج تجريبي.</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>قيمة العملية صغيره جدا</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>المعاملة كبيرة جدا</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation>يتعذر الربط مع %s على هذا الكمبيوتر (الربط انتج خطأ %s)</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation>غير قادر على توليد مفاتيح أولية</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <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>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>بدء مؤشرات شبكة الاتصال...</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>سوف تتجنب المحفظة دفع أقل من الحد الأدنى لرسوم التتابع.</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>هذه هي اقل قيمة من العمولة التي تدفعها عند كل عملية تحويل للأموال.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>يجب ألا تكون قيمة المعاملة سلبية</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>المعاملات طويلة جداً على حجم سلسلة الذاكرة </translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>يجب أن تحتوي المعاملة على مستلم واحد على الأقل</translation>
+ </message>
+ <message>
+ <source>Insufficient funds</source>
+ <translation>الرصيد غير كافي</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>لايمكن الكتابة على دليل البيانات '%s'؛ تحقق من السماحيات.</translation>
+ </message>
+ <message>
+ <source>Loading block index...</source>
+ <translation>تحميل مؤشر الكتلة</translation>
+ </message>
+ <message>
+ <source>Loading wallet...</source>
+ <translation>تحميل المحفظة...</translation>
+ </message>
+ <message>
+ <source>Cannot downgrade wallet</source>
+ <translation>لايمكن تنزيل نسخة محفظة أقل</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>إعادة المسح...</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation>إنتهاء التحميل</translation>
+ </message>
+</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_be_BY.ts b/src/qt/locale/bitcoin_be.ts
index ab80936a59..bb0c17901f 100644
--- a/src/qt/locale/bitcoin_be_BY.ts
+++ b/src/qt/locale/bitcoin_be.ts
@@ -1,4 +1,4 @@
-<TS language="be_BY" version="2.1">
+<TS language="be" version="2.1">
<context>
<name>AddressBookPage</name>
<message>
@@ -70,10 +70,6 @@
<translation>Тут знаходзяцца Біткойн-адрасы для высылання плацяжоў. Заўсёды спраўджвайце колькасць і адрас прызначэння перад здзяйсненнем транзакцыі.</translation>
</message>
<message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Тут знаходзяцца Біткойн-адрасы для прымання плацяжоў. Пажадана выкарыстоўваць новы адрас для кожнай транзакцыі.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>Капіяваць адрас</translation>
</message>
@@ -136,10 +132,6 @@
<translation>Паўтарыце новую кодавую фразу</translation>
</message>
<message>
- <source>Enter the new passphrase to 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>
- </message>
- <message>
<source>Encrypt wallet</source>
<translation>Зашыфраваць гаманец.</translation>
</message>
@@ -164,10 +156,6 @@
<translation>Змяніць пароль</translation>
</message>
<message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Увядзіце стары пароль і новы пароль для гаманца.</translation>
- </message>
- <message>
<source>Confirm wallet encryption</source>
<translation>Пацвердзіце шыфраванне гаманца</translation>
</message>
@@ -238,10 +226,6 @@
<translation>Агляд</translation>
</message>
<message>
- <source>Node</source>
- <translation>Вузел</translation>
- </message>
- <message>
<source>Show general overview of wallet</source>
<translation>Паказвае агульныя звесткі аб гаманцы</translation>
</message>
@@ -286,14 +270,6 @@
<translation>&amp;Change Passphrase...</translation>
</message>
<message>
- <source>&amp;Sending addresses...</source>
- <translation>Адрасы дасылання...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Адрасы прымання...</translation>
- </message>
- <message>
<source>Open &amp;URI...</source>
<translation>Адчыниць &amp;URI...</translation>
</message>
@@ -314,26 +290,10 @@
<translation>Змяніць пароль шыфравання гаманца</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Вакно адладкі</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Адкрыць кансоль дыягностыкі і адладкі</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>Праверыць паведамленне...</translation>
</message>
<message>
- <source>Bitcoin</source>
- <translation>Біткойн</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Гаманец</translation>
- </message>
- <message>
<source>&amp;Send</source>
<translation>Даслаць</translation>
</message>
@@ -386,10 +346,6 @@
<translation>Паказаць спіс адрасоў і метак для прымання</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Адкрыць біткойн: URI ці запыт плацяжу</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Опцыі каманднага радка</translation>
</message>
@@ -592,6 +548,12 @@
</message>
</context>
<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
+ </context>
+<context>
<name>EditAddressDialog</name>
<message>
<source>Edit Address</source>
@@ -644,10 +606,6 @@
<context>
<name>HelpMessageDialog</name>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-біт)</translation>
- </message>
- <message>
<source>Command-line options</source>
<translation>Опцыі каманднага радка</translation>
</message>
@@ -676,10 +634,9 @@
</context>
<context>
<name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Адкрыць URI</translation>
- </message>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
</context>
<context>
<name>OptionsDialog</name>
@@ -688,10 +645,6 @@
<translation>Опцыі</translation>
</message>
<message>
- <source>MB</source>
- <translation>Мб</translation>
- </message>
- <message>
<source>W&amp;allet</source>
<translation>Гаманец</translation>
</message>
@@ -729,9 +682,6 @@
</message>
</context>
<context>
- <name>QObject::QObject</name>
- </context>
-<context>
<name>QRImageWidget</name>
</context>
<context>
@@ -740,10 +690,6 @@
<source>&amp;Information</source>
<translation>Інфармацыя</translation>
</message>
- <message>
- <source>Debug window</source>
- <translation>Вакно адладкі</translation>
- </message>
</context>
<context>
<name>ReceiveCoinsDialog</name>
@@ -790,7 +736,7 @@
<source>Wallet</source>
<translation>Гаманец</translation>
</message>
- </context>
+</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -931,15 +877,8 @@
<source>Memo:</source>
<translation>Памятка:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Увядзіце пазнаку гэтаму адрасу, каб дадаць яго ў адрасную кнігу</translation>
- </message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -958,13 +897,6 @@
</message>
</context>
<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
<name>TrafficGraphWidget</name>
<message>
<source>KB/s</source>
@@ -1203,6 +1135,9 @@
<name>UnitDisplayStatusBarControl</name>
</context>
<context>
+ <name>WalletController</name>
+ </context>
+<context>
<name>WalletFrame</name>
</context>
<context>
@@ -1226,10 +1161,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Ці жадаеце вы перабудаваць зараз базу звестак блокаў?</translation>
</message>
@@ -1250,10 +1181,6 @@
<translation>Памылка адчынення базы звестак блокаў</translation>
</message>
<message>
- <source>Error: Disk space is low!</source>
- <translation>Памылка: Замала вольнага месца на дыску!</translation>
- </message>
- <message>
<source>Importing...</source>
<translation>Імпартаванне...</translation>
</message>
@@ -1266,10 +1193,6 @@
<translation>Праверка блокаў...</translation>
</message>
<message>
- <source>Information</source>
- <translation>Інфармацыя</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Памылка подпісу транзакцыі</translation>
</message>
@@ -1286,10 +1209,6 @@
<translation>Транзакцыя занадта вялікая</translation>
</message>
<message>
- <source>Warning</source>
- <translation>Увага</translation>
- </message>
- <message>
<source>Insufficient funds</source>
<translation>Недастаткова сродкаў</translation>
</message>
@@ -1313,9 +1232,5 @@
<source>Done loading</source>
<translation>Загрузка выканана</translation>
</message>
- <message>
- <source>Error</source>
- <translation>Памылка</translation>
- </message>
</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts
new file mode 100644
index 0000000000..694c1b1008
--- /dev/null
+++ b/src/qt/locale/bitcoin_bg.ts
@@ -0,0 +1,2328 @@
+<TS language="bg" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>Клик с десен бутон на мишката за промяна на адрес или етикет</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>Създай нов адрес</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>Нов</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>Копирай текущо избрания адрес към клипборда</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;Copy</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>Затвори</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <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>
+ <message>
+ <source>&amp;Export</source>
+ <translation>Изнеси</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;Изтрий</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Избери адреса на който да пратиш монети</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Избери адреса на който да получиш монети</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>Избери</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Адрес за пращане</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <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>Копирай адрес</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Копирай етикет</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>Редактирай</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Изнеси лист с адреси</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Comma separated file (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Изнасянето се провали</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Получи се грешка при запазването на листа с адреси към %1. Моля опитайте пак.</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Етикет</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Адрес</translation>
+ </message>
+ <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>
+ <message>
+ <source>New passphrase</source>
+ <translation>Нова парола</translation>
+ </message>
+ <message>
+ <source>Repeat new 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>
+ <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>
+ <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>ВНИМАНИЕ: Ако шифрирате вашият портфейл и изгубите паролата си, &lt;b&gt;ЩЕ ИЗГУБИТЕ ВСИЧКИТЕ СИ БИТКОИНИ&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Наистина ли желаете да шифрирате портфейла си?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>портфейлa е шифрован</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>ВАЖНО: Всички стари запазвания, които сте направили на Вашият портфейл трябва да замените с запазване на новополучения, шифриран портфейл. От съображения за сигурност, предишните запазвания на нешифрирани портфейли ще станат неизползваеми веднага, щом започнете да използвате новият, шифриран портфейл.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Шифрирането беше неуспешно</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Шифрирането на портфейла беше неуспешно, поради софтуерен проблем. Портфейлът не е шифриран.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Паролите не съвпадат</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Отключването не бе успешно</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Паролата въведена за дешифриране на портфейла е грешна.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Отключването не бе успешно</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Паролата на портфейла беше променена успешно.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Внимание:Бутонът Caps Lock е включен.</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Мрежова маска</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Блокиран до</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>Подпиши съобщение...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>Синхронизиране с мрежата...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>Преглед</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>Покажи общ преглед на портфейла</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>Транзакции</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>Разгледай история на транзакциите</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>Изход</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>Излез от приложението</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>За %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Покажи информация за %1</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>Относно Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Покажи информация отностно Qt</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>Настройки...</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation>Промени конфигурации за %1</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>Криптирай портфейл</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>Направи резервно копие на портфейла...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>Промени паролата...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>Отвори URI</translation>
+ </message>
+ <message>
+ <source>Create Wallet...</source>
+ <translation>Създай портфейл...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Създай нов портфейл</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Портфейл</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Натиснете за деактивиране на мрежата</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Мрежата деактивирана</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Натиснете за повторно активиране на мрежата.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Синхронизиране на хедъри (%1%)</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Повторно индексиране на блоковете на диска...</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>Изпращане към Биткоин адрес</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>Запазване на портфейла на друго място</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>Променя паролата за портфейла</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;Проверка на съобщение...</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;изпращам</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;получавам</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Показване / Скриване</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Показване и скриване на основния прозорец</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Шифроване на личните ключове,които принадлежат на портфейла Ви.</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Пишете съобщения със своя Биткойн адрес за да докажете,че е ваш.</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Потвърждаване на съобщения за да се знае,че са написани с дадените Биткойн адреси.</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;Файл</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>&amp;Настройки</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>&amp;Помощ</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>Лентата с инструменти</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>Изискване на плащания(генерира QR кодове и биткойн: URIs)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Показване на списъка с използвани адреси и имена</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Покажи списък с използваните адреси и имена.</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>&amp;Налични команди</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Индексиране на блокове на диска...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Обработване на блокове на диска...</translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 зад</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Последния получен блок е генериран преди %1.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Транзакции след това няма все още да бъдат видими.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>грешка</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Внимание</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Информация</translation>
+ </message>
+ <message>
+ <source>Up to date</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>default wallet</source>
+ <translation>Портфейл по подразбиране</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;Прозорец</translation>
+ </message>
+ <message>
+ <source>Minimize</source>
+ <translation>Минимизирай</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 клиент</translation>
+ </message>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>Свързване с пиъри</translation>
+ </message>
+ <message>
+ <source>Catching up...</source>
+ <translation>Наваксвам</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Дата: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Сума: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Тип: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Етикет: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Адрес: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Изпратена транзакция</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>Входяща транзакция</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation>Портфейлът е &lt;b&gt;криптиран&lt;/b&gt; и &lt;b&gt;отключен&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation>Портфейлът е &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>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Coin Selection</source>
+ <translation>Избор на монети</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Количество:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Байтове:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Количество:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Такса:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>прах:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>След такса:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Промяна:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>(Пре)махни всички</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>Дървовиден режим</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>списък Режим</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Количество</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation>Получени с име</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Получени с адрес</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Дата</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation>потвърждения</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Потвърдено</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Копирайте адреса</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Копиране на етикета</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Копиране на сумата</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Копиране на ID на транзакцията</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Заключи неусвоени</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Отключете неизползваните</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Копиране на количеството</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Копирай такса</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Копирайте след такса</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Копиране на байтовете</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Копирай прахта:</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Промяна на копирането</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 заключен)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>да</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>не</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(без етикет)</translation>
+ </message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>ресто от %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(промени)</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation>Редактирайте адреса</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;Име</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation>Етикетът свързан с това въведение в листа с адреси</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>Адресът свързан с това въведение в листа с адреси. Това може да бъде променено само за адреси за изпращане.</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;Адрес</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>Нов адрес за изпращане</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Редактиране на получаващия адрес</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Редактиране на адрес за изпращане</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>"%1" не е валиден Биткоин адрес.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Не може да отключите портфейла.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Създаването на ключ беше неуспешно.</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation>Ще се създаде нова папка за данни.</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation>име</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Директорията вече съществува.Добавете %1 ако желаете да добавите нова директория тук.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>Пътят вече съществува и не е папка.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>Не може да се създаде директория тук.</translation>
+ </message>
+</context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation>версия</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation>Относно %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>Списък с команди</translation>
+ </message>
+</context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Welcome</source>
+ <translation>Добре дошли</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation>Добре дошли в %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>Програмата се стартира за първи път вие може да изберете къде %1 ще се запаметят данните.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>Използване на директория по подразбиране</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>Използване на директория ръчно</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Биткоин</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 GB данни ще бъдат запаметени в тази директория, и ще нарастват през времето.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>Около %1 GB данни ще бъдат запаметени в тази директория.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>грешка</translation>
+ </message>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation>форма</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Време на последния блок</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation>прогрес</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>изчисляване</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Скрий</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ <message>
+ <source>URI:</source>
+ <translation>URI:</translation>
+ </message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>default wallet</source>
+ <translation>Портфейл по подразбиране</translation>
+ </message>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>Options</source>
+ <translation>Настроики</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation>&amp;Основни</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Размер на кеша в &amp;базата данни</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation>Брой на скриптове и &amp;нишки за потвърждение</translation>
+ </message>
+ <message>
+ <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>Open Configuration File</source>
+ <translation>Отворете конфигурационния файл</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>Възстановете всички настройки по подразбиране.</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation>&amp;Нулирай настройките</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation>&amp;Мрежа</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>ГБ</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation>По&amp;ртфейл</translation>
+ </message>
+ <message>
+ <source>Expert</source>
+ <translation>Експерт</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation>Позволяване на монетите и &amp;техните възможности</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <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>
+ <translation>Автоматично отваряне на входящия Bitcoin порт. Работи само с рутери поддържащи UPnP.</translation>
+ </message>
+ <message>
+ <source>Map port using &amp;UPnP</source>
+ <translation>Отваряне на входящия порт чрез &amp;UPnP</translation>
+ </message>
+ <message>
+ <source>Accept connections from outside.</source>
+ <translation>Позволи външни връзки</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Позволи входящи връзки</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation>Свързване с Биткойн мрежата чрез SOCKS5 прокси.</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>&amp;Свързване чрез SOCKS5 прокси (прокси по подразбиране):</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation>Прокси &amp; АйПи:</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation>&amp;Порт:</translation>
+ </message>
+ <message>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation>Порт на прокси сървъра (пр. 9050)</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>Тор</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;Прозорец</translation>
+ </message>
+ <message>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation>След минимизиране ще е видима само иконата в системния трей.</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize to the tray instead of the taskbar</source>
+ <translation>&amp;Минимизиране в системния трей</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation>М&amp;инимизиране при затваряне</translation>
+ </message>
+ <message>
+ <source>&amp;Display</source>
+ <translation>&amp;Интерфейс</translation>
+ </message>
+ <message>
+ <source>User Interface &amp;language:</source>
+ <translation>Език:</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation>Мерна единица за показваните суми:</translation>
+ </message>
+ <message>
+ <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
+ <translation>Изберете единиците, показвани по подразбиране в интерфейса.</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>Дали да покаже възможностите за контрол на монетите или не.</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>ОК</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>Отказ</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation>подразбиране</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation>нищо</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <translation>Потвърдете опциите за нулиране</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>Изисква се рестартиране на клиента за активиране на извършените промени.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>Клиентът ще бъде изключен. Искате ли да продължите?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Опции за конфигуриране</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>грешка</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>Тази промяна изисква рестартиране на клиента Ви.</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>Текущият прокси адрес е невалиден.</translation>
+ </message>
+</context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Form</source>
+ <translation>форма</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>Текущата информация на екрана може да не е актуална. Вашият портфейл ще се синхронизира автоматично с мрежата на Биткоин, щом поне една връзката с нея се установи; този процес все още не е приключил.</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>Гледайте само:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>На разположение:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>Текущото Ви разходоносно салдо</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>В очакване на:</translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation>Незрялото:</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>Миниран баланс,който все още не се е развил</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>баланс</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>Обща сума:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation>Текущото Ви общо салдо</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>За харчене:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Последни транзакции</translation>
+ </message>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Възникна грешка по време назаявката за плащане</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Биткойн не можe да се стартира: click-to-pay handler</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>Справяне с URI</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Невалиден адрес на плащане %1</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>Файл за справяне със заявки</translation>
+ </message>
+</context>
+<context>
+ <name>PeerTableModel</name>
+ <message>
+ <source>User Agent</source>
+ <translation>Потребителски агент</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>пинг</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Изпратени</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Получени</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>Количество</translation>
+ </message>
+ <message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Въведете Биткойн адрес (например: %1)</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation>%1 ден</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 час</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 минута</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 секунда</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>нито един</translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation>Несъществуващ</translation>
+ </message>
+ <message>
+ <source>%1 ms</source>
+ <translation>%1 милисекунда</translation>
+ </message>
+ <message>
+ <source>%1 and %2</source>
+ <translation>%1 и %2</translation>
+ </message>
+ <message>
+ <source>%1 B</source>
+ <translation>%1 Байт</translation>
+ </message>
+ <message>
+ <source>%1 KB</source>
+ <translation>%1 Килобайт</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation>%1 Мегабайт</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation>%1 Гигабайт</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation>Грешка:Избраната "%1" директория не съществува.</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>неизвестен</translation>
+ </message>
+</context>
+<context>
+ <name>QRImageWidget</name>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Запиши изображение...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;Копирай изображение</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>Грешка при създаването на QR Code от URI.</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation>Запази QR Код</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>PNG Изображение (*.png)</translation>
+ </message>
+</context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>N/A</source>
+ <translation>Несъществуващ</translation>
+ </message>
+ <message>
+ <source>Client version</source>
+ <translation>Клиентска версия</translation>
+ </message>
+ <message>
+ <source>&amp;Information</source>
+ <translation>Данни</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>Общ</translation>
+ </message>
+ <message>
+ <source>Using BerkeleyDB version</source>
+ <translation>Използване на база данни BerkeleyDB </translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation>Време за стартиране</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>мрежа</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>име</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation>Брой връзки</translation>
+ </message>
+ <message>
+ <source>Current number of blocks</source>
+ <translation>Текущ брой блокове</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Получени</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Изпратени</translation>
+ </message>
+ <message>
+ <source>&amp;Peers</source>
+ <translation>&amp;Пиъри</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation>Избери пиър за детайлна информация.</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Посока</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>Версия</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>Потребителски агент</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>Услуги</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation>Продължителност на връзката</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation>Изпратени за последно</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation>Получени за последно</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation>Време за отговор</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Време на последния блок</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation>&amp;Отвори</translation>
+ </message>
+ <message>
+ <source>&amp;Console</source>
+ <translation>&amp;Конзола</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation>&amp;Мрежов Трафик</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation>Общо:</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation>Входящи:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>Изходящи</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation>Лог файл,съдържащ грешките</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation>Изчисти конзолата</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>посредством %1</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>Никога</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>Входящи</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>Изходящи</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation>Да</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation>Не</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>Неизвестен</translation>
+ </message>
+</context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Amount:</source>
+ <translation>&amp;Сума</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Име:</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation>&amp;Съобщение:</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation>Използвате този формуляр за заявяване на плащания. Всички полета са &lt;b&gt;незадължителни&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
+ <translation>Незадължително заявяване на сума. Оставете полето празно или нулево, за да не заявите конкретна сума.</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Изчисти всички полета от формуляра.</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>Изчистване</translation>
+ </message>
+ <message>
+ <source>Requested payments history</source>
+ <translation>Изискана история на плащанията</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>Показване</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Премахване</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Копиране на етикета</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Копиране на съобщението</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Копиране на сумата</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>
+ </message>
+ <message>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Копирай адрес</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Запиши изображение...</translation>
+ </message>
+ <message>
+ <source>Request payment to %1</source>
+ <translation>Изискване на плащане от %1</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Date</source>
+ <translation>Дата</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Етикет</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Съобщение</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(без етикет)</translation>
+ </message>
+ <message>
+ <source>(no message)</source>
+ <translation>(без съобщение)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>Изпращане</translation>
+ </message>
+ <message>
+ <source>Coin Control Features</source>
+ <translation>Настройки за контрол на монетите</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>астоматично избран</translation>
+ </message>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation>Нямате достатъчно налични пари!</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Количество:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Байтове:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Количество:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Такса:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>След такса:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Промяна:</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>Ако тази опция е активирана,но адресът на промяна е празен или невалиден,промяната ще бъде изпратена на новосъздаден адрес.</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation>Такса за транзакцията:</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>Избери...</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>за килобайт</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Скрий</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>Препоръчителна:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>По избор:</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation>Изпращане към повече от един получател</translation>
+ </message>
+ <message>
+ <source>Add &amp;Recipient</source>
+ <translation>Добави &amp;получател</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Изчисти всички полета от формуляра.</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>прах:</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>&amp;Изчисти</translation>
+ </message>
+ <message>
+ <source>Balance:</source>
+ <translation>Баланс:</translation>
+ </message>
+ <message>
+ <source>Confirm the send action</source>
+ <translation>Потвърдете изпращането</translation>
+ </message>
+ <message>
+ <source>S&amp;end</source>
+ <translation>И&amp;зпрати</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Копиране на количеството</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Копиране на сумата</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Копирай такса</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Копирайте след такса</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Копиране на байтовете</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Копирай прахта:</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Промяна на копирането</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Наистина ли искате да изпратите?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>или</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Такса</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Потвърждаване</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Сумата трябва да е по-голяма от 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Сумата надвишава текущия баланс</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>Сумата при добавяне на данък добавена стойност по %1 транзакцията надвишава сумата по вашата сметка.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Грешка при създаването на транзакция!</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Заявката за плащане е изтекла.</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Внимание: Невалиден Биткойн адрес</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Внимание:Неизвестен адрес за промяна</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(без етикет)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ <message>
+ <source>A&amp;mount:</source>
+ <translation>С&amp;ума:</translation>
+ </message>
+ <message>
+ <source>Pay &amp;To:</source>
+ <translation>Плати &amp;На:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Име:</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Изберете използван преди адрес</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Вмъкни от клипборда</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Remove this entry</source>
+ <translation>Премахване на този запис</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Съобщение:</translation>
+ </message>
+ <message>
+ <source>Pay To:</source>
+ <translation>Плащане на:</translation>
+ </message>
+ <message>
+ <source>Memo:</source>
+ <translation>Бележка:</translation>
+ </message>
+</context>
+<context>
+ <name>ShutdownWindow</name>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation>Не изключвайте компютъра докато този прозорец не изчезне.</translation>
+ </message>
+</context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ <message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>Подпиши / Провери съобщение</translation>
+ </message>
+ <message>
+ <source>&amp;Sign Message</source>
+ <translation>&amp;Подпиши</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Изберете използван преди адрес</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Вмъкни от клипборда</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Enter the message you want to sign here</source>
+ <translation>Въведете съобщението тук</translation>
+ </message>
+ <message>
+ <source>Signature</source>
+ <translation>Подпис</translation>
+ </message>
+ <message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>Копиране на текущия подпис</translation>
+ </message>
+ <message>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation>Подпишете съобщение като доказателство, че притежавате определен адрес</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation>Подпиши &amp;съобщение</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>&amp;Изчисти</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation>&amp;Провери</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>Проверете съобщение, за да сте сигурни че е подписано с определен Биткоин адрес</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation>Потвърди &amp;съобщението</translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Натиснете "Подписване на съобщение" за да създадете подпис</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>Въведеният адрес е невалиден.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Моля проверете адреса и опитайте отново.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>Въведеният адрес не може да се съпостави с валиден ключ.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>Отключването на портфейла беше отменено.</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>Не е наличен частен ключ за въведеният адрес.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Подписването на съобщение беше неуспешно.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Съобщението е подписано.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>Подписът не може да бъде декодиран.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Проверете подписа и опитайте отново.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>Подписът не отговаря на комбинацията от съобщение и адрес.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Проверката на съобщението беше неуспешна.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Съобщението е потвърдено.</translation>
+ </message>
+</context>
+<context>
+ <name>TrafficGraphWidget</name>
+ <message>
+ <source>KB/s</source>
+ <translation>Килобайта в секунда</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Open until %1</source>
+ <translation>Подлежи на промяна до %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/непотвърдени</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>включена в %1 блока</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Статус</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Дата</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>източник</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Генериран</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>от</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>неизвестен</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>към</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>собствен адрес</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>само гледане</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>име</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>кредит</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>не е приет</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Дебит</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>Общ дълг</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Общ дълг</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Такса</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation>Нетна сума</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Съобщение</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Коментар</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Търговец</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>Генерираните монети трябва да отлежат %1 блока преди да могат да бъдат похарчени. Когато генерираш блока, той се разпространява в мрежата, за да се добави в блок-веригата. Ако не успее да се добави във веригата, неговия статус ще се стане "неприет" и няма да може да се похарчи. Това е възможно да се случи случайно, ако друг възел генерира блок няколко секунди след твоя.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Информация за грешките</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Транзакция</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Количество</translation>
+ </message>
+ <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>Описание на транзакцията</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Дата</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Тип</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Етикет</translation>
+ </message>
+ <message>
+ <source>Open until %1</source>
+ <translation>Подлежи на промяна до %1</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>Непотвърдено</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>Потвърждаване (%1 от %2 препоръчвани потвърждения)</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Потвърдени (%1 потвърждения)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation>Конфликтно</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>Неплатим (%1 потвърждения, ще бъде платим след %2)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Генерирана, но отхвърлена от мрежата</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Получени</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Получен от</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Изпратени на</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Плащане към себе си</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Емитирани</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>само гледане</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n/a)</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(без етикет)</translation>
+ </message>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Състояние на транзакцията. Задръжте върху това поле за брой потвърждения.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Дата и час на получаване на транзакцията.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Вид транзакция.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Сума извадена или добавена към баланса.</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>All</source>
+ <translation>Всички</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Днес</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Тази седмица</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Този месец</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Предния месец</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Тази година</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>От - до...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Получени</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Изпратени на</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Собствени</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Емитирани</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Други</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Минимална сума</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Копирайте адреса</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Копиране на етикета</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Копиране на сумата</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Копиране на ID на транзакцията</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Редактирай име</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Подробности за транзакцията</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>Изнасяне историята на транзакциите</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Comma separated file (*.csv)</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Потвърдено</translation>
+ </message>
+ <message>
+ <source>Watch-only</source>
+ <translation>само гледане</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Дата</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Тип</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Етикет</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Адрес</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>ИД</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Изнасянето се провали</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Изнасянето е успешна</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>Историята с транзакциите беше успешно запазена в %1.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>От:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>до</translation>
+ </message>
+</context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletController</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>Няма зареден портфейл.</translation>
+ </message>
+</context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>Изпращане</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Портфейл по подразбиране</translation>
+ </message>
+</context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>Изнеси</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Изнеси данните в избрания раздел към файл</translation>
+ </message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Запазване на портфейла</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>Информация за портфейла (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Неуспешно запазване на портфейла</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>Възникна грешка при запазването на информацията за портфейла в %1.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Успешно запазване на портфейла</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>Информацията за портфейла беше успешно запазена в %1.</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>Желаете ли да пресъздадете базата данни с блокове сега?</translation>
+ </message>
+ <message>
+ <source>Error initializing block database</source>
+ <translation>Грешка в пускането на базата данни с блокове</translation>
+ </message>
+ <message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation>Провалено "слушане" на всеки порт. Използвайте -listen=0 ако искате това.</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>Внасяне...</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>Проверка на блоковете...</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>Това е експериментален софтуер.</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>Сумата на транзакцията е твърде малка</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>Транзакцията е твърде голяма</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>Стартиране на мрежовите нишки...</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>Портфейлът няма да плаша по-малко от миналата такса за препредаване.</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>Това е минималната такса за транзакция, която плащате за всяка транзакция.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>Това е таксата за транзакцията която ще платите ако изпратите транзакция.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>Сумите на транзакциите не могат да бъдат отрицателни</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>Транзакцията трябва да има поне един получател.</translation>
+ </message>
+ <message>
+ <source>Insufficient funds</source>
+ <translation>Недостатъчно средства</translation>
+ </message>
+ <message>
+ <source>Loading block index...</source>
+ <translation>Зареждане на блок индекса...</translation>
+ </message>
+ <message>
+ <source>Loading wallet...</source>
+ <translation>Зареждане на портфейла...</translation>
+ </message>
+ <message>
+ <source>Cannot downgrade wallet</source>
+ <translation>Портфейлът не може да се понижи.</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>Преразглеждане на последовтелността от блокове...</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation>Зареждането е завършено</translation>
+ </message>
+</context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_bn.ts b/src/qt/locale/bitcoin_bn.ts
new file mode 100644
index 0000000000..3a68e2847c
--- /dev/null
+++ b/src/qt/locale/bitcoin_bn.ts
@@ -0,0 +1,186 @@
+<TS language="bn" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>ঠিকানা কিংবা লেভেল সম্পাদনার জন্য রাইট-ক্লিক করুন</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>নতুন একটি ঠিকানা তৈরি করুন</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>নতুন</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>কপি/প্রতিলিপি</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>কপি/প্রতিলিপি</translation>
+ </message>
+ </context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Address</source>
+ <translation>ঠিকানা </translation>
+ </message>
+ </context>
+<context>
+ <name>AskPassphraseDialog</name>
+ </context>
+<context>
+ <name>BanTableModel</name>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Warning</source>
+ <translation>সতর্কতা</translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ </context>
+<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ </context>
+<context>
+ <name>Intro</name>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>QR Code</source>
+ <translation>QR কোড</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>ঠিকানা </translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ </context>
+<context>
+ <name>SendCoinsEntry</name>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>প্রবেশকৃত ঠিকানাটি শুদ্ধ নয়।</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>অনুগ্রহ করে স্বাক্ষরটি পুনরায় পরীক্ষা করে আবারও চেষ্টা করুন।</translation>
+ </message>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Address</source>
+ <translation>ঠিকানা </translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletController</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ </context>
+<context>
+ <name>WalletView</name>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>আপনি কি পুনরায় ব্লক ডাটাবেইজ এখনই তৈরি করতে চান?</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>এটি পরীক্ষামূলক সফটওয়্যার।</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>লেনদেনের পরিমান অনেক ছোট</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>লেনদেনর অংক অনেক বড়</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_he_IL.ts b/src/qt/locale/bitcoin_bs.ts
index 927b6184d8..ef97da747a 100644
--- a/src/qt/locale/bitcoin_he_IL.ts
+++ b/src/qt/locale/bitcoin_bs.ts
@@ -1,75 +1,103 @@
-<TS language="he_IL" version="2.1">
+<TS language="bs" version="2.1">
<context>
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>קליל ימני כדי לערוך כתובת או תווית</translation>
+ <translation>Desni klik za uređivanje adrese ili oznake</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>צור כתובת חדשה</translation>
+ <translation>Napravite novu adresu</translation>
</message>
<message>
<source>&amp;New</source>
- <translation>וחדש</translation>
+ <translation>&amp;Nova</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>העתק את הכתובת הנבחרת ללוח</translation>
+ <translation>Kopirajte trenutno odabranu adresu u sistemski meduspremnik</translation>
</message>
<message>
<source>&amp;Copy</source>
- <translation>והעתק</translation>
+ <translation>&amp;Kopirajte</translation>
</message>
<message>
<source>C&amp;lose</source>
- <translation>וסגור</translation>
+ <translation>&amp;Zatvorite</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>מחק את הכתובת הנבחרת מהרשימה</translation>
+ <translation>Izbrišite trenutno odabranu odresu sa liste</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>Unesite adresu ili oznaku za pretragu</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>יצא את המידע בעמוד הנוכחי לקובץ</translation>
+ <translation>Izvezite podatke trenutne kartice u datoteku</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation>ייצוא</translation>
+ <translation>&amp;Izvezite</translation>
</message>
<message>
<source>&amp;Delete</source>
- <translation>מחק</translation>
+ <translation>Iz&amp;brišite</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>בחר את הכתובת כדי לשלוח אליה מטבעות</translation>
+ <translation>Izaberite adresu na koju ćete poslati novac</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>בחר את הכתובת כדי לקבל אליה מטבעות</translation>
+ <translation>Izaberite adresu na koju ćete primiti novac</translation>
</message>
<message>
<source>C&amp;hoose</source>
- <translation>בחר</translation>
+ <translation>&amp;Izaberite</translation>
</message>
<message>
<source>Sending addresses</source>
- <translation>שולח כתובות</translation>
+ <translation>Adrese pošiljalaca</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation>מקבל כתובות</translation>
+ <translation>Adrese primalaca</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>
+ <translation>Ovo su vaše Bitcoin adrese za slanje novca. Uvijek provjerite iznos i adresu primaoca prije slanja novca.</translation>
</message>
<message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>אלו הן כתובות הביטקוין שלך לקבלת תשלומים. מומלץ להשתמש בכתובת חדשה בכל העברת מטבעות</translation>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Kopirajte adresu</translation>
</message>
- </context>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Kopirajte &amp;ozanku</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Uredite</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Izvezite listu adresa</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Datoteka podataka odvojenih zarezima (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Izvoz neuspješan</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Došlo je do greške kod spašavanja liste adresa na %1. Molimo pokušajte ponovo.</translation>
+ </message>
+</context>
<context>
<name>AddressTableModel</name>
</context>
@@ -81,25 +109,15 @@
</context>
<context>
<name>BitcoinGUI</name>
- <message>
- <source>Bitcoin</source>
- <translation>ביטקוין</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>ארנק</translation>
- </message>
</context>
<context>
<name>CoinControlDialog</name>
- <message>
- <source>Copy amount</source>
- <translation>העתק סכום</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>העתק כמות</translation>
- </message>
+ </context>
+<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
</context>
<context>
<name>EditAddressDialog</name>
@@ -114,7 +132,7 @@
<name>Intro</name>
<message>
<source>Bitcoin</source>
- <translation>ביטקוין</translation>
+ <translation>Bitcoin</translation>
</message>
</context>
<context>
@@ -124,6 +142,9 @@
<name>OpenURIDialog</name>
</context>
<context>
+ <name>OpenWalletActivity</name>
+ </context>
+<context>
<name>OptionsDialog</name>
</context>
<context>
@@ -139,9 +160,6 @@
<name>QObject</name>
</context>
<context>
- <name>QObject::QObject</name>
- </context>
-<context>
<name>QRImageWidget</name>
</context>
<context>
@@ -149,46 +167,40 @@
</context>
<context>
<name>ReceiveCoinsDialog</name>
- <message>
- <source>Copy amount</source>
- <translation>העתק סכום</translation>
- </message>
-</context>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Wallet</source>
- <translation>ארנק</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
</context>
<context>
<name>SendCoinsDialog</name>
+ </context>
+<context>
+ <name>SendCoinsEntry</name>
<message>
- <source>Copy quantity</source>
- <translation>העתק כמות</translation>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
</message>
<message>
- <source>Copy amount</source>
- <translation>העתק סכום</translation>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
</message>
</context>
<context>
- <name>SendCoinsEntry</name>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
<name>SignVerifyMessageDialog</name>
- </context>
-<context>
- <name>SplashScreen</name>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
</context>
<context>
<name>TrafficGraphWidget</name>
@@ -205,14 +217,41 @@
<context>
<name>TransactionView</name>
<message>
- <source>Copy amount</source>
- <translation>העתק סכום</translation>
+ <source>All</source>
+ <translation>Sve</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Danas</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Ovaj mjesec</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Prošli mjesec</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Ove godine</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Datoteka podataka odvojenih zarezima (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Izvoz neuspješan</translation>
</message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
<context>
+ <name>WalletController</name>
+ </context>
+<context>
<name>WalletFrame</name>
</context>
<context>
@@ -222,11 +261,11 @@
<name>WalletView</name>
<message>
<source>&amp;Export</source>
- <translation>ייצוא</translation>
+ <translation>&amp;Izvezite</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>יצא את המידע בעמוד הנוכחי לקובץ</translation>
+ <translation>Izvezite podatke trenutne kartice u datoteku</translation>
</message>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts
index 78113b0185..e14fc3097e 100644
--- a/src/qt/locale/bitcoin_ca.ts
+++ b/src/qt/locale/bitcoin_ca.ts
@@ -7,11 +7,11 @@
</message>
<message>
<source>Create a new address</source>
- <translation>Crea una nova adreça</translation>
+ <translation>Crea una adreça nova</translation>
</message>
<message>
<source>&amp;New</source>
- <translation>&amp;Nou</translation>
+ <translation>&amp;Nova</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
@@ -27,7 +27,7 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>Elimina l'adreça sel·leccionada actualment de la llista</translation>
+ <translation>Elimina l'adreça seleccionada actualment de la llista</translation>
</message>
<message>
<source>Enter address or label to search</source>
@@ -125,31 +125,35 @@
</message>
<message>
<source>New passphrase</source>
- <translation>Nova contrasenya</translation>
+ <translation>Contrasenya nova</translation>
</message>
<message>
<source>Repeat new passphrase</source>
- <translation>Repetiu la nova contrasenya</translation>
+ <translation>Repetiu la contrasenya nova</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation>Mostra la contrasenya</translation>
</message>
<message>
<source>Encrypt wallet</source>
- <translation>Xifra el moneder</translation>
+ <translation>Xifra la cartera</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Aquesta operació requereix la contrasenya del moneder per a desbloquejar-lo.</translation>
+ <translation>Aquesta operació requereix la contrasenya de la cartera per a desblocar-la.</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation>Desbloqueja el moneder</translation>
+ <translation>Desbloca la cartera</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Aquesta operació requereix la contrasenya del moneder per desxifrar-lo.</translation>
+ <translation>Aquesta operació requereix la contrasenya de la cartera per a desxifrar-la.</translation>
</message>
<message>
<source>Decrypt wallet</source>
- <translation>Desxifra el moneder</translation>
+ <translation>Desxifra la cartera</translation>
</message>
<message>
<source>Change passphrase</source>
@@ -157,27 +161,47 @@
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation>Confirma el xifrat del moneder</translation>
+ <translation>Confirma el xifratge de la cartera</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Avís: si xifreu el vostre moneder i perdeu la contrasenya, &lt;b&gt;PERDREU TOTS ELS VOSTRES BITCOINS&lt;/b&gt;!</translation>
+ <translation>Avís: si xifreu la cartera i perdeu la contrasenya, &lt;b&gt;PERDREU TOTS ELS BITCOINS&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Esteu segurs que voleu xifrar el vostre moneder?</translation>
+ <translation>Esteu segurs que voleu xifrar la vostra cartera?</translation>
</message>
<message>
<source>Wallet encrypted</source>
- <translation>Moneder xifrat</translation>
+ <translation>Cartera xifrada</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>Introduïu la contrasenya nova a la cartera.&lt;br/&gt;Utilitzeu una contrasenya de &lt;b&gt;deu o més caràcters aleatoris&lt;/b&gt;, o &lt;b&gt;vuit o més paraules&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Introduïu la contrasenya antiga i la contrasenya nova a la cartera.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Cartera per ser encriptada</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>La teva cartera està apunt de ser xifrada</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>S'ha xifrat la cartera.</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>IMPORTANT: Tota copia de seguretat del fitxer del moneder que hàgiu realitzat hauria de ser reemplaçada pel fitxer xifrat del moneder recentment generat. Per motius de seguretat, les còpies de seguretat anteriors del fitxer del moneder no xifrat esdevindran inusables tan aviat com comenci a utilitzar el nou moneder xifrat.</translation>
+ <translation>IMPORTANT: Tota copia de seguretat del fitxer de la cartera que hàgiu realitzat hauria de ser reemplaçada pel fitxer xifrat de la cartera generat recentment. Per motius de seguretat, les còpies de seguretat anteriors del fitxer de la cartera no xifrada esdevindran inusables tan aviat com comenceu a utilitzar la cartera xifrada nova.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
- <translation>El xifrat del moneder ha fallat</translation>
+ <translation>Ha fallat el xifratge de la cartera</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
@@ -189,7 +213,7 @@
</message>
<message>
<source>Wallet unlock failed</source>
- <translation>El desbloqueig del moneder ha fallat</translation>
+ <translation>El desbloqueig de la cartera ha fallat</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
@@ -278,6 +302,10 @@
<translation>Modifica les opcions de configuració de %1</translation>
</message>
<message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;Encripta la cartera...</translation>
+ </message>
+ <message>
<source>&amp;Backup Wallet...</source>
<translation>&amp;Realitza una còpia de seguretat del moneder...</translation>
</message>
@@ -302,17 +330,421 @@
<translation>S'ha inhabilitat l'activitat de la xarxa.</translation>
</message>
<message>
+ <source>Click to enable network activity again.</source>
+ <translation>Feu clic per tornar a habilitar l'activitat de la xarxa.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Sincronitzant capçaleres (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>S'estan reindexant els blocs al disc...</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>El servidor proxy està &lt;b&gt;activat&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>Envia monedes a una adreça Bitcoin</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>Realitza una còpia de seguretat de la cartera a una altra ubicació</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>Canvia la contrasenya d'encriptació de la cartera</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;Verifica el missatge...</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;Envia</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;Rep</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Mostra / Amaga</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Mostra o amaga la finestra principal</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Encripta les claus privades pertanyents de la cartera</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Signa el missatges amb la seva adreça de Bitcoin per provar que les poseeixes</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Verifiqueu els missatges per assegurar-vos que han estat signats amb una adreça Bitcoin específica.</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;Fitxer</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>&amp;Configuració</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>&amp;Ajuda</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>Barra d'eines de les pestanyes</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>Sol·licita pagaments (genera codis QR i bitcoin: URI)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Mostra la llista d'adreces d'enviament i etiquetes utilitzades</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Mostra la llista d'adreces de recepció i etiquetes utilitzades</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>Opcions de la &amp;línia d'ordres</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>S'estan indexant els blocs al disc...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>S'estan processant els blocs al disc...</translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 darrere</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>El darrer bloc rebut ha estat generat fa %1.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Les transaccions a partir d'això no seran visibles.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Avís</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Informació</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation>Actualitzat</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation>Adreces d'&amp;enviament</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation>Adreces de &amp;recepció</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <translation>Obre la cartera</translation>
+ </message>
+ <message>
+ <source>Open a wallet</source>
+ <translation>Obre la cartera</translation>
+ </message>
+ <message>
+ <source>Close Wallet...</source>
+ <translation>Tanca la cartera...</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation>Tanca la cartera</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>default wallet</source>
+ <translation>cartera predeterminada</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation>No hi ha cap cartera disponible</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;Finestra</translation>
+ </message>
+ <message>
+ <source>Minimize</source>
+ <translation>Minimitza</translation>
+ </message>
+ <message>
+ <source>Zoom</source>
+ <translation>Escala</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation>Finestra principal</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>Client de %1</translation>
+ </message>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>Connectant als iguals...</translation>
+ </message>
+ <message>
+ <source>Catching up...</source>
+ <translation>S'està posant al dia ...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>Avís: %1</translation>
</message>
- </context>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Data: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Import: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>Cartera: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Tipus: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Etiqueta: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Adreça: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Transacció enviada</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>Transacció entrant</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>La generació de la clau HD és &lt;b&gt;habilitada&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>La generació de la clau HD és &lt;b&gt;inhabilitada&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>Clau privada &lt;b&gt;inhabilitada&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 està &lt;b&gt;encriptada&lt;/b&gt; i actualment &lt;b&gt;desblocada&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>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>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation>Selecció de moneda</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Quantitat:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bytes:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Import:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Comissió:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Polsim:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Comissió posterior:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Canvi:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>(des)selecciona-ho tot</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>Mode arbre</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>Mode llista</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Import</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation>Rebut amb l'etiqueta</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Rebut amb l'adreça</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation>Confirmacions</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Confirmat</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Copia l'adreça</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copia l'etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copia l'import</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copia l'ID de transacció</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Bloqueja sense gastar</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Desbloqueja sense gastar</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Copia la quantitat</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Copia la comissió</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Copia la comissió posterior</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Copia els bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Copia el polsim</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Copia el canvi</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 bloquejada)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>sí</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>Aquesta etiqueta es torna vermella si cap recipient rep un import inferior al llindar de polsim actual.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Pot variar en +/- %1 satoshi(s) per entrada.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sense etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>canvia de %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(canvia)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
</context>
@@ -321,44 +753,692 @@
</context>
<context>
<name>EditAddressDialog</name>
- </context>
+ <message>
+ <source>Edit Address</source>
+ <translation>Edita l'adreça</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;Etiqueta</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation>L'etiqueta associada amb aquesta entrada de llista d'adreces</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>L'adreça associada amb aquesta entrada de llista d'adreces. Només es pot modificar per a les adreces d'enviament.</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;Adreça</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>Nova adreça d'enviament</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Edita l'adreça de recepció</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Edita l'adreça d'enviament</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>L'adreça introduïda «%1» no és una adreça de Bitcoin vàlida.</translation>
+ </message>
+ <message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>L'adreça "%1" ja existeix com una adreça per rebre amb l'etiqueta "%2" i per tant no pot ésser afegida com adreça per enviar.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>L'adreça introduïda "%1" ja existeix al directori d'adreces amb l'etiqueta "%2".</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No s'ha pogut desblocar la cartera.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Ha fallat la generació d'una clau nova.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
- </context>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation>Es crearà un nou directori de dades.</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation>nom</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>El directori ja existeix. Afegeix %1 si vols crear un nou directori en aquesta ubicació.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>El camí ja existeix i no és cap directori.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>No es pot crear el directori de dades aquí.</translation>
+ </message>
+</context>
<context>
<name>HelpMessageDialog</name>
- </context>
+ <message>
+ <source>version</source>
+ <translation>versió</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation>Quant al %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>Opcions de línia d'ordres</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
+ <message>
+ <source>Welcome</source>
+ <translation>Us donem la benvinguda</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation>Us donem la benvinguda a %1.</translation>
+ </message>
+ <message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation>Com és la primera vegada que s'executa el programa, podeu triar on %1 emmagatzemarà les dades.</translation>
+ </message>
+ <message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>Quan feu clic a D'acord, %1 començarà a descarregar i processar la cadena de blocs %4 completa (%2 GB) començant per les primeres transaccions de %3, any de llençament inicial de %4.</translation>
+ </message>
+ <message>
+ <source>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>Aquesta sincronització inicial és molt exigent i pot exposar problemes de maquinari amb l'equip que anteriorment havien passat desapercebuts. Cada vegada que executeu %1, continuarà descarregant des del punt on es va deixar.</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>Si heu decidit limitar l'emmagatzematge de la cadena de blocs (podar), les dades històriques encara s'hauran de baixar i processar, però se suprimiran més endavant per mantenir baix l'ús del disc.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>Utilitza el directori de dades per defecte</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>Utilitza un directori de dades personalitzat:</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>Almenys %1 GB de dades s'emmagatzemaran en aquest directori, i creixerà amb el temps.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>Aproximadament %1GB de dades seran emmagetzamades en aquest directori.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>%1 descarregarà i emmagatzemarà una còpia de la cadena de blocs Bitcoin.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>La cartera també serà emmagatzemat en aquest directori.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation>Error: el directori de dades «%1» especificat no pot ser creat.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
</context>
<context>
<name>ModalOverlay</name>
- </context>
+ <message>
+ <source>Form</source>
+ <translation>Formulari</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>És possible que les transaccions recents encara no siguin visibles i, per tant, el saldo de la vostra cartera podria ser incorrecte. Aquesta informació serà correcta una vegada que la cartera hagi finalitzat la sincronització amb la xarxa bitcoin, tal com es detalla més avall.</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>Els intents de gastar bitcoins que es veuen afectats per les transaccions que encara no s'hagin mostrat no seran acceptats per la xarxa.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Nombre de blocs pendents</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Desconegut...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Últim temps de bloc</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation>Progrés</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>Augment de progrés per hora</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>s'està calculant...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>Temps estimat restant fins sincronitzat</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Amaga</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)...</source>
+ <translation>Desconegut. Sincronització de les capçaleres (%1, %2%)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
- </context>
+ <message>
+ <source>URI:</source>
+ <translation>URI:</translation>
+ </message>
+</context>
<context>
<name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>moneder per defecte</translation>
</message>
- </context>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>S'està obrint la cartera &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+</context>
<context>
<name>OptionsDialog</name>
- </context>
+ <message>
+ <source>Options</source>
+ <translation>Opcions</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation>&amp;Principal</translation>
+ </message>
+ <message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Inicieu %1 automàticament després d'entrar en el sistema.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>&amp;Inicia %1 en l'entrada al sistema</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Mida de la memòria cau de la base de &amp;dades</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation>Nombre de fils de &amp;verificació d'scripts</translation>
+ </message>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation>Adreça IP del proxy (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>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>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>Amaga la icona de la safata</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>Minimitza en comptes de sortir de l'aplicació quan la finestra es tanca. Quan s'habilita aquesta opció l'aplicació es tancarà només quan se selecciona Surt del 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>URL de terceres parts (p. ex. explorador de blocs) que apareix en la pestanya de transaccions com elements del menú contextual. %s en l'URL es reemplaçat pel resum de la transacció. Diferents URL estan separades per una barra vertical |.</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Obriu el fitxer de configuració %1 des del directori de treball.</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>Obre el fitxer de configuració</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>Reestableix totes les opcions del client.</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation>&amp;Reestableix les opcions</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation>&amp;Xarxa</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>Deshabilita unes característiques avançades però tots els blocs encara seran validats completament. Revertir aquesta configuració requereix tornar a descarregar la cadena de blocs sencera un altre cop. L'espai en ús del disc és possible que augmenti.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Prunar emmagatzemament de &amp;block a</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Revertir aquesta configuració requereix tornar a descarregar la cadena de blocs sencera un altre cop.</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 = deixa tants nuclis lliures)</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation>&amp;Moneder</translation>
+ </message>
+ <message>
+ <source>Expert</source>
+ <translation>Expert</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation>Activa les funcions de &amp;control de les monedes</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 inhabiliteu la despesa d'un canvi sense confirmar, el canvi d'una transacció no pot ser utilitzat fins que la transacció no tingui com a mínim una confirmació. Això també afecta com es calcula el vostre balanç.</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation>&amp;Gasta el canvi sense confirmar</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>Obre el port del client de Bitcoin al router de forma automàtica. Això només funciona quan el router implementa UPnP i l'opció està activada.</translation>
+ </message>
+ <message>
+ <source>Map port using &amp;UPnP</source>
+ <translation>Port obert amb &amp;UPnP</translation>
+ </message>
+ <message>
+ <source>Accept connections from outside.</source>
+ <translation>Accepta connexions de fora</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Permet connexions entrants</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation>Connecta a la xarxa Bitcoin a través d'un proxy SOCKS5.</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>&amp;Connecta a través d'un proxy SOCKS5 (proxy per defecte):</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation>&amp;IP del proxy:</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation>&amp;Port:</translation>
+ </message>
+ <message>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation>Port del proxy (per exemple 9050)</translation>
+ </message>
+ <message>
+ <source>Used for reaching peers via:</source>
+ <translation>Utilitzat per arribar als iguals mitjançant:</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>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>
+ <message>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation>Mostra només la icona de la barra en minimitzar la finestra.</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize to the tray instead of the taskbar</source>
+ <translation>&amp;Minimitza a la barra d'aplicacions en comptes de la barra de tasques</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation>M&amp;inimitza en tancar</translation>
+ </message>
+ <message>
+ <source>&amp;Display</source>
+ <translation>&amp;Pantalla</translation>
+ </message>
+ <message>
+ <source>User Interface &amp;language:</source>
+ <translation>&amp;Llengua de la interfície d'usuari:</translation>
+ </message>
+ <message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation>Aquí es pot definir la llengua de la interfície d'usuari. Aquest paràmetre tindrà efecte en reiniciar el %1.</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation>&amp;Unitats per mostrar els imports en:</translation>
+ </message>
+ <message>
+ <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
+ <translation>Selecciona la unitat de subdivisió per defecte per mostrar en la interfície quan s'envien monedes.</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>Si voleu mostrar les funcions de control de monedes o no.</translation>
+ </message>
+ <message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>URL de transaccions de tercers</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>&amp;D'acord</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>&amp;Cancel·la</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation>Per defecte</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation>cap</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <translation>Confirmeu el reestabliment de les opcions</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>Cal reiniciar el client per activar els canvis.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>S'aturarà el client. Voleu procedir?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Opcions de configuració</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>El fitxer de configuració s'utilitza per especificar les opcions d'usuari avançades que substitueixen la configuració de la interfície gràfica d'usuari. A més, qualsevol opció de la línia d'ordres substituirà aquest fitxer de configuració.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
+ <source>The configuration file could not be opened.</source>
+ <translation>No s'ha pogut obrir el fitxer de configuració.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>Amb aquest canvi cal un reinici del client.</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>L'adreça proxy introduïda és invalida.</translation>
+ </message>
+</context>
<context>
<name>OverviewPage</name>
- </context>
+ <message>
+ <source>Form</source>
+ <translation>Formulari</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>La informació mostrada pot no estar al dia. El vostra cartera se sincronitza automàticament amb la xarxa Bitcoin un cop s'ha establert connexió, però aquest proces encara no ha finalitzat.</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>Només lectura:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>Disponible:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>El balanç que podeu gastar actualment</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>Pendent:</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 de transaccions que encara han de confirmar-se i que encara no compten en el balanç que es pot gastar</translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation>Immadur:</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>Balanç minat que encara no ha madurat</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>El balanç total actual</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>El vostre balanç actual en adreces de només lectura</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>Que es pot gastar:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Transaccions recents</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>Transaccions sense confirmar a adreces de només lectura</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation>Balanç minat en adreces de només lectura que encara no ha madurat</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation>Balanç total actual en adreces de només lectura</translation>
+ </message>
+</context>
<context>
<name>PaymentServer</name>
- </context>
+ <message>
+ <source>Payment request error</source>
+ <translation>Error de la sol·licitud de pagament</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>No es pot iniciar bitcoin: controlador click-to-pay</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>Gestió d'URI</translation>
+ </message>
+ <message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' no és una URI vàlida. Usi 'bitcoin:' en lloc seu.</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Adreça de pagament no vàlida %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 no pot ser analitzat! Això pot ser a causa d'una adreça de Bitcoin no vàlida o per paràmetres URI amb mal format.</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>Gestió de fitxers de les sol·licituds de pagament</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
- </context>
+ <message>
+ <source>User Agent</source>
+ <translation>Agent d'usuari</translation>
+ </message>
+ <message>
+ <source>Node/Service</source>
+ <translation>Node/Servei</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>NodeId</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>Ping</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Enviat</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Rebut</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
+ <source>Amount</source>
+ <translation>Import</translation>
+ </message>
+ <message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Introduïu una adreça de Bitcoin (p. ex. %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>Cap</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 i %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: El directori de dades especificat «%1» no existeix.</translation>
</message>
@@ -370,10 +1450,26 @@
<source>Error: %1</source>
<translation>Avís: %1</translation>
</message>
- </context>
+ <message>
+ <source>%1 didn't yet exit safely...</source>
+ <translation>%1 encara no ha finalitzat de manera segura...</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>desconegut</translation>
+ </message>
+</context>
<context>
<name>QRImageWidget</name>
<message>
+ <source>&amp;Save Image...</source>
+ <translation>De&amp;sa la imatge...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;Copia la imatge</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI resultant massa llarga, intenta reduir el text per a la etiqueta / missatge</translation>
</message>
@@ -381,13 +1477,361 @@
<source>Error encoding URI into QR Code.</source>
<translation>Error en codificar l'URI en un codi QR.</translation>
</message>
- </context>
+ <message>
+ <source>Save QR Code</source>
+ <translation>Desa el codi QR</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>Imatge PNG (*.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>Versió del client</translation>
+ </message>
+ <message>
+ <source>&amp;Information</source>
+ <translation>&amp;Informació</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>General</translation>
+ </message>
+ <message>
+ <source>Using BerkeleyDB version</source>
+ <translation>Utilitzant BerkeleyDB versió</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation>Datadir</translation>
+ </message>
+ <message>
+ <source>Blocksdir</source>
+ <translation>Directori de blocs</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation>&amp;Temps d'inici</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>Xarxa</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>Nom</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation>Nombre de connexions</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <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>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>Nombre actual de transaccions</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>Ús de memòria</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation>Cartera:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(cap)</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>&amp;Reinicialitza</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Rebut</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Enviat</translation>
+ </message>
+ <message>
+ <source>&amp;Peers</source>
+ <translation>&amp;Iguals</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation>Iguals bandejats</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <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>
+ <message>
+ <source>Version</source>
+ <translation>Versió</translation>
+ </message>
+ <message>
+ <source>Starting Block</source>
+ <translation>Bloc d'inici</translation>
+ </message>
+ <message>
+ <source>Synced Headers</source>
+ <translation>Capçaleres sincronitzades</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>Blocs sincronitzats</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>Agent d'usuari</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>Obre el fitxer de registre de depuració %1 del directori de dades actual. Això pot trigar uns segons en fitxers de registre grans.</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation>Disminueix la mida de la lletra</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>Augmenta la mida de la lletra</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <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>
+ <message>
+ <source>Last Send</source>
+ <translation>Darrer enviament</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation>Darrera recepció</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation>Temps de ping</translation>
+ </message>
+ <message>
+ <source>The duration of a currently outstanding ping.</source>
+ <translation>La duració d'un ping més destacat actualment.</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>Espera de ping</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>Min Ping</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation>Diferència horària</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Últim temps de bloc</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation>&amp;Obre</translation>
+ </message>
+ <message>
+ <source>&amp;Console</source>
+ <translation>&amp;Consola</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation>Trà&amp;nsit de la xarxa</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation>Totals</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation>Dins:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>Fora:</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation>Fitxer de registre de depuració</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation>Neteja la consola</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;hora</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;dia</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp;setmana</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp;any</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;Desconnecta</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>Bandeja per</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>&amp;Desbandeja</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>Us donem la benvinguda a la consola RPC de %1</translation>
+ </message>
+ <message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>Utilitzeu les fletxes amunt i avall per navegar per l'historial i %1 per netejar la pantalla.</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Escriu %1 per veure un sumari de les comandes disponibles.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Per més informació per usar aquesta consola de comandes, escriu %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>ADVERTIMENT: Els estafadors han estat actius, dient als usuaris que escriguin ordres aquí, robant els contingut de les seves carteres. No utilitzeu aquesta consola sense comprendre completament les ramificacions d'una ordre.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>Activitat de xarxa inhabilitada</translation>
+ </message>
+ <message>
+ <source>Executing command without any wallet</source>
+ <translation>S'està executant l'ordre sense cap cartera</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>S'està executant comanda usant la cartera "%1"</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(id del node: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>a través de %1</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>mai</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>Entrant</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <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>
+</context>
<context>
<name>ReceiveCoinsDialog</name>
<message>
+ <source>&amp;Amount:</source>
+ <translation>Im&amp;port:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etiqueta:</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation>&amp;Missatge:</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 missatge opcional que s'adjuntarà a la sol·licitud de pagament, que es mostrarà quan s'obri la sol·licitud. Nota: El missatge no s'enviarà amb el pagament per la xarxa Bitcoin.</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation>Una etiqueta opcional que s'associarà amb la nova adreça receptora.</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation>Utilitzeu aquest formulari per sol·licitar pagaments. Tots els camps són &lt;b&gt;opcionals&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>Un import opcional per sol·licitar. Deixeu-ho en blanc o zero per no sol·licitar cap import específic.</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Neteja tots els camps del formulari.</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>Neteja</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>Les adreces segwit natives (més conegudes com Bech32 o BIP-173) redueixen les vostres comisions de les transaccions i ofereixen millor protecció contra errades tipogràfiques, però els moneders antics no les suporten. Quan desmarqui la casella, es generarà una adreça compatible amb moneders antics.</translation>
</message>
@@ -395,75 +1839,1020 @@
<source>Generate native segwit (Bech32) address</source>
<translation>Generar una adreça segwit nativa (Bech32)</translation>
</message>
- </context>
+ <message>
+ <source>Requested payments history</source>
+ <translation>Historial de pagaments sol·licitats</translation>
+ </message>
+ <message>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation>Mostra la sol·licitud seleccionada (fa el mateix que el doble clic a una entrada)</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>Mostra</translation>
+ </message>
+ <message>
+ <source>Remove the selected entries from the list</source>
+ <translation>Esborra les entrades seleccionades de la llista</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Esborra</translation>
+ </message>
+ <message>
+ <source>Copy URI</source>
+ <translation>Copia l'URI</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copia l'etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Copia el missatge</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copia l'import</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>QR Code</source>
+ <translation>Codi QR</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation>Copia l'&amp;URI</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Address</source>
+ <translation>Copia l'&amp;adreça</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>De&amp;sa la imatge...</translation>
+ </message>
+ <message>
+ <source>Request payment to %1</source>
+ <translation>Sol·licita un pagament a %1</translation>
+ </message>
+ <message>
+ <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>
- </context>
+ <message>
+ <source>Message</source>
+ <translation>Missatge</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Cartera</translation>
+ </message>
+</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Etiqueta</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Missatge</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sense etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation>(sense missatge)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(no s'ha sol·licitat import)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>Sol·licitat</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
+ <source>Send Coins</source>
+ <translation>Envia monedes</translation>
+ </message>
+ <message>
+ <source>Coin Control Features</source>
+ <translation>Característiques de control de les monedes</translation>
+ </message>
+ <message>
+ <source>Inputs...</source>
+ <translation>Entrades...</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>seleccionat automàticament</translation>
+ </message>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation>Fons insuficients!</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Quantitat:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bytes:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Import:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Comissió:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Comissió posterior:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Canvi:</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>Si s'activa això, però l'adreça de canvi està buida o bé no és vàlida, el canvi s'enviarà a una adreça generada de nou.</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation>Personalitza l'adreça de canvi</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation>Comissió de transacció</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>Tria...</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>L'ús de la tarifa de pagament pot provocar l'enviament d'una transacció que trigarà diverses hores o dies (o mai) a confirmar. Penseu a triar la possibilitat d'escollir la tarifa manualment o espereu fins que hagueu validat la cadena completa.</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Advertència: l'estimació de tarifes no és possible actualment.</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>Especifiqui una comissió personalitzada per kB (1.000 bytes) de la mida virtual de la transacció.
+
+Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "100 satoshis per cada kB" per una transacció de mida 500 bytes (la meitat de 1 kB) comportaria finalment una comissió de la transacció de només 50 satoshis.</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>per kilobyte</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Amaga</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>Recomanada:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>Personalitzada:</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(No s'ha inicialitzat encara la comissió intel·ligent. Normalment pren uns pocs blocs...)</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation>Envia a múltiples destinataris al mateix temps</translation>
+ </message>
+ <message>
+ <source>Add &amp;Recipient</source>
+ <translation>Afegeix &amp;destinatari</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Neteja tots els camps del formulari.</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Polsim:</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>Temps de confirmació objectiu:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Habilita Replace-By-Fee: substitució per comissió</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>Amb la substitució per comissió o Replace-By-Fee (BIP-125) pot incrementar la comissió de la transacció després d'enviar-la. Sense això, seria recomenable una comissió més alta per compensar el risc d'increment del retard de la transacció.</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Neteja-ho &amp;tot</translation>
+ </message>
+ <message>
+ <source>Balance:</source>
+ <translation>Balanç:</translation>
+ </message>
+ <message>
+ <source>Confirm the send action</source>
+ <translation>Confirma l'acció d'enviament</translation>
+ </message>
+ <message>
+ <source>S&amp;end</source>
+ <translation>E&amp;nvia</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Copia la quantitat</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copia l'import</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Copia la comissió</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Copia la comissió posterior</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Copia els bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Copia el polsim</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Copia el canvi</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 blocs)</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation>de la cartera "%1"</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 a %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Esteu segur que ho voleu enviar?</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>Pot incrementar la comissió més tard (senyala Replace-By-Fee o substitució per comissió, BIP-125).</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Reviseu la transacció</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Comissió de transacció</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Import total</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Confirma l'enviament de monedes</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>L'adreça del destinatari no és vàlida. Torneu-la a comprovar.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>L'import a pagar ha de ser major que 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>L'import supera el vostre balanç.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>El total excedeix el vostre balanç quan s'afegeix la comissió a la transacció %1.</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>S'ha trobat una adreça duplicada: les adreces només s'haurien d'utilitzar una vegada cada una.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>La creació de la transacció ha fallat!</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>Una comissió superior a %1 es considera una comissió absurdament alta.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>La sol·licitud de pagament ha vençut.</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Avís: adreça Bitcoin no vàlida</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Avís: adreça de canvi desconeguda</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation>Confirma l'adreça de canvi personalitzada</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>L'adreça que heu seleccionat per al canvi no és part d'aquesta cartera. Tots els fons de la vostra cartera es poden enviar a aquesta adreça. N'esteu segur?</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sense etiqueta)</translation>
</message>
</context>
<context>
<name>SendCoinsEntry</name>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
+ <message>
+ <source>A&amp;mount:</source>
+ <translation>Q&amp;uantitat:</translation>
+ </message>
+ <message>
+ <source>Pay &amp;To:</source>
+ <translation>Paga &amp;a:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etiqueta:</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Escull una adreça feta servir anteriorment</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>L'adreça Bitcoin on enviar el pagament</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alta+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Enganxa l'adreça del porta-retalls</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Remove this entry</source>
+ <translation>Elimina aquesta entrada</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>La comissió es deduirà de l'import que s'enviarà. El destinatari rebrà menys bitcoins que les que introduïu al camp d'import. Si se seleccionen múltiples destinataris, la comissió es dividirà per igual.</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>S&amp;ubstreu la comissió de l'import</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>Usa el saldo disponible</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Missatge:</translation>
+ </message>
+ <message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>Aquesta és una sol·licitud de pagament no autenticada.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>Aquesta és una sol·licitud de pagament autenticada.</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <translation>Introduïu una etiqueta per a aquesta adreça per afegir-la a la llista d'adreces utilitzades</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 missatge que s'ha adjuntat al bitcoin: URI que s'emmagatzemarà amb la transacció per a la vostra referència. Nota: el missatge no s'enviarà a través de la xarxa Bitcoin.</translation>
+ </message>
+ <message>
+ <source>Pay To:</source>
+ <translation>Paga a:</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 s'està tancant ...</translation>
+ </message>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation>No apagueu l'ordinador fins que no desaparegui aquesta finestra.</translation>
+ </message>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
- </context>
+ <message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>Signatures - Signa o verifica un missatge</translation>
+ </message>
+ <message>
+ <source>&amp;Sign Message</source>
+ <translation>&amp;Signa el missatge</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>Podeu signar missatges/acords amb les vostres adreces per provar que rebeu les bitcoins que s'hi envien. Aneu amb compte no signar res que sigui vague o aleatori, perquè en alguns atacs de suplantació es pot provar que hi signeu la vostra identitat. Només signeu aquelles declaracions completament detallades en què hi esteu d'acord. </translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation>L'adreça Bitcoin amb què signar el missatge</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Escull una adreça feta servir anteriorment</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alta+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Enganxa l'adreça del porta-retalls</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Enter the message you want to sign here</source>
+ <translation>Introduïu aquí el missatge que voleu signar</translation>
+ </message>
+ <message>
+ <source>Signature</source>
+ <translation>Signatura</translation>
+ </message>
+ <message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>Copia la signatura actual al porta-retalls del sistema</translation>
+ </message>
+ <message>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation>Signa el missatge per provar que ets propietari d'aquesta adreça Bitcoin</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation>Signa el &amp;missatge</translation>
+ </message>
+ <message>
+ <source>Reset all sign message fields</source>
+ <translation>Neteja tots els camps de clau</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Neteja-ho &amp;tot</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation>&amp;Verifica el missatge</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>Introduïu l'adreça del receptor, el missatge (assegureu-vos de copiar els salts de línia, espais, tabuladors, etc. exactament) i signatura de sota per verificar el missatge. Tingueu cura de no llegir més en la signatura del que està al missatge signat, per evitar ser enganyat per un atac d'home-en-el-mig. Tingueu en compte que això només demostra que la part que signa rep amb l'adreça, i no es pot provar l'enviament de qualsevol transacció!</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation>L'adreça Bitcoin amb què va ser signat el missatge</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>Verificar el missatge per assegurar-se que ha estat signat amb una adreça Bitcoin específica</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation>Verifica el &amp;missatge</translation>
+ </message>
+ <message>
+ <source>Reset all verify message fields</source>
+ <translation>Neteja tots els camps de verificació de missatge</translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Feu clic a «Signa el missatge» per a generar una signatura</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>L'adreça introduïda no és vàlida.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Comproveu l'adreça i torneu-ho a provar.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>L'adreça introduïda no referencia a cap clau.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>S'ha cancel·lat el desblocatge de la cartera.</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>La clau privada per a la adreça introduïda no està disponible.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>La signatura del missatge ha fallat.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Missatge signat.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>La signatura no s'ha pogut descodificar.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Comproveu la signatura i torneu-ho a provar.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>La signatura no coincideix amb el resum del missatge.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Ha fallat la verificació del missatge.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Missatge verificat.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
- </context>
+ <message>
+ <source>KB/s</source>
+ <translation>KB/s</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
- </context>
+ <message>
+ <source>Open until %1</source>
+ <translation>Obert fins %1</translation>
+ </message>
+ <message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>produït un conflicte amb una transacció amb %1 confirmacions</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, %1</source>
+ <translation>0/no confirmades, %1</translation>
+ </message>
+ <message>
+ <source>in memory pool</source>
+ <translation>a la reserva de memòria</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>no a la reserva de memòria</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>abandonada</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/sense confirmar</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 confirmacions</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Estat</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>Font</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Generada</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>desconegut</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>A</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>adreça pròpia</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>només lectura</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>etiqueta</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Crèdit</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>no acceptat</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Dèbit</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>Dèbit total</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Crèdit total</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Comissió de transacció</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation>Import net</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Missatge</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Comentari</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID de la transacció</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation>Mida total de la transacció</translation>
+ </message>
+ <message>
+ <source>Transaction virtual size</source>
+ <translation>Mida virtual de la transacció</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>Índex de resultats</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Mercader</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>Les monedes generades han de madurar %1 blocs abans de poder ser gastades. Quan genereu aquest bloc, es farà saber a la xarxa per tal d'afegir-lo a la cadena de blocs. Si no pot fer-se lloc a la cadena, el seu estat canviarà a «no acceptat» i no es podrà gastar. Això pot passar ocasionalment si un altre node genera un bloc en un marge de segons respecte al vostre.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Informació de depuració</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transacció</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>Entrades</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Import</translation>
+ </message>
+ <message>
+ <source>true</source>
+ <translation>cert</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>fals</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
- </context>
+ <message>
+ <source>This pane shows a detailed description of the transaction</source>
+ <translation>Aquest panell mostra una descripció detallada de la transacció</translation>
+ </message>
+ <message>
+ <source>Details for %1</source>
+ <translation>Detalls per %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Tipus</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Etiqueta</translation>
</message>
<message>
+ <source>Open until %1</source>
+ <translation>Obert fins %1</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>Sense confirmar</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation>Abandonada</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>Confirmant (%1 de %2 confirmacions recomanades)</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Confirmat (%1 confirmacions)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation>En conflicte</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>Immadur (%1 confirmacions, serà disponible després de %2)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Generat però no acceptat</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Rebuda amb</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Rebuda de</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Enviada a</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Pagament a un mateix</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minada</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>només lectura</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n/a)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sense etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Estat de la transacció. Desplaceu-vos sobre aquest camp per mostrar el nombre de confirmacions.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Data i hora en què la transacció va ser rebuda.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Tipus de transacció.</translation>
+ </message>
+ <message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>Si està implicada o no una adreça només de lectura en la transacció.</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>Intenció/propòsit de la transacció definida per l'usuari.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Import extret o afegit del balanç.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Tot</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Avui</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Aquesta setmana</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Aquest mes</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>El mes passat</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Enguany</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Rang...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Rebuda amb</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Enviada a</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>A un mateix</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minada</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Altres</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Introduïu una adreça, la id de la transacció o l'etiqueta per a cercar</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Import mínim</translation>
+ </message>
+ <message>
+ <source>Abandon transaction</source>
+ <translation>Abandonar transacció</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>Augmenta la comissió de transacció</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Copia l'adreça</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copia l'etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copia l'import</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copia l'ID de transacció</translation>
+ </message>
+ <message>
+ <source>Copy raw transaction</source>
+ <translation>Copia la transacció crua</translation>
+ </message>
+ <message>
+ <source>Copy full transaction details</source>
+ <translation>Copia els detalls complets de la transacció</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Editar etiqueta</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Mostra detalls de la transacció</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>Exporta l'historial de transacció</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Fitxer separat per comes (*.csv)</translation>
</message>
<message>
+ <source>Confirmed</source>
+ <translation>Confirmat</translation>
+ </message>
+ <message>
+ <source>Watch-only</source>
+ <translation>Només de lectura</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Tipus</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Etiqueta</translation>
</message>
@@ -472,22 +2861,102 @@
<translation>Adreça</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>L'exportació ha fallat</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>S'ha produït un error en provar de desar l'historial de transacció a %1.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Exportació amb èxit</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>L'historial de transaccions s'ha desat correctament a %1.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Rang:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>a</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
- </context>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation>Unitat en què mostrar els imports. Feu clic per seleccionar una altra unitat.</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation>Tanca la cartera</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>No s'ha carregat cap cartera.</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
- </context>
+ <message>
+ <source>Send Coins</source>
+ <translation>Envia monedes</translation>
+ </message>
+ <message>
+ <source>Fee bump error</source>
+ <translation>Error de recàrrec de tarifes</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>S'ha produït un error en augmentar la tarifa de transacció</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>Voleu augmentar la tarifa?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>tarifa actual:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>Increment:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>Nova tarifa:</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation>Confirmeu el recàrrec de tarifes</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>No es pot signar la transacció.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>No s'ha pogut confirmar la transacció</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>cartera predeterminada</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
@@ -498,8 +2967,436 @@
<source>Export the data in the current tab to a file</source>
<translation>Exporta les dades de la pestanya actual a un fitxer</translation>
</message>
- </context>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Còpia de seguretat de la cartera</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>Dades de cartera (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Ha fallat la còpia de seguretat</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>S'ha produït un error en provar de desar les dades de la cartera a %1.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>La còpia de seguretat s'ha realitzat correctament</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>S'han desat correctament %1 les dades de la cartera a .</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>Cancel·la</translation>
+ </message>
+</context>
<context>
<name>bitcoin-core</name>
- </context>
+ <message>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation>Distribuït sota la llicència del programari MIT, consulteu el fitxer d'acompanyament %s o %s</translation>
+ </message>
+ <message>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation>Poda configurada per sota el mínim de %d MiB. Utilitzeu un nombre superior.</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>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>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>No s'ha pogut iniciar el servidor HTTP. Vegeu debug.log per a més detalls.</translation>
+ </message>
+ <message>
+ <source>The %s developers</source>
+ <translation>Els desenvolupadors %s</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>
+ <message>
+ <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation>S'ha produït un error en llegir %s. Totes les claus es llegeixen correctament, però les dades de la transacció o les entrades de la llibreta d'adreces podrien faltar o ser incorrectes.</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>Comproveu que la data i hora de l'ordinador són correctes. Si el rellotge és incorrecte, %s no funcionarà correctament.</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Contribueix si trobes %s útil. Visita %s per obtenir més informació sobre el programari.</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 dades de blocs conté un bloc que sembla ser del futur. Això pot ser degut a que la data i l'hora del vostre ordinador s'estableix incorrectament. Només reconstruïu la base de dades de blocs si esteu segur que la data i l'hora del vostre ordinador són correctes</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>Aquesta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>Aquesta és la tarifa de transacció que podeu descartar si el canvi és menor que el polsim a aquest nivell</translation>
+ </message>
+ <message>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>No es poden reproduir els blocs. Haureu de reconstruir la base de dades mitjançant -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>No es pot rebobinar la base de dades a un estat de pre-bifurcament. Haureu de tornar a descarregar la cadena de blocks</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Avís: la xarxa no sembla que hi estigui plenament d'acord. Alguns miners sembla que estan experimentant problemes.</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>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>
+ <message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>No es pot resoldre -%s adreça: '%s'</translation>
+ </message>
+ <message>
+ <source>Change index out of range</source>
+ <translation>Canvieu l'índex fora de l'abast</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Copyright (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation>S'ha detectat una base de dades de blocs corrupta</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>Voleu reconstruir la base de dades de blocs ara?</translation>
+ </message>
+ <message>
+ <source>Error initializing block database</source>
+ <translation>Error carregant la base de dades de blocs</translation>
+ </message>
+ <message>
+ <source>Error initializing wallet database environment %s!</source>
+ <translation>Error inicialitzant l'entorn de la base de dades de la cartera %s!</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>Error carregant %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>S'ha produït un error en carregar %s: la cartera és corrupta</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>S'ha produït un error en carregar %s: la cartera requereix una versió més nova de %s</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation>Error carregant la base de dades del bloc</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation>Error en obrir la base de dades de blocs</translation>
+ </message>
+ <message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation>Ha fallat escoltar a qualsevol port. Feu servir -listen=0 si voleu fer això.</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>S'està important...</translation>
+ </message>
+ <message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation>No s'ha trobat el bloc de gènesi o és incorrecte. El directori de dades de la xarxa és incorrecte?</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>S'ha produït un error en la verificació de sanejament d'inicialització. S'està tancant %s.</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>Import invàlid per -%s=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation>Import invàlid per -discardfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation>Import invàlid per -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>S'estan carregant les adreces P2P ...</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>Carregant banlist ...</translation>
+ </message>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation>No hi ha suficient descriptors de fitxers disponibles.</translation>
+ </message>
+ <message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation>La poda no es pot configurar amb un valor negatiu.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation>El mode de poda és incompatible amb -txindex.</translation>
+ </message>
+ <message>
+ <source>Replaying blocks...</source>
+ <translation>Reproduïnt blocs ...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>Rebobinant blocs...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation>El codi font està disponible a %s.</translation>
+ </message>
+ <message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>La tarifa de transacció i el càlcul del canvi no han funcionat</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation>No es pot enllaçar a %s en aquest ordinador. %s probablement ja s'estigui executant.</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation>No s'han pogut generar les claus</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation>Categoria de registre no admesa %s=%s.</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>Actualització de la base de dades UTXO</translation>
+ </message>
+ <message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation>El comentari de l'agent d'usuari (%s) conté caràcters insegurs.</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>S'estan verificant els blocs...</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>Cal tornar a escriure la cartera: reinicieu %s per a completar-ho</translation>
+ </message>
+ <message>
+ <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
+ <translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'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>Import no vàlid per a -maxtxfee=&lt;amount&gt;: '%s' (cal que sigui com a mínim la comissió de minrelay de %s per evitar que les comissions s'encallin)</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</source>
+ <translation>L'import de la transacció és massa petit per enviar-la després que se'n dedueixi la comissió</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>Cal que torneu a construir la base de dades fent servir -reindex per tornar al mode no podat. Això tornarà a baixar la cadena de blocs sencera</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation>Error en llegir la base de dades, tancant.</translation>
+ </message>
+ <message>
+ <source>Error upgrading chainstate database</source>
+ <translation>S'ha produït un error en actualitzar la base de dades de chainstate</translation>
+ </message>
+ <message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Adreça o nom de l'ordinador -onion no vàlida: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>Adreça o nom de l'ordinador -proxy no vàlida: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
+ <translation>Import no vàlid per a -paytxfee=&lt;amount&gt;: «%s» (ha de ser com a mínim %s)</translation>
+ </message>
+ <message>
+ <source>Invalid netmask specified in -whitelist: '%s'</source>
+ <translation>S'ha especificat una màscara de xarxa no vàlida a -whitelist: «%s»</translation>
+ </message>
+ <message>
+ <source>Need to specify a port with -whitebind: '%s'</source>
+ <translation>Cal especificar un port amb -whitebind: «%s»</translation>
+ </message>
+ <message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation>Reducció de -maxconnections de %d a %d, a causa de les limitacions del sistema.</translation>
+ </message>
+ <message>
+ <source>Section [%s] is not recognized.</source>
+ <translation>No es reconeix la secció [%s]</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation>Ha fallat la signatura de la transacció</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation>L'import de la transacció és massa petit per pagar-ne una comissió</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>Aquest és programari experimental.</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>La transacció és massa petita</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>La transacció és massa gran</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation>No s'ha pogut vincular a %s en aquest ordinador (la vinculació ha retornat l'error %s)</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation>No s'han pogut generar les claus inicials</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>S'estan verificant les carteres...</translation>
+ </message>
+ <message>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <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>
+ <message>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>Aquesta és la tarifa de transacció que podeu pagar quan les estimacions de tarifes no estan disponibles.</translation>
+ </message>
+ <message>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <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>
+ <message>
+ <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
+ <translation>S'ha produït un error en carregar la cartera %s. S'ha especificat un nom de fitxer duplicat -wallet.</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>S'estan iniciant els fils de la xarxa...</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>La cartera evitarà pagar menys de la comissió de tramesa mínima</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>Aquesta és la comissió mínima de transacció que paga en cada transacció.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>Aquesta és la comissió de transacció que pagareu si envieu una transacció.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>Els imports de la transacció no han de ser negatius</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>La transacció té massa temps d'una cadena de mempool</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>La transacció ha de tenir com a mínim un destinatari</translation>
+ </message>
+ <message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation>Xarxa desconeguda especificada a -onlynet: '%s'</translation>
+ </message>
+ <message>
+ <source>Insufficient funds</source>
+ <translation>Balanç insuficient</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>No es pot escriure en el directori de dades "%s". Reviseu-ne els permisos.</translation>
+ </message>
+ <message>
+ <source>Loading block index...</source>
+ <translation>S'està carregant l'índex de blocs...</translation>
+ </message>
+ <message>
+ <source>Loading wallet...</source>
+ <translation>S'està carregant la cartera...</translation>
+ </message>
+ <message>
+ <source>Cannot downgrade wallet</source>
+ <translation>No es pot reduir la versió de la cartera</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>S'està reescanejant...</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation>Ha acabat la càrrega</translation>
+ </message>
+</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts
index 97bfeb02f5..70334087e8 100644
--- a/src/qt/locale/bitcoin_cs.ts
+++ b/src/qt/locale/bitcoin_cs.ts
@@ -70,6 +70,10 @@
<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>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;Kopíruj adresu</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Totéž heslo ještě jednou</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Ukaž heslo</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Zašifruj peněženku</translation>
</message>
@@ -172,6 +180,30 @@
<translation>Peněženka je zašifrována</translation>
</message>
<message>
+ <source>Enter the new passphrase for the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Zadej nové heslo k peněžence.&lt;br/&gt;Použij &lt;b&gt;alespoň deset náhodných znaků&lt;/b&gt; nebo &lt;b&gt;alespoň osm slov&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Zadej staré a nové heslo k peněžence.</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>Pamatujte, že zašifrování peněženky nemůže plně ochránit vaše bitcoiny před krádeží, pokud by byl váš počítač napadem malwarem.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Peněženka k zašifrování</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Vaše peněženka bude zašifrována.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Vaše peněženka je zašifrovaná.</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>DŮLEŽITÉ: Všechny předchozí zálohy peněženky by měly být nahrazeny nově vygenerovanou, zašifrovanou peněženkou. Z bezpečnostních důvodů budou předchozí zálohy nešifrované peněženky nepoužitelné, jakmile začneš používat novou zašifrovanou peněženku.</translation>
</message>
@@ -294,6 +326,14 @@
<translation>Načíst &amp;URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Vytvoř peněženku...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Vytvoř novou peněženku</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Peněženka:</translation>
</message>
@@ -334,14 +374,6 @@
<translation>Změň heslo k šifrování peněženky</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Ladicí okno</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Otevři ladicí a diagnostickou konzoli</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Ověř zprávu...</translation>
</message>
@@ -402,10 +434,6 @@
<translation>Ukaž seznam použitých přijímacích adres a jejich označení</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Načti bitcoin: URI nebo platební požadavek</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Ar&amp;gumenty příkazové řádky</translation>
</message>
@@ -832,10 +860,6 @@
<translation>verze</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>O %1</translation>
</message>
@@ -969,25 +993,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Načíst URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Načíst platební požadavek z URI nebo ze souboru</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Vyber soubor platebního požadavku</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Vyber soubor platebního požadavku k načtení</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1369,18 +1377,6 @@
<translation>'bitcoin://' není platné URI. Místo toho použij 'bitcoin:'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Používáte BIP70 URL, která nebude v budoucnosti podporovaná.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Zdrojová URL platebního požadavku není platná: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Není možné zpracovat platební požadavek, protože podpora pro BIP70 platby nebyla přikompilována.</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>Neplatná platební adresa %1</translation>
</message>
@@ -1392,66 +1388,6 @@
<source>Payment request file handling</source>
<translation>Zpracování souboru platebního požadavku</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Soubor platebního požadavku nejde přečíst nebo zpracovat! Příčinou může být špatný soubor platebního požadavku.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Platební požadavek byl odmítnut</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Síť platebního požadavku neodpovídá síti klienta.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Platební požadavek vypršel.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Platební požadavek není zahájený.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Neověřené platební požadavky k uživatelským platebním skriptům nejsou podporované.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Neplatný platební požadavek.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Požadovaná platební částka %1 je příliš malá (je považována za prach).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Vrácení peněz od %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Platební požadavek %1 je moc velký (%2 bajtů, povoleno %3 bajtů).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Chyba při komunikaci s %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Platební požadavek je nečitelný!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Chybná odpověď ze serveru %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Chyba síťového požadavku</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Platba potvrzena</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1625,10 +1561,6 @@
<translation>&amp;Informace</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Ladicí okno</translation>
- </message>
- <message>
<source>General</source>
<translation>Obecné</translation>
</message>
@@ -2165,10 +2097,6 @@
<translation>Upozornění: teď není možné poplatek odhadnout.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>sbal nastavení poplatků</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>
@@ -2317,6 +2245,10 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Potvrď odeslání mincí</translation>
</message>
<message>
+ <source>Send</source>
+ <translation>Pošli</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Adresa příjemce je neplatná – překontroluj ji prosím.</translation>
</message>
@@ -2341,10 +2273,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Vytvoření transakce selhalo!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Transakce byla zamítnuta s tímto odůvodněním: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Poplatek vyšší než %1 je považován za absurdně vysoký.</translation>
</message>
@@ -2396,10 +2324,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Vyber již použitou adresu</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Tohle je normální platba.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Bitcoinová adresa příjemce</translation>
</message>
@@ -2459,17 +2383,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<source>Memo:</source>
<translation>Poznámka:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Zadej označení této adresy; obojí se ti pak uloží do adresáře</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ano</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -3198,10 +3111,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>V prořezávacím režimu není možné blockchain přeskenovávat. Musíš provést -reindex, což jej znovu celý stáhne.</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>
@@ -3568,10 +3477,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Toto je transakční poplatek, který se platí, pokud náhodou není k dispozici odhad poplatků.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Tento produkt zahrnuje programy vyvinuté OpenSSL Projektem pro použití v OpenSSL Toolkitu %s a kryptografický program od Erika Younga a program UPnP od Thomase Bernarda.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
diff --git a/src/qt/locale/bitcoin_cs_CZ.ts b/src/qt/locale/bitcoin_cs_CZ.ts
deleted file mode 100644
index f53e12bd11..0000000000
--- a/src/qt/locale/bitcoin_cs_CZ.ts
+++ /dev/null
@@ -1,691 +0,0 @@
-<TS language="cs_CZ" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Pravým klikem editujte adresu nebo popisek</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Vytvořit novou adresu</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Nový</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Kopírovat aktuálně vybrané adresy do schránky</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Kopírovat</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>Z&amp;avřít</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Odstraní aktuálně vybrané adresy ze seznamu</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportovat aktuální pohled do souboru</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportovat</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Odstranit</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>V&amp;ybrat</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Kopírovat adresu</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Upravit</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Textový soubor oddělený středníkem (*.csv)</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Popis</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez popisu)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Enter passphrase</source>
- <translation>Zadej heslo</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Nové heslo</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Zopakujte nové heslo</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Zobrazit heslo</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Zašifrovat peněženku</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Tato operace vyžaduje heslo k odemknutí peněženky.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Odemknout peněženku</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Tato operace vyžaduje heslo k dešifrování peněženky.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Dešifrovat peněženku</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Změnit heslo</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Potvrďte zašifrování peněženky</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Peněženka zašifrována</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Zašifrování peněženky selhalo</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Šifrování peněženky selhalo vinou vnitřní chyby. Vaše peněženka nebyla zašifrována.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Zadaná hesla nejsou shodná.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Odemčení peněženky selhalo</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Heslo zadané k dešifrování peněženky nebylo správné</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Deěifrování peněženky selhalo</translation>
- </message>
- </context>
-<context>
- <name>BanTableModel</name>
- </context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Synchronizuji se sítí...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Přehled</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Uzel</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Zobrazit základní přehled o peněžence</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transakce</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Procházení historií transakcí</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Ukončit aplikaci</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Možnosti...</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Změnit heslo k šifrování peněženky</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Peněženka</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Soubor</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Nastavení</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>Nápo&amp;věda</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Panely</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Aktuální</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Zachytávám...</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Odeslané transakce</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Příchozí transakce</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>Peněženka je &lt;b&gt;zašifrována&lt;/b&gt; a momentálně &lt;b&gt;odemčená&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>Peněženka je &lt;b&gt;zašifrována&lt;/b&gt; a momentálně &lt;b&gt;uzamčená&lt;/b&gt;</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Amount:</source>
- <translation>Množství:</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Množství</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Potvrzeno</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Kopírovat sdresu</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Kopírovat popis</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez popisu)</translation>
- </message>
- </context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Upravit adresu</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Popisek</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Adresa</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Nová adresa k odeslání</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Upravit adresu pro příjem</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Upravit adresu k odeslání</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Nemohu odemknout peněženku</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Generování nového klíče selhalo.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- </context>
-<context>
- <name>HelpMessageDialog</name>
- </context>
-<context>
- <name>Intro</name>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- </context>
-<context>
- <name>OpenURIDialog</name>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Možnosti</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Mapovat port pomocí &amp;UPnP</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimalizovat do systémové lišty (tray) namísto do hlavního panelu</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>M&amp;inimalizovat při zavření</translation>
- </message>
- </context>
-<context>
- <name>OverviewPage</name>
- </context>
-<context>
- <name>PaymentServer</name>
- </context>
-<context>
- <name>PeerTableModel</name>
- </context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Množství</translation>
- </message>
- </context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>Name</source>
- <translation>Jméno</translation>
- </message>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Popisek:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>Zpráva:</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Kopírovat popis</translation>
- </message>
- </context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Množství</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Popis</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>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Popis</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Zpráva</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez popisu)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Amount:</source>
- <translation>Množství:</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Zůstatek:</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation>Částka k zaplacení musí být větší než 0.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez popisu)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Popisek:</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Zpráva:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- </context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>%1/unconfirmed</source>
- <translation>%1 potvrzeno</translation>
- </message>
- <message>
- <source>%1 confirmations</source>
- <translation>%1 potvrzení</translation>
- </message>
- <message>
- <source>Status</source>
- <translation>Stav</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Zpráva</translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation>Transakce</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Množství</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Toto podokno zobrazuje detailní popis transakce</translation>
- </message>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Typ</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Popis</translation>
- </message>
- <message>
- <source>Confirmed (%1 confirmations)</source>
- <translation>Potvrzeno (%1 potvrzení)</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Přijato s</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Odesláno na</translation>
- </message>
- <message>
- <source>Payment to yourself</source>
- <translation>Platba sobě samému</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Vytěženo</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez popisu)</translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation>Typ transakce.</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Vše</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Dnes</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>Tento týden</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>Tento měsíc</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Minulý měsíc</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Tento rok</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Rozsah...</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Přijato s</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Odesláno na</translation>
- </message>
- <message>
- <source>To yourself</source>
- <translation>Sobě samému</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Vytěženo</translation>
- </message>
- <message>
- <source>Other</source>
- <translation>Ostatní</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation>Min. množství</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Kopírovat sdresu</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Kopírovat popis</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Upravit popis</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Textový soubor oddělený středníkem (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Potvrzeno</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Typ</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Popis</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>ID</source>
- <translation>ID</translation>
- </message>
- <message>
- <source>Range:</source>
- <translation>Rozsah:</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportovat</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportovat aktuální pohled do souboru</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Loading wallet...</source>
- <translation>Načítání peněženky...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Načítání dokončeno</translation>
- </message>
- </context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_cy.ts b/src/qt/locale/bitcoin_cy.ts
index b28e88651d..3f053f7be6 100644
--- a/src/qt/locale/bitcoin_cy.ts
+++ b/src/qt/locale/bitcoin_cy.ts
@@ -30,6 +30,10 @@
<translation>Dileu'r cyfeiriad presennol wedi ei ddewis o'r rhestr</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Cyfeiriad neu label i chwilio</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Allforio'r data yn y tab presennol i ffeil</translation>
</message>
@@ -43,7 +47,7 @@
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Dewis y cyfeiriad i yrru'r arian </translation>
+ <translation>Dewis y cyfeiriad i yrru'r arian</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
@@ -161,7 +165,11 @@
</message>
<message>
<source>Wallet encrypted</source>
- <translation>Waled Wedi Amgryptio</translation>
+ <translation>Waled wedi amgryptio</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Waled i'w amgryptio</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>
@@ -193,7 +201,7 @@
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
- <translation>Newid cyfrinair waled yn llwyddiannus. </translation>
+ <translation>Newid cyfrinair waled yn llwyddiannus.</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
@@ -322,10 +330,6 @@
<translation>Newid y cyfrinair ddefnyddiwyd ar gyfer amgryptio'r waled</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Di fygio'r ffenest</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Gwirio neges...</translation>
</message>
@@ -386,10 +390,6 @@
<translation>Dangos rhestr o gyfeiriadau derbyn a labelau wedi eu defnyddio</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Agor Bitcoin: URI neu ofyn taliad</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Dewisiadau Gorchymyn-llinell</translation>
</message>
@@ -458,6 +458,14 @@
<translation>Dal i fyny...</translation>
</message>
<message>
+ <source>Error: %1</source>
+ <translation> Gwall: %1</translation>
+ </message>
+ <message>
+ <source>Warning: %1</source>
+ <translation>Rhybudd: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Dyddiad: %1
@@ -470,6 +478,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Waled: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Math: %1
@@ -528,23 +542,23 @@
</message>
<message>
<source>Bytes:</source>
- <translation>Maint</translation>
+ <translation>Maint:</translation>
</message>
<message>
<source>Amount:</source>
- <translation>Cyfanswm</translation>
+ <translation>Cyfanswm:</translation>
</message>
<message>
<source>Fee:</source>
- <translation>Ffî</translation>
+ <translation>Ffî:</translation>
</message>
<message>
<source>Dust:</source>
- <translation>Llwch</translation>
+ <translation>Llwch:</translation>
</message>
<message>
<source>After Fee:</source>
- <translation>Ar Ôl Ffî</translation>
+ <translation>Ar Ôl Ffî:</translation>
</message>
<message>
<source>Change:</source>
@@ -584,13 +598,17 @@
</message>
<message>
<source>Copy amount</source>
- <translation>Copïo Cyfanswm</translation>
+ <translation>Copïo cyfanswm</translation>
</message>
<message>
<source>(no label)</source>
<translation>(dim label)</translation>
</message>
- </context>
+ <message>
+ <source>(change)</source>
+ <translation>(newid)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
</context>
@@ -611,7 +629,27 @@
<source>&amp;Address</source>
<translation>&amp;Cyfeiriad</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Cyfeiriad anfon newydd</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Golygu'r cyfeiriad derbyn</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Golygu'r cyfeiriad anfon</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Methodd ddatgloi'r waled.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Methodd gynhyrchu allwedd newydd.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
@@ -647,14 +685,10 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Agor URI</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
</context>
@@ -720,6 +754,10 @@
<source>%1 and %2</source>
<translation>%1 a %2</translation>
</message>
+ <message>
+ <source>Error: %1</source>
+ <translation> Gwall: %1</translation>
+ </message>
</context>
<context>
<name>QRImageWidget</name>
@@ -773,6 +811,10 @@
<translation>Label</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Neges</translation>
+ </message>
+ <message>
<source>Wallet</source>
<translation>Waled</translation>
</message>
@@ -788,6 +830,10 @@
<translation>Label</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Neges</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(dim label)</translation>
</message>
@@ -843,6 +889,10 @@
<translation>Copïo Cyfanswm</translation>
</message>
<message>
+ <source>%1 to %2</source>
+ <translation>%1 i %2</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(dim label)</translation>
</message>
@@ -875,9 +925,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -901,10 +948,18 @@
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>Agor tan %1</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Dyddiad</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Neges</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Cyfanswm</translation>
</message>
@@ -927,6 +982,10 @@
<translation>Label</translation>
</message>
<message>
+ <source>Open until %1</source>
+ <translation>Agor tan %1</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(dim label)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts
index 3383052009..0fb4d104aa 100644
--- a/src/qt/locale/bitcoin_da.ts
+++ b/src/qt/locale/bitcoin_da.ts
@@ -71,7 +71,7 @@
</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>
+ <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>
@@ -374,14 +374,6 @@
<translation>Skift adgangskode anvendt til tegnebogskryptering</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Fejlsøgningsvindue</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Åbn fejlsøgnings- og diagnosticeringskonsollen</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verificér besked…</translation>
</message>
@@ -442,10 +434,6 @@
<translation>Vis listen over brugte modtagelsesadresser og -mærkater</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Åbn en “bitcoin:”-URI eller betalingsanmodning</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Tilvalg for &amp;kommandolinje</translation>
</message>
@@ -494,6 +482,14 @@
<translation>Opdateret</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Knudevindue</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Åbn knudens fejlsøgningskonsol</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>&amp;Afsenderadresser</translation>
</message>
@@ -502,6 +498,10 @@
<translation>&amp;Modtageradresser</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Åbn en bitcoin:-URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Åben Tegnebog</translation>
</message>
@@ -924,10 +924,6 @@
<translation>version</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Om %1</translation>
</message>
@@ -1066,6 +1062,14 @@
<translation>Skjul</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 synkroniserer lige nu. Hoveder og blokke bliver downloadet og valideret fra andre knuder. Processen fortsætter indtil den seneste blok nås.</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>Ukendt. Synkroniserer Hoveder (%1, %2%)...</translation>
</message>
@@ -1073,25 +1077,13 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Åbn URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Åbn betalingsanmodning fra URI eller fil</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Åbn bitcoin-URI</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Vælg fil for betalingsanmodning</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Vælg fil for betalingsanmodning til åbning</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1478,23 +1470,15 @@
</message>
<message>
<source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
- <translation>'bitcoin://' er ikke et gyldigt URI. Brug 'bitcoin:' istedet. </translation>
+ <translation>'bitcoin://' er ikke et gyldigt URI. Brug 'bitcoin:' istedet.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Du anvender et BIP70 URL hvilket ikke vil være understøttet i fremtiden.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Hentnings-URL for betalingsanmodning er ugyldig: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Kan ikke behandle betalingsanmodningen, da BIP70-understøttelse ikke er medtaget under programkodeoversættelsen.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>Betalingsanmodninger kan ikke behandles mere, da BIP70 ikke længere er understøttet.</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>På grund af vidtstrakte sikkerhedsfejl i BIP70 anbefales det kraftigt, at enhver instruktion til handlende om at skifte tegnebog ignoreres.</translation>
+ <translation>På grund af vidtstrakte sikkerhedsfejl i BIP70 anbefales det kraftigt, at enhver instruktion fra handlende om at skifte til en BIP70-tegnebog ignoreres.</translation>
</message>
<message>
<source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
@@ -1512,66 +1496,6 @@
<source>Payment request file handling</source>
<translation>Filhåndtering for betalingsanmodninger</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Fil for betalingsanmodning kan ikke læses! Dette kan skyldes en ugyldig fil for betalingsanmodning.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Betalingsanmodning afvist</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Netværk for betalingsanmodning stemmer ikke overens med klientens netværk.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Betalingsanmodning er udløbet.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Betalingsanmodning er ikke klargjort.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Ikke-verificerede betalingsanmodninger for tilpassede betalings-scripts understøttes ikke.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Ugyldig betalingsanmodning.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Anmodet betalingsbeløb på %1 er for lille (regnes som støv).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Tilbagebetaling fra %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Betalingsanmodning %1 er for stor (%2 byte; %3 byte tilladt).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Fejl under kommunikation med %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Betalingsanmodning kan ikke tolkes!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Fejlagtigt svar fra server %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Fejl i netværksforespørgsel</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Betaling anerkendt</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1749,10 +1673,6 @@
<translation>&amp;Information</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Fejlsøgningsvindue</translation>
- </message>
- <message>
<source>General</source>
<translation>Generelt</translation>
</message>
@@ -1862,7 +1782,7 @@
</message>
<message>
<source>Synced Headers</source>
- <translation>Synkroniserede headers</translation>
+ <translation>Synkroniserede hoveder</translation>
</message>
<message>
<source>Synced Blocks</source>
@@ -1873,6 +1793,10 @@
<translation>Brugeragent</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Knudevindue</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>Åbn %1s fejlsøgningslogfil fra den aktuelle datamappe. Dette kan tage nogle få sekunder for store logfiler.</translation>
</message>
@@ -2084,6 +2008,14 @@
<translation>Et valgfrit beløb til anmodning. Lad dette felt være tomt eller indeholde nul for at anmode om et ikke-specifikt beløb.</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>Et valgfrit mærkat, der associeres med den nye modtagelsesadresse. Det bruges til at identificere en faktura. Det er også indlejret i betalingsanmodningen.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>En valgfri meddelelse som er indlejret i betalingsanmodningen og som kan blive vist til afsenderen.</translation>
+ </message>
+ <message>
<source>&amp;Create new receiving address</source>
<translation>&amp;Opret ny modtager adresse</translation>
</message>
@@ -2293,10 +2225,6 @@
<translation>Advarsel: Gebyrestimering er ikke muligt i øjeblikket.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>sammenfold gebyropsætning</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>
@@ -2341,6 +2269,10 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Støv:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Skjul indstillinger for transaktionsgebyr</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>På tidspunkter, hvor der er færre transaktioner, end der er plads til i nye blokke, kan minere og videresendende knuder gennemtvinge et minimumsgebyr. Du kan vælge kun at betale dette minimumsgebyr, men vær opmærksom på, at det kan resultere i en transaktion, der aldrig bliver bekræftet, hvis mængden af nye bitcoin-transaktioner stiger til mere, end hvad netværket kan behandle ad gangen.</translation>
</message>
@@ -2409,6 +2341,10 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>%1 (%2 blokke)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>L&amp;av usigneret</translation>
+ </message>
+ <message>
<source> from wallet '%1'</source>
<translation>fra tegnebog '%1'</translation>
</message>
@@ -2421,6 +2357,10 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>%1 til %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Vil du lave et udkast til denne transaktion?</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<translation>Er du sikker på, at du vil sende?</translation>
</message>
@@ -2457,6 +2397,26 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Bekræft afsendelse af bitcoins</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Modtageradressen er ikke gyldig. Tjek venligst igen.</translation>
</message>
@@ -2481,10 +2441,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Oprettelse af transaktion mislykkedes!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Transaktionen blev afvist med følgende begrundelse: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Et gebyr højere end %1 opfattes som et absurd højt gebyr.</translation>
</message>
@@ -2536,10 +2492,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Vælg tidligere brugt adresse</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Dette er en normal betaling.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Bitcoin-adresse, som betalingen skal sendes til</translation>
</message>
@@ -2560,6 +2512,10 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Fjern denne indgang</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>Beløbet der skal afsendes i den valgte enhed</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>Gebyret vil blive trukket fra det sendte beløb. Modtageren vil modtage færre bitcoin, end du indtaster i beløbfeltet. Hvis flere modtagere vælges, vil gebyret deles ligeligt.</translation>
</message>
@@ -2599,17 +2555,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Indtast en mærkat for denne adresse for at føje den til din adressebog</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2697,6 +2642,14 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Bitcoin-adressen, som beskeden blev signeret med</translation>
</message>
<message>
+ <source>The signed message to verify</source>
+ <translation>Den signerede meddelelse som skal verificeres</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>Signaturen som blev givet da meddelelsen blev signeret</translation>
+ </message>
+ <message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
<translation>Verificér beskeden for at sikre, at den er signeret med den angivne Bitcoin-adresse</translation>
</message>
@@ -2729,6 +2682,10 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Tegnebogsoplåsning annulleret.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Ingen fejl</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>Den private nøgle for den indtastede adresse er ikke tilgængelig.</translation>
</message>
@@ -2903,6 +2860,10 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Outputindeks</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(certifikat er ikke verificeret)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Forretningsdrivende</translation>
</message>
@@ -3260,6 +3221,10 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Vil du forøge gebyret?</translation>
</message>
<message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Vil du lave et transaktionsudkast med øget gebyr?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Aktuelt gebyr:</translation>
</message>
@@ -3276,6 +3241,14 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Bekræft gebyrforøgelse</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>Kan ikke lave transaktionsudkast.</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT kopieret</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Kan ikke signere transaktionen.</translation>
</message>
@@ -3342,10 +3315,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Genindlæsninger er ikke mulige i beskåret tilstand. Du er nødt til at bruge -reindex, hvilket vil downloade hele blokkæden igen.</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>
@@ -3363,7 +3332,7 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
</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>
+ <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>
@@ -3446,6 +3415,14 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Ødelagt blokdatabase opdaget</translation>
</message>
<message>
+ <source>Could not find asmap file %s</source>
+ <translation>Kan ikke finde asmap-filen %s </translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>Kan ikke fortolke asmap-filen %s</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Ønsker du at genopbygge blokdatabasen nu?</translation>
</message>
@@ -3539,7 +3516,7 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
</message>
<message>
<source>Error: Disk space is too low!</source>
- <translation>Fejl: Disk pladsen er for lav! </translation>
+ <translation>Fejl: Disk pladsen er for lav!</translation>
</message>
<message>
<source>Loading banlist...</source>
@@ -3736,10 +3713,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Dette er transaktionsgebyret, du kan betale, når gebyrestimeringer ikke er tilgængelige.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Dette produkt indeholder software, der er udviklet af OpenSSL-projektet for brug i OpenSSL-værktøjskassen %s, samt kryptografisk software, der er skrevet af Eric Young, samt UPnP-software, der er skrevet af Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation>Den totale længde på netværksversionsstrengen (%i) overstiger maksimallængden (%i). Reducér antaller af eller størrelsen på uacomments.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts
index e73bb22c75..ff763b002c 100644
--- a/src/qt/locale/bitcoin_de.ts
+++ b/src/qt/locale/bitcoin_de.ts
@@ -70,6 +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>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;Adresse kopieren</translation>
</message>
@@ -176,8 +180,28 @@
<translation>Wallet verschlüsselt</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>Geben Sie die neue Passphrase für die Wallet ein.&lt;br/&gt;Bitte benutzen Sie eine Passphrase bestehend aus &lt;b&gt;zehn oder mehr zufälligen Zeichen&lt;/b&gt; oder &lt;b&gt;acht oder mehr Wörtern&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Geben Sie die alte und die neue Wallet-Passphrase ein.</translation>
+ </message>
+ <message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>Beachten Sie, dass das Verschlüsseln Ihrer Brieftasche nicht komplett vor Diebstahl Ihrer Bitcoins durch Malware schützt, die Ihren Computer infiziert hat.</translation>
+ <translation>Beachten Sie, dass das Verschlüsseln Ihrer Wallet nicht komplett vor Diebstahl Ihrer Bitcoins durch Malware schützt, die Ihren Computer infiziert hat.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Wallet zu verschlüsseln</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Wallet wird verschlüsselt.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Deine Wallet ist jetzt verschlüsselt.</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>
@@ -302,6 +326,14 @@
<translation>&amp;URI öffnen...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Wallet erstellen...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Neue Wallet erstellen</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Wallet:</translation>
</message>
@@ -342,14 +374,6 @@
<translation>Ändert die Passphrase, die für die Wallet-Verschlüsselung benutzt wird</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Debug-Fenster</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Debugging- und Diagnosekonsole öffnen</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>Nachricht &amp;verifizieren...</translation>
</message>
@@ -410,10 +434,6 @@
<translation>Liste verwendeter Empfangsadressen und Bezeichnungen anzeigen</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Eine "bitcoin:"-URI oder Zahlungsanforderung öffnen</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Kommandozeilenoptionen</translation>
</message>
@@ -462,6 +482,14 @@
<translation>Auf aktuellem Stand</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Node Fenster</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Konsole für Node Debugging und Diagnose öffnen</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>&amp;Versandadressen</translation>
</message>
@@ -470,6 +498,10 @@
<translation>&amp;Empfangsadressen</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>bitcoin: URI öffnen</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Wallet öffnen</translation>
</message>
@@ -530,6 +562,10 @@
<translation>Fehler: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Warnung: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Datum: %1
@@ -751,7 +787,19 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Erstelle Wallet&lt;b&gt;%1&lt;/b&gt; ...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Fehler beim Wallet erstellen aufgetreten</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Warnung beim Wallet erstellen aufgetreten</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
<message>
@@ -759,6 +807,10 @@
<translation>Wallet erstellen</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>Verschlüssele das Wallet. Das Wallet wird mit einer Passphrase deiner Wahl verschlüsselt.</translation>
</message>
@@ -767,10 +819,22 @@
<translation>Wallet verschlüsseln</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>Deaktiviert private Schlüssel für dieses Wallet. Wallets mit deaktivierten privaten Schlüsseln werden keine privaten Schlüssel haben und können keinen HD Seed oder private Schlüssel importieren. Das ist ideal für Wallets, die nur beobachten.</translation>
+ </message>
+ <message>
<source>Disable Private Keys</source>
<translation>Private Keys deaktivieren</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>Erzeugt ein leeres Wallet. Leere Wallets haben zu Anfang keine privaten Schlüssel oder Scripte. Private Schlüssel oder Adressen können importiert werden, ebenso können jetzt oder später HD-Seeds gesetzt werden.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Eine leere Wallet erstellen</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Erstellen</translation>
</message>
@@ -860,10 +924,6 @@
<translation>Version</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-Bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Über %1</translation>
</message>
@@ -891,6 +951,10 @@
<translation>Wenn Sie auf OK klicken, beginnt %1 mit dem Herunterladen und Verarbeiten der gesamten %4-Blockchain (%2GB), beginnend mit den frühesten Transaktionen in %3 beim ersten Start von %4.</translation>
</message>
<message>
+ <source>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>Um diese Einstellung wiederherzustellen, muss die gesamte Blockchain neu heruntergeladen werden. Es ist schneller, die gesamte Chain zuerst herunterzuladen und später zu bearbeiten. Deaktiviert einige erweiterte Funktionen.</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>Diese initiale Synchronisation führt zur hohen Last und kann Harewareprobleme, die bisher nicht aufgetreten sind, mit ihrem Computer verursachen. Jedes Mal, wenn Sie %1 ausführen, wird der Download zum letzten Synchronisationspunkt fortgesetzt.</translation>
</message>
@@ -911,6 +975,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Verwerfe Blöcke nachdem sie verifiziert worden sind, ausser die %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>Mindestens %1 GB Daten werden in diesem Verzeichnis gespeichert, und sie werden mit der Zeit zunehmen.</translation>
</message>
@@ -942,7 +1010,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(von %n GB benötigt)</numerusform><numerusform>(von %n GB benötigt)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB benötigt für komplette Blockchain)</numerusform><numerusform>(%n GB benötigt für komplette Blockchain)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -990,6 +1062,14 @@
<translation>Ausblenden</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 synchronisiert gerade. Es lädt Header und Blöcke von anderen Nodes und validiert sie bis zum Erreichen der Spitze der Blockkette.</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>Unbekannt. Synchronisiere Headers (%1, %2%)...</translation>
</message>
@@ -997,28 +1077,24 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>URI öffnen</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Zahlungsanforderung über URI oder aus Datei öffnen</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Öffne bitcoin URI</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Zahlungsanforderungsdatei auswählen</translation>
+ <source>Open wallet failed</source>
+ <translation>Wallet öffnen fehlgeschlagen</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Zu öffnende Zahlungsanforderungsdatei auswählen</translation>
+ <source>Open wallet warning</source>
+ <translation>Wallet öffnen Warnung</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>Standard Wallet</translation>
@@ -1397,16 +1473,16 @@
<translation>'bitcoin://' ist kein gültiger URL. Bitte 'bitcoin:' nutzen.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Sie verwenden eine BIP70 URL, die in Zukunft nicht mehr untersützt wird.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>Zahlung kann aufgrund fehlender BIP70 Unterstützung nicht bearbeitet werden.</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Abruf-URL der Zahlungsanforderung ist ungültig: %1</translation>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Aufgrund der weit verbreiteten Sicherheitsmängel in BIP70 wird dringend empfohlen, dass alle Anweisungen des Händlers zum Wechseln von Wallets ignoriert werden.</translation>
</message>
<message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Zahlungsanfrage kann nicht verarbeitet werden, da die Unterstützung für BIP70 nicht mitkompiliert wurde.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Wenn du diese Fehlermeldung erhälst, solltest du Kontakt mit dem Händler aufnehmen und eine mit BIP21 kompatible URL zur Verwendung nachfragen.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1420,66 +1496,6 @@
<source>Payment request file handling</source>
<translation>Zahlungsanforderungsdatei-Verarbeitung</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Zahlungsanforderungsdatei kann nicht gelesen werden! Dies kann durch eine ungültige Zahlungsanforderungsdatei verursacht werden.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Zahlungsanforderung abgelehnt</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Netzwerk der Zahlungsanforderung stimmt nicht mit dem Client-Netzwerk überein.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Zahlungsanforderung abgelaufen.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Zahlungsanforderung ist nicht initialisiert.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Unverifizierte Zahlungsanforderungen an benutzerdefinierte Zahlungsskripte werden nicht unterstützt.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Ungültige Zahlungsanforderung.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Angeforderter Zahlungsbetrag in Höhe von %1 ist zu niedrig und wurde als "Staub" eingestuft.</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Rücküberweisung von %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Zahlungsanforderung %1 ist zu groß (%2 Byte, erlaubt sind %3 Byte).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Kommunikationsfehler mit %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Zahlungsanforderung kann nicht verarbeitet werden!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Fehlerhafte Antwort vom Server: %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Fehler bei der Netzwerkanfrage</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Zahlung bestätigt</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1630,6 +1646,10 @@
<translation>Beim Enkodieren der URI in den QR-Code ist ein Fehler aufgetreten.</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>QR Code Funktionalität nicht vorhanden</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>QR-Code speichern</translation>
</message>
@@ -1653,10 +1673,6 @@
<translation>Hinweis</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Debug-Fenster</translation>
- </message>
- <message>
<source>General</source>
<translation>Allgemein</translation>
</message>
@@ -1777,6 +1793,10 @@
<translation>User-Agent</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Node Fenster</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>
@@ -1988,6 +2008,18 @@
<translation>Ein optional angeforderter Betrag. Lassen Sie dieses Feld leer oder setzen Sie es auf 0, um keinen spezifischen Betrag anzufordern.</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>Ein optionales Etikett zu einer neuen Empfängeradresse (für dich zum Identifizieren einer Rechnung). Es wird auch der Zahlungsanforderung beigefügt.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Eine optionale Nachricht, die der Zahlungsanforderung beigefügt wird und dem Absender angezeigt werden kann.</translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation>Neue Empfangsadresse erstellen</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Alle Formularfelder zurücksetzen.</translation>
</message>
@@ -2193,10 +2225,6 @@
<translation>Achtung: Berechnung der Gebühr ist momentan nicht möglich.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>Transaktionsgebühren-Einstellungen ausblenden</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>
@@ -2241,6 +2269,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>"Dust":</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Einstellungen für Transaktionsgebühr nicht anzeigen</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>Nur die minimale Gebühr zu bezahlen ist so lange in Ordnung, wie weniger Transaktionsvolumen als Platz in den Blöcken vorhanden ist. Aber Vorsicht, diese Option kann dazu führen, dass Transaktionen nicht bestätigt werden, wenn mehr Bedarf an Bitcoin-Transaktionen besteht als das Netzwerk verarbeiten kann.</translation>
</message>
@@ -2309,14 +2341,38 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>%1 (%2 Blöcke)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Unsigniert erzeugen</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>Erzeugt eine teilsignierte Bitcoin Transaktion (PSBT) zur Benutzung mit z.B. einem Offline %1 Wallet, oder einem kompatiblen Hardware Wallet.</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation>von der Wallet '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 an '%2'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 an %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Möchtest du diesen Transaktionsentwurf anlegen?</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<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>
+ </message>
+ <message>
<source>or</source>
<translation>oder</translation>
</message>
@@ -2326,7 +2382,7 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
</message>
<message>
<source>Please, review your transaction.</source>
- <translation>Bitte überprüfen sie ihre Transaktion. </translation>
+ <translation>Bitte überprüfen sie ihre Transaktion.</translation>
</message>
<message>
<source>Transaction fee</source>
@@ -2341,10 +2397,34 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Gesamtbetrag</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Um die Empfängerliste anzuzeigen, klicke auf "Details anzeigen..."</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Überweisung bestätigen</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Die Zahlungsadresse ist ungültig, bitte nochmals überprüfen.</translation>
</message>
@@ -2369,10 +2449,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Transaktionserstellung fehlgeschlagen!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Die Transaktion wurde aus folgendem Grund abgelehnt: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Eine höhere Gebühr als %1 wird als unsinnig hohe Gebühr angesehen.</translation>
</message>
@@ -2424,10 +2500,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Bereits verwendete Adresse auswählen</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Dies ist eine normale Überweisung.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Die Zahlungsadresse der Überweisung</translation>
</message>
@@ -2448,6 +2520,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Diesen Eintrag entfernen</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>Zu sendender Betrag in der ausgewählten Einheit</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>Die Gebühr wird vom zu überweisenden Betrag abgezogen. Der Empfänger wird also weniger Bitcoins erhalten, als Sie im Betrags-Feld eingegeben haben. Falls mehrere Empfänger ausgewählt wurden, wird die Gebühr gleichmäßig verteilt.</translation>
</message>
@@ -2487,17 +2563,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Geben Sie eine Bezeichnung für diese Adresse ein, um sie zu Ihrem Adressbuch hinzuzufügen</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2585,6 +2650,14 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Die Bitcoin-Adresse mit der die Nachricht signiert wurde</translation>
</message>
<message>
+ <source>The signed message to verify</source>
+ <translation>Die zu überprüfende signierte Nachricht</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>Die beim Signieren der Nachricht geleistete Signatur</translation>
+ </message>
+ <message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
<translation>Die Nachricht verifizieren, um sicherzustellen, dass diese mit der angegebenen Bitcoin-Adresse signiert wurde</translation>
</message>
@@ -2617,6 +2690,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Wallet-Entsperrung wurde abgebrochen.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Kein Fehler</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>Privater Schlüssel zur eingegebenen Adresse ist nicht verfügbar.</translation>
</message>
@@ -2791,6 +2868,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Ausgabeindex</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(Zertifikat wurde nicht verifiziert)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Händler</translation>
</message>
@@ -3114,6 +3195,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Wallet schließen</translation>
</message>
<message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>Sind Sie sich sicher, dass Sie die Wallet &lt;i&gt;%1&lt;/i&gt; schließen möchten?</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>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>
@@ -3144,6 +3229,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Möchten Sie die Gebühr erhöhen?</translation>
</message>
<message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Möchtest du eine Transaktion mit erhöhter Gebühr entwerfen?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Aktuelle Gebühr:</translation>
</message>
@@ -3160,6 +3249,14 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Gebührenerhöhung bestätigen</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>Kann Transaktion nicht entwerfen.</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT kopiert</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Signierung der Transaktion fehlgeschlagen.</translation>
</message>
@@ -3226,10 +3323,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Rescans sind im gekürzten (Pruned) Modus nicht möglich. Sie müssen -reindex verwenden, um die gesamte Blockchain erneut herunterzuladen.</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>
@@ -3284,7 +3377,7 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
</message>
<message>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <translation>Fehler beim Verarbeiten von Blöcken. Sie müssen die Datenbank mit Hilfe des Arguments '-reindex-chainstate' neu aufbauen. </translation>
+ <translation>Fehler beim Verarbeiten von Blöcken. Sie müssen die Datenbank mit Hilfe des Arguments '-reindex-chainstate' neu aufbauen.</translation>
</message>
<message>
<source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
@@ -3331,6 +3424,14 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Beschädigte Blockdatenbank erkannt</translation>
</message>
<message>
+ <source>Could not find asmap file %s</source>
+ <translation>Konnte die asmap Datei %s nicht finden</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>Konnte die asmap Datei %s nicht analysieren</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Möchten Sie die Blockdatenbank jetzt neu aufbauen?</translation>
</message>
@@ -3388,6 +3489,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Initialisierungsplausibilitätsprüfung fehlgeschlagen. %s wird beendet.</translation>
</message>
<message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Ungültige P2P Genehmigung: '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
<translation>Ungültiger Betrag für -%s=&lt;amount&gt;: '%s'</translation>
</message>
@@ -3420,6 +3525,10 @@ 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>
@@ -3528,6 +3637,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>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Kürzungsmodus ist nicht mit -blockfilterindex kompatibel.</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reduziere -maxconnections von %d zu %d, aufgrund von Systemlimitierungen.</translation>
</message>
@@ -3610,10 +3723,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Das ist die Transaktionsgebühr, welche Sie zahlen müssten, wenn die Gebührenschätzungen nicht verfügbar sind.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Dieses Produkt enthält Software, die vom OpenSSL-Projekt zur Verwendung im OpenSSL-Toolkit %s entwickelt wird, von Eric Young geschriebene kryptographische Software und von Thomas Bernard geschriebene UPnP-Software.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation>Gesamtlänge des Netzwerkversionstrings (%i) erreicht die maximale Länge (%i). Reduzieren Sie die Nummer oder die Größe von uacomments.</translation>
</message>
@@ -3679,7 +3788,7 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
</message>
<message>
<source>Cannot write to data directory '%s'; check permissions.</source>
- <translation>Es konnte nicht in das Datenverzeichnis '%s' geschrieben werden; Überprüfen Sie die Berechtigungen. </translation>
+ <translation>Es konnte nicht in das Datenverzeichnis '%s' geschrieben werden; Überprüfen Sie die Berechtigungen.</translation>
</message>
<message>
<source>Loading block index...</source>
diff --git a/src/qt/locale/bitcoin_de_DE.ts b/src/qt/locale/bitcoin_de_DE.ts
deleted file mode 100644
index 8813c796fe..0000000000
--- a/src/qt/locale/bitcoin_de_DE.ts
+++ /dev/null
@@ -1,929 +0,0 @@
-<TS language="de_DE" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Rechtsklick um Adresse oder Etikett zu bearbeiten</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Eine neue Adresse erstellen</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Neu</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Aktive Adresse in die Zwischenablage kopieren</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Kopieren</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>Schliessen</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Ausgewählte Adresse aus der Liste löschen</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Daten des aktiven Fensters exportieren</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportieren</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Löschen</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Wähle die Empfängeradresse</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Wähle die Empfangsadresse</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>Auswählen</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Sendeadressen</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Empfangsadressen</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>Dies sind Ihre Bitcoin-Adressen zum Senden von Zahlungen. Überprüfen Sie immer die Menge und die Empfangsadresse, bevor Sie Bitcoins senden.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Dies sind Ihre Bitcoin-Adressen für den Empfang von Zahlungen. Es wird empfohlen, für jede Transaktion eine neue Empfangsadresse zu verwenden.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Kopiere Adresse</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Kopiere &amp;Etikett</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Bearbeiten</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Export Adressliste</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Komma getrenntes Dokument (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Export fehlgeschlagen</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Etikett</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresse</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(kein Etikett)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Passwort Dialog</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Passwort eingeben</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Neues Passwort</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Neues Passwort wiederholen</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Passwort anzeigen</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Geben Sie das neue Passwort Ihrer digitalen Geldbörse ein.&lt;br/&gt;Verwenden Sie bitte ein Passwort bestehend aus &lt;b&gt;zehn oder mehr zufälligen Zeichen&lt;/b&gt;, oder aus &lt;b&gt;acht oder mehr Wörtern&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Brieftasche verschlüsseln</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Diese Aktion benötigt ihr Passwort zum entsperren der Wallet.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Brieftasche entschlüsseln</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Diese Operation benötigt Ihr Wallet-Passwort zum entschlüsseln der Wallet.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Brieftasche entschlüsseln</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Passwort ändern</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Geben Sie das alte und neue Passwort Ihrer Wallet ein.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Brieftaschenverschlüsselung bestätigen</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Achtung: Wenn Sie Ihre Wallet verschlüsseln und das Passwort verlieren, gehen &lt;b&gt;alle Ihre Bitcoins verloren&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Möchten Sie Ihre Wallet wirklich verschlüsseln?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Brieftasche verschlüsselt</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>WICHTIG: Alle früheren Sicherungen, die Sie von Ihrer Wallet-Datei gemacht haben, sollten durch die neu erzeugte, verschlüsselte Wallet-Datei ersetzt werden. Sobald Sie die neue, verschlüsselte Wallet verwenden, werden frühere Sicherungen der unverschlüsselten Wallet-Datei aus Sicherheitsgründen nutzlos.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Brieftaschenverschlüsselung fehlgeschlagen</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Die Wallet-Verschlüsselung ist aufgrund eines internen Fehlers fehlgeschlagen. Ihre Wallet wurde nicht verschlüsselt.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Die eingegebenen Passwörter stimmen nicht überein.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Brieftasche öffnen fehlgeschlagen</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Inkorrektes Passwort um die Brieftasche zu entschlüsseln</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Brieftasche entschlüsseln fehlgeschlagen</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Brieftaschen Passwort erfolgreich geändert</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Achtung: Die Umschalttaste ist eingeschaltet!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netzmaske</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Gesperrt bis</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Über das Netzwerk abgleichen</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Übersicht</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Knoten</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Generelle Übersicht der Brieftasche </translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transaktionen</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Zeige Transaktionsverlauf</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>Beenden</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Programm beenden</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Über %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Zeige Informationen zu %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Über &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Informationen über Qt anzeigen</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Einstellungen...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Ändern Sie die Konfigurationsoptionen für %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Brieftasche verschlüsseln...</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>Sicherungskopie der Brieftasche...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Passwort ändern...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Adressen senden...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>&amp;Adressen empfangen...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Öffne &amp;URI...</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Klicken Sie, um die Netzwerkaktivität zu deaktivieren.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Netzwerkaktivität wurde deaktiviert.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Klicken Sie, um die Netzwerkaktivität wieder zu aktivieren.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Synchronisiere Header (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Reindexiere Blöcke auf dem Datenträger...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Coins an eine Bitcoin-Adresse senden</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Wallet an einen anderen Ort sichern</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Ändern Sie das Passwort, das für die Wallet-Verschlüsselung verwendet wird</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Debug Fenster</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Die Debugging- und Diagnosekonsole öffnen</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>Nachricht &amp;bestätigen</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Brieftasche</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Senden</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Empfangen</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;anzeigen / verstecken</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Das Hauptfenster ein- oder ausblenden</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Verschlüssele die Private Keys, die zu deiner Brieftasche gehören</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Nachrichten mit Ihrer Bitcoin-Adresse signieren, um zu beweisen, dass sie Ihnen gehören</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Überprüfen Sie Nachrichten, um sicherzustellen, dass sie mit den angegebenen Bitcoin-Adressen signiert wurden</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Datei</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Einstellungen</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Hilfe</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Registerkarten-Symbolleiste</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Liste der benutzten Sendeadressen und -etiketten</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Zeige Liste der benutzten Empfangsadressen und -etiketten</translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Indexiere Blöcke auf dem Datenträger...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Verarbeite Blöcke auf dem Datenträger...</translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 im Rückstand</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Transaktionen danach sind noch nicht sichtbar.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Fehler</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Achtung</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Information</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Auf dem neuesten Stand</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Aufholen...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Datum: %1</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Menge: %1</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Überweisung gesendet</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Überweisung empfangen</translation>
- </message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Ein schwerwiegender Fehler ist aufgetreten. Bitcoin kann nicht mehr sicher fortfahren und beendet sich.</translation>
- </message>
-</context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Quantity:</source>
- <translation>Anzahl:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Byte:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Betrag:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Gebühr:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Dust:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Nach Gebühr:</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Betrag</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Bestätigungen</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Bestätigt</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Adresse kopieren</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Etikett kopieren</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Betrag kopieren</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Transaktions ID kopieren</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Menge kopieren</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>Ja</translation>
- </message>
- <message>
- <source>no</source>
- <translation>Nein</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(kein Etikett)</translation>
- </message>
- </context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Adresse bearbeiten</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Etikett</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Adresse</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Neue Sendeadresse</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Empfangsadresse bearbeiten</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Sendeadresse bearbeiten</translation>
- </message>
- </context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>name</source>
- <translation>Name</translation>
- </message>
- </context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>Version</translation>
- </message>
- </context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Willkommen</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Fehler</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Formular</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Unbekannt...</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Error</source>
- <translation>Fehler</translation>
- </message>
- </context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Formular</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>Ping</source>
- <translation>Ping</translation>
- </message>
- </context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Betrag</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Bitcoin Adresse eingeben (z.B. %1)</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>N/A</translation>
- </message>
- </context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>N/A</translation>
- </message>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>Copy label</source>
- <translation>Etikett kopieren</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Betrag kopieren</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>Adresse</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Betrag</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etikett</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Brieftasche</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etikett</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(kein Etikett)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Quantity:</source>
- <translation>Anzahl:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Byte:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Betrag:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Gebühr:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Nach Gebühr:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Dust:</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Menge kopieren</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Betrag kopieren</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(kein Etikett)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- </context>
-<context>
- <name>SplashScreen</name>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Betrag</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etikett</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(kein Etikett)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Copy address</source>
- <translation>Adresse kopieren</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Etikett kopieren</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Betrag kopieren</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Transaktions ID kopieren</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Komma getrenntes Dokument (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Bestätigt</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etikett</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresse</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Export fehlgeschlagen</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportieren</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Daten des aktiven Fensters exportieren</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>Sicherung fehlgeschlagen</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Sicherung erfolgreich</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Information</source>
- <translation>Information</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Achtung</translation>
- </message>
- <message>
- <source>Starting network threads...</source>
- <translation>Starte Netzwerk-Threads...</translation>
- </message>
- <message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Das ist die Mindestgebühr für jede Transaktion</translation>
- </message>
- <message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Das ist die Gebühr für die Überweisung</translation>
- </message>
- <message>
- <source>Transaction amounts must not be negative</source>
- <translation>Überweisungsbetrag kann nicht negativ sein</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>Überweisung muss mindestens einen Empfänger haben </translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Ungenügendes Guthaben</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Block Verzeichnis laden...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Brieftasche laden...</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Neuscannen...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Laden abgeschlossen</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Fehler</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_el.ts b/src/qt/locale/bitcoin_el.ts
index 9267ecf33e..d903e2f85d 100644
--- a/src/qt/locale/bitcoin_el.ts
+++ b/src/qt/locale/bitcoin_el.ts
@@ -70,6 +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>Αυτές είναι οι Bitcoin διευθύνσεις για την λήψη πληρωμών. Χρησιμοποιήσε το κουμπί 'Δημιουργία νέας διεύθυνσης λήψεων' στο παράθυρο λήψεων για την δημιουργία νέας διεύθυνσης </translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;Αντιγραφή Διεύθυνσης</translation>
</message>
@@ -117,7 +121,7 @@
<name>AskPassphraseDialog</name>
<message>
<source>Passphrase Dialog</source>
- <translation>Φράση πρόσβασης </translation>
+ <translation>Φράση πρόσβασης</translation>
</message>
<message>
<source>Enter passphrase</source>
@@ -132,6 +136,10 @@
<translation>Επανέλαβε τον νέο κωδικό πρόσβασης</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Εμφάνισε τον κωδικό πρόσβασης</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>&amp;Κρυπτογράφηση πορτοφολιού</translation>
</message>
@@ -172,8 +180,32 @@
<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;δέκα ή περισσότερων τυχαίων χαρακτήρων &lt;/b&gt;, ή &lt;b&gt;οκτώ ή περισσότερες λέξεις&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Πληκτρολόγησε τον παλιό κωδικό πρόσβασής σου και τον νέο κωδικό πρόσβασής σου για το πορτοφόλι</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>Θυμίσου ότι το να κρυπτογραφείς το πορτοφόλι σου δεν μπορεί να προστατέψει πλήρως τα bitcoins σου από κλοπή από κακόβουλο λογισμικό που έχει μολύνει τον υπολογιστή σου</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>To πορτοφόλι θα κρυπτογραφηθεί</translation>
+ </message>
+ <message>
+ <source>Your wallet is about 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>
+ <translation>ΣΗΜΑΝΤΙΚΟ: Τα προηγούμενα αντίγραφα ασφαλείας που έχετε κάνει από το αρχείο του πορτοφόλιου σας θα πρέπει να αντικατασταθουν με το νέο που δημιουργείται, κρυπτογραφημένο αρχείο πορτοφόλιου. Για λόγους ασφαλείας, τα προηγούμενα αντίγραφα ασφαλείας του μη κρυπτογραφημένου αρχείου πορτοφόλιου θα καταστουν άχρηστα μόλις αρχίσετε να χρησιμοποιείτε το νέο κρυπτογραφημένο πορτοφόλι.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
@@ -197,7 +229,7 @@
</message>
<message>
<source>Wallet decryption failed</source>
- <translation> Η αποκρυπτογράφηση του πορτοφολιού απέτυχε </translation>
+ <translation>Η αποκρυπτογράφηση του πορτοφολιού απέτυχε</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
@@ -294,6 +326,14 @@
<translation>'Ανοιγμα &amp;URI</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Δημιουργία Πορτοφολιού</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Δημιουργία νέου Πορτοφολιού</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Πορτοφόλι</translation>
</message>
@@ -318,6 +358,10 @@
<translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρό δίσκο...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy είναι&lt;b&gt;ενεργοποιημένος&lt;/b&gt;:%1 </translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Στείλε νομίσματα σε μια διεύθυνση bitcoin</translation>
</message>
@@ -330,14 +374,6 @@
<translation>Αλλαγή του κωδικού κρυπτογράφησης του πορτοφολιού</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Παράθυρο αποσφαλμάτωσης</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Άνοιγμα κονσόλας αποσφαλμάτωσης και διαγνωστικών</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Επιβεβαίωση μηνύματος</translation>
</message>
@@ -347,7 +383,7 @@
</message>
<message>
<source>&amp;Receive</source>
- <translation>&amp;Παραλαβή </translation>
+ <translation>&amp;Παραλαβή</translation>
</message>
<message>
<source>&amp;Show / Hide</source>
@@ -359,7 +395,7 @@
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
- <translation>Κρυπτογραφήστε τα ιδιωτικά κλειδιά που ανήκουν στο πορτοφόλι σας </translation>
+ <translation>Κρυπτογραφήστε τα ιδιωτικά κλειδιά που ανήκουν στο πορτοφόλι σας</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
@@ -398,13 +434,13 @@
<translation>Προβολή της λίστας των χρησιμοποιημένων διευθύνσεων και ετικετών λήψεως</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Άνοιγμα bitcoin: URI αίτησης πληρωμής</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Επιλογές γραμμής εντολών</translation>
</message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n ενεργές συνδέσεις στο δίκτυο Bitcoin</numerusform><numerusform>%n ενεργές συνδέσεις στο δίκτυο Bitcoin</numerusform></translation>
+ </message>
<message>
<source>Indexing blocks on disk...</source>
<translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρο δισκο...</translation>
@@ -413,6 +449,10 @@
<source>Processing blocks on disk...</source>
<translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρο δισκο...</translation>
</message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>Επεξεργασμένα %n μπλοκ ιστορικού συναλλαγών.</numerusform><numerusform>Επεξεργασμένα %n μπλοκ ιστορικού συναλλαγών.</numerusform></translation>
+ </message>
<message>
<source>%1 behind</source>
<translation>%1 πίσω</translation>
@@ -442,10 +482,54 @@
<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;Αποστολή διεύθυνσης</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation>&amp;Λήψη διευθύνσεων</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Ανοίξτε ένα bitcoin: URI</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <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>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Εμφάνισε το %1 βοηθητικό μήνυμα για λήψη μιας λίστας με διαθέσιμες επιλογές για Bitcoin εντολές </translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>Προεπιλεγμένο πορτοφόλι</translation>
</message>
<message>
+ <source>No wallets available</source>
+ <translation>Κανένα πορτοφόλι διαθέσιμο</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;Παράθυρο</translation>
</message>
@@ -454,10 +538,34 @@
<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>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>Σύνδεση στους σύντροφους...</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Ενημέρωση...</translation>
</message>
<message>
+ <source>Error: %1</source>
+ <translation>Σφάλμα: %1</translation>
+ </message>
+ <message>
+ <source>Warning: %1</source>
+ <translation>Προειδοποίηση: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Ημερομηνία: %1
@@ -502,6 +610,18 @@
<translation>Εισερχόμενη συναλλαγή</translation>
</message>
<message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>Δημιουργία πλήκτρων HD είναι &lt;b&gt;ενεργοποιημένη&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>Δημιουργία πλήκτρων HD είναι &lt;b&gt;απενεργοποιημένη&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <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>
<translation>Το πορτοφόλι είναι &lt;b&gt;κρυπτογραφημένο&lt;/b&gt; και &lt;b&gt;ξεκλείδωτο&lt;/b&gt;</translation>
</message>
@@ -509,7 +629,11 @@
<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>
- </context>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>Εμφανίστηκε ένα μοιραίο σφάλμα. Το Bitcoin δεν μπορεί πλέον να συνεχίσει με ασφάλεια και θα σταματήσει.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -597,6 +721,14 @@
<translation>Αντιγραφή ταυτότητας συναλλαγής</translation>
</message>
<message>
+ <source>Lock unspent</source>
+ <translation>Κλείδωμα μη δαπανημένου</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Ξεκλείδωμα μη δαπανημένου</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation>Αντιγραφή ποσότητας</translation>
</message>
@@ -605,6 +737,26 @@
<translation>Αντιγραφή τελών</translation>
</message>
<message>
+ <source>Copy after fee</source>
+ <translation>Αντιγραφή μετά τα έξοδα</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Αντιγραφή των bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Αντιγραφή σκόνης</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Αντιγραφή αλλαγής</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 κλειδωμένο)</translation>
+ </message>
+ <message>
<source>yes</source>
<translation>ναι</translation>
</message>
@@ -613,20 +765,80 @@
<translation>όχι</translation>
</message>
<message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>Αυτή η ετικέτα γίνεται κόκκινη εάν οποιοσδήποτε παραλήπτης λάβει ένα ποσό μικρότερο από το τρέχον όριο σκόνης.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Μπορεί να ποικίλει +/- %1 satoshi(s) ανά είσοδο.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(χωρίς ετικέτα)</translation>
</message>
<message>
+ <source>change from %1 (%2)</source>
+ <translation>αλλαγή από %1(%2)</translation>
+ </message>
+ <message>
<source>(change)</source>
<translation>(αλλαγή)</translation>
</message>
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <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>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Προειδοποίηση δημιουργίας πορτοφολιού</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Δημιουργία Πορτοφολιού</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Όνομα Πορτοφολιού</translation>
+ </message>
+ <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>Create</source>
+ <translation>Δημιουργία</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -659,7 +871,7 @@
</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>
@@ -712,10 +924,6 @@
<translation>έκδοση</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Σχετικά %1</translation>
</message>
@@ -735,18 +943,50 @@
<translation>Καλωσήρθες στο %1.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>Όταν κάνετε κλικ στο OK, το %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>
+ <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>Αν έχετε επιλέξει να περιορίσετε την αποθήκευση της αλυσίδας μπλοκ (κλάδεμα), τα ιστορικά δεδομένα θα πρέπει ακόμα να κατεβάσετε και να επεξεργαστείτε, αλλά θα διαγραφούν αργότερα για να διατηρήσετε τη χρήση του δίσκου σας χαμηλή.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation>Χρήση του προεπιλεγμένου φακέλου δεδομένων</translation>
</message>
<message>
<source>Use a custom data directory:</source>
- <translation>Προσαρμογή του φακέλου δεδομένων: </translation>
+ <translation>Προσαρμογή του φακέλου δεδομένων:</translation>
</message>
<message>
<source>Bitcoin</source>
<translation>Bitcoin</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 GB δεδομένων θα αποθηκευτούν σε αυτόν τον κατάλογο και θα αυξηθεί με την πάροδο του χρόνου.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>Περίπου %1 GB δεδομένων θα αποθηκεύονται σε αυτόν τον κατάλογο.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>Το %1 θα κατεβάσει και θα αποθηκεύσει ένα αντίγραφο της αλυσίδας μπλοκ Bitcoin.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Το πορτοφόλι θα αποθηκευτεί επίσης σε αυτό το ευρετήριο</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" cannot be created.</source>
<translation>Σφάλμα: Ο καθορισμένος φάκελος δεδομένων "%1" δεν μπορεί να δημιουργηθεί.</translation>
</message>
@@ -762,7 +1002,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(από το %n GB που απαιτείται)</numerusform><numerusform>(από τα %n GB που απαιτούνται)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB απαιτούνται για την πλήρη αλυσίδα)</numerusform><numerusform>(%n GB απαιτούνται για την πλήρη αλυσίδα)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -770,6 +1014,18 @@
<translation>Φόρμα</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>Οι πρόσφατες συναλλαγές ενδέχεται να μην είναι ακόμα ορατές και επομένως η ισορροπία του πορτοφολιού σας μπορεί να είναι εσφαλμένη. Αυτές οι πληροφορίες θα είναι σωστές όταν ολοκληρωθεί το συγχρονισμό του πορτοφολιού σας με το δίκτυο Bitcoin, όπως περιγράφεται παρακάτω.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation>Η προσπάθεια να δαπανήσετε bitcoins που επηρεάζονται από τις μη εμφανιζόμενες ακόμη συναλλαγές δεν θα γίνει αποδεκτή από το δίκτυο.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Αριθμός των εναπομείνων κομματιών</translation>
+ </message>
+ <message>
<source>Unknown...</source>
<translation>Άγνωστο...</translation>
</message>
@@ -778,36 +1034,68 @@
<translation>Χρόνος τελευταίου μπλοκ</translation>
</message>
<message>
+ <source>Progress</source>
+ <translation>Πρόοδος</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>Αύξηση προόδου ανά ώρα</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>Υπολογισμός...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>Εκτιμώμενος χρόνος μέχρι να συγχρονιστεί</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation>Απόκρυψη</translation>
</message>
- </context>
-<context>
- <name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Άνοιγμα &amp;URI</translation>
+ <source>Esc</source>
+ <translation>Πλήκτρο Esc</translation>
</message>
<message>
- <source>Open payment request from URI or file</source>
- <translation>Ανοιχτό αίτημα πληρωμής από URI ή από αρχείο</translation>
+ <source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
+ <translation>Το %1 συγχρονίζεται αυτήν τη στιγμή. Θα κατεβάσει κεφαλίδες και μπλοκ από τους συντρόφους και θα τους επικυρώσει μέχρι να φτάσουν στην άκρη της αλυσίδας μπλοκ.</translation>
</message>
<message>
- <source>URI:</source>
- <translation>URI:</translation>
+ <source>Unknown. Syncing Headers (%1, %2%)...</source>
+ <translation>Αγνωστος. Συγχρονισμός κεφαλίδων (%1, %2%)...</translation>
+ </message>
+</context>
+<context>
+ <name>OpenURIDialog</name>
+ <message>
+ <source>Open bitcoin URI</source>
+ <translation>Ανοίξτε το bitcoin URI</translation>
</message>
<message>
- <source>Select payment request file</source>
- <translation>Επιλέξτε πληρωμή αρχείου αίτησης</translation>
+ <source>URI:</source>
+ <translation>URI:</translation>
</message>
- </context>
+</context>
<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>
- </context>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Άνοιγμα Πορτοφολιού &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+</context>
<context>
<name>OptionsDialog</name>
<message>
@@ -819,18 +1107,42 @@
<translation>&amp;Κύριο</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Αυτόματη εκκίνηση του %1 μετά τη σύνδεση στο σύστημα.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>&amp;Έναρξη %1 στο σύστημα σύνδεσης</translation>
+ </message>
+ <message>
<source>Size of &amp;database cache</source>
<translation>Μέγεθος κρυφής μνήμης βάσης δεδομένων.</translation>
</message>
<message>
<source>Number of script &amp;verification threads</source>
- <translation>Αριθμός script και γραμμές επαλήθευσης </translation>
+ <translation>Αριθμός script και γραμμές επαλήθευσης</translation>
</message>
<message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
<translation>Διεύθυνση IP του διαμεσολαβητή (π.χ. 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 proxy για να προσεγγίσετε συνομηλίκους μέσω κρυφών υπηρεσιών Tor:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Απόκρυψη του εικονιδίου από το συρτάρι του συστήματος.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp; Απόκρυψη εικονιδίου δίσκου</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>Ελαχιστοποίηση αντί για έξοδο κατά το κλείσιμο του παραθύρου. Όταν αυτή η επιλογή είναι ενεργοποιημένη, η εφαρμογή θα κλείνει μόνο αν επιλεχθεί η Έξοδος στο μενού.</translation>
</message>
@@ -839,6 +1151,10 @@
<translation>URLs από τρίτους (π.χ. ένας εξερευνητής μπλοκ) τα οποία εμφανίζονται στην καρτέλα συναλλαγών ως στοιχεία μενού. Το %s στα URL αντικαθίσταται από την τιμή της κατατεμαχισμένης συναλλαγής.</translation>
</message>
<message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Ανοίξτε το %1 αρχείο διαμόρφωσης από τον κατάλογο εργασίας.</translation>
+ </message>
+ <message>
<source>Open Configuration File</source>
<translation>Άνοιγμα Αρχείου Ρυθμίσεων</translation>
</message>
@@ -855,10 +1171,26 @@
<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>Αποκοπή &amp;αποκλεισμός αποθήκευσης στο</translation>
+ </message>
+ <message>
<source>GB</source>
<translation>GB</translation>
</message>
<message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Η επαναφορά αυτής της ρύθμισης απαιτεί εκ νέου λήψη ολόκληρου του μπλοκ αλυσίδας.</translation>
+ </message>
+ <message>
+ <source>MiB</source>
+ <translation>MebiBytes</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = αυτόματο, &lt;0 = ελεύθεροι πυρήνες)</translation>
</message>
@@ -891,6 +1223,14 @@
<translation>Απόδοση θυρών με χρήστη &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Αποδοχή εξωτερικών συνδέσεων</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Επιτρέπονται εισερχόμενες συνδέσεις</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Σύνδεση στο δίκτυο Bitcoin μέσω διαμεσολαβητή SOCKS5 (π.χ. για σύνδεση μέσω Tor)</translation>
</message>
@@ -911,6 +1251,10 @@
<translation>Θύρα διαμεσολαβητή</translation>
</message>
<message>
+ <source>Used for reaching peers via:</source>
+ <translation>Χρησιμοποιείται για να φτάσεις στους σύντροφους μέσω:</translation>
+ </message>
+ <message>
<source>IPv4</source>
<translation>IPv4</translation>
</message>
@@ -923,6 +1267,10 @@
<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>
@@ -947,6 +1295,10 @@
<translation>Γλώσσα περιβάλλοντος εργασίας:</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>&amp;Μονάδα μέτρησης:</translation>
</message>
@@ -959,6 +1311,10 @@
<translation>Επιλογή κατά πόσο να αναδείχνονται οι δυνατότητες ελέγχου κερμάτων.</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>&amp;ΟΚ</translation>
</message>
@@ -983,10 +1339,27 @@
<translation>Χρειάζεται επανεκκίνηση του προγράμματος για να ενεργοποιηθούν οι αλλαγές.</translation>
</message>
<message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>Ο πελάτης θα τερματιστεί. Θέλετε να συνεχίσετε?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <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>Το αρχείο ρυθμίσεων χρησιμοποιείται για τον προσδιορισμό των προχωρημένων επιλογών χρηστών που παρακάμπτουν τις ρυθμίσεις GUI. Επιπλέον, όλες οι επιλογές γραμμής εντολών θα αντικαταστήσουν αυτό το αρχείο ρυθμίσεων.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Σφάλμα</translation>
</message>
<message>
+ <source>The configuration file could not be opened.</source>
+ <translation>Το αρχείο διαμόρφωσης δεν ήταν δυνατό να ανοιχτεί.</translation>
+ </message>
+ <message>
<source>This change would require a client restart.</source>
<translation>Η αλλαγή αυτή θα χρειαστεί επανεκκίνηση του προγράμματος</translation>
</message>
@@ -1003,7 +1376,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>Οι πληροφορίες που εμφανίζονται μπορεί να είναι ξεπερασμένες. Το πορτοφόλι σας συγχρονίζεται αυτόματα με το δίκτυο Bitcoin μετά από μια σύνδεση, αλλά αυτή η διαδικασία δεν έχει ακόμη ολοκληρωθεί. </translation>
+ <translation>Οι πληροφορίες που εμφανίζονται μπορεί να είναι ξεπερασμένες. Το πορτοφόλι σας συγχρονίζεται αυτόματα με το δίκτυο Bitcoin μετά από μια σύνδεση, αλλά αυτή η διαδικασία δεν έχει ακόμη ολοκληρωθεί.</translation>
</message>
<message>
<source>Watch-only:</source>
@@ -1085,21 +1458,53 @@
<translation>URI χειριστής</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <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>Αν λαμβάνετε αυτό το σφάλμα, θα πρέπει να ζητήσετε από τον έμπορο να παράσχει URI συμβατό με BIP21.</translation>
+ </message>
+ <message>
<source>Invalid payment address %1</source>
<translation>Μη έγκυρη διεύθυνση πληρωμής %1</translation>
</message>
<message>
- <source>Payment request file handling</source>
- <translation>Επεξεργασία αρχείου αίτησης πληρωμής</translation>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation>Δεν είναι δυνατή η ανάλυση του URI! Αυτό μπορεί να προκληθεί από μη έγκυρη διεύθυνση Bitcoin ή παραμορφωμένες παραμέτρους URI.</translation>
</message>
<message>
- <source>Payment request rejected</source>
- <translation>Η αίτηση πληρωμής απορρίφθηκε</translation>
+ <source>Payment request file handling</source>
+ <translation>Επεξεργασία αρχείου αίτησης πληρωμής</translation>
</message>
- </context>
+</context>
<context>
<name>PeerTableModel</name>
<message>
+ <source>User Agent</source>
+ <translation>Agent χρήστη</translation>
+ </message>
+ <message>
+ <source>Node/Service</source>
+ <translation>Κόμβος / Υπηρεσία</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>Ταυτότητα Κόμβου</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>Ping</translation>
+ </message>
+ <message>
<source>Sent</source>
<translation>Αποστολή</translation>
</message>
@@ -1146,10 +1551,34 @@
<source>%1 ms</source>
<translation>%1 ms</translation>
</message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation><numerusform>%n δευτερόλεπτα</numerusform><numerusform>%n δευτερόλεπτα</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation><numerusform>%n λεπτά</numerusform><numerusform>%n λεπτά</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation><numerusform>%n ώρες</numerusform><numerusform>%n ώρες</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation><numerusform>%n ημέρες</numerusform><numerusform>%n ημέρες</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation><numerusform>%n εβδομάδες</numerusform><numerusform>%n εβδομάδες</numerusform></translation>
+ </message>
<message>
<source>%1 and %2</source>
<translation>%1 και %2</translation>
</message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation><numerusform>%n χρόνια</numerusform><numerusform>%n χρόνια</numerusform></translation>
+ </message>
<message>
<source>%1 B</source>
<translation>%1 B</translation>
@@ -1167,6 +1596,22 @@
<translation>%1 GB</translation>
</message>
<message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation>Σφάλμα: Ο καθορισμένος κατάλογος δεδομένων "%1" δεν υπάρχει.</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Σφάλμα: Δεν είναι δυνατή η ανάλυση αρχείου ρυθμίσεων: %1.</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>Σφάλμα: %1</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely...</source>
+ <translation> Το %1 δεν έφυγε ακόμα με ασφάλεια...</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>Άγνωστο</translation>
</message>
@@ -1177,7 +1622,31 @@
<source>&amp;Save Image...</source>
<translation>&amp;Αποθήκευση εικόνας...</translation>
</message>
- </context>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;Αντιγραφή Εικόνας</translation>
+ </message>
+ <message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation>Το προκύπτον URI είναι πολύ μεγάλο, προσπαθήστε να μειώσετε το κείμενο για ετικέτα / μήνυμα.</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>Σφάλμα κωδικοποίησης του URI σε κώδικα QR.</translation>
+ </message>
+ <message>
+ <source>QR code support not available.</source>
+ <translation>Η υποστήριξη QR code δεν είναι διαθέσιμη.</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation>Αποθήκευση κωδικού QR</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>PNG Εικόνα (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -1193,10 +1662,6 @@
<translation>&amp;Πληροφορία</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Παράθυρο αποσφαλμάτωσης</translation>
- </message>
- <message>
<source>General</source>
<translation>Γενικά</translation>
</message>
@@ -1205,6 +1670,18 @@
<translation>Χρήση BerkeleyDB έκδοσης</translation>
</message>
<message>
+ <source>Datadir</source>
+ <translation>Κατάλογος Δεδομένων</translation>
+ </message>
+ <message>
+ <source>Blocksdir</source>
+ <translation>Κατάλογος των Μπλοκς</translation>
+ </message>
+ <message>
+ <source>To specify a non-default location of the blocks directory use the '%1' option.</source>
+ <translation>Για να καθορίσετε μια μη προεπιλεγμένη θέση του καταλόγου μπλοκ, χρησιμοποιήστε την επιλογή '%1'.</translation>
+ </message>
+ <message>
<source>Startup time</source>
<translation>Χρόνος εκκίνησης</translation>
</message>
@@ -1229,10 +1706,30 @@
<translation>Τρέχον αριθμός μπλοκ</translation>
</message>
<message>
+ <source>Memory Pool</source>
+ <translation>Πισίνα μνήμης</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>Τρέχων αριθμός συναλλαγών</translation>
+ </message>
+ <message>
<source>Memory usage</source>
<translation>χρήση Μνήμης</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Πορτοφόλι:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(κενό)</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>&amp;Επαναφορά</translation>
+ </message>
+ <message>
<source>Received</source>
<translation>Παραλήφθησαν</translation>
</message>
@@ -1245,14 +1742,50 @@
<translation>&amp;Χρήστες</translation>
</message>
<message>
+ <source>Banned peers</source>
+ <translation>Αποκλεισμένοι σύντροφοι</translation>
+ </message>
+ <message>
<source>Select a peer to view detailed information.</source>
<translation>Επιλέξτε ένα χρήστη για να δείτε αναλυτικές πληροφορίες.</translation>
</message>
<message>
+ <source>Whitelisted</source>
+ <translation> Τα στοιχεία που έχουν πρόσβαση στο σύστημα</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Κατεύθυνση</translation>
+ </message>
+ <message>
<source>Version</source>
<translation>Έκδοση</translation>
</message>
<message>
+ <source>Starting Block</source>
+ <translation>Αρχικό Μπλοκ</translation>
+ </message>
+ <message>
+ <source>Synced Headers</source>
+ <translation>Συγχρονισμένες Κεφαλίδες</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>Συγχρονισμένα Μπλοκς</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>Agent χρήστη</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>
+ <message>
<source>Decrease font size</source>
<translation>Μείωση μεγέθους γραμματοσειράς</translation>
</message>
@@ -1285,6 +1818,22 @@
<translation>Χρόνος καθυστέρησης</translation>
</message>
<message>
+ <source>The duration of a currently outstanding ping.</source>
+ <translation>Η διάρκεια ενός τρέχοντος ping.</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>Ping Αναμονή</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>Ελάχιστο Min</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation>Χρονική αντιστάθμιση</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation>Χρόνος τελευταίου μπλοκ</translation>
</message>
@@ -1314,7 +1863,7 @@
</message>
<message>
<source>Debug log file</source>
- <translation>Αρχείο καταγραφής εντοπισμού σφαλμάτων </translation>
+ <translation>Αρχείο καταγραφής εντοπισμού σφαλμάτων</translation>
</message>
<message>
<source>Clear console</source>
@@ -1337,6 +1886,55 @@
<translation>1 &amp;χρόνος</translation>
</message>
<message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;Αποσύνδεση</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>Απαγόρευση για</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>&amp;Ακύρωση Απαγόρευσης</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>Καλώς ήρθατε στην κονσόλα %1 RPC.</translation>
+ </message>
+ <message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>Χρησιμοποιήστε τα βέλη πάνω και κάτω για να περιηγηθείτε στο ιστορικό και το %1 για να καθαρίσετε την οθόνη.</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Πληκτρολογήστε %1 για μια επισκόπηση των διαθέσιμων εντολών.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Για περισσότερες πληροφορίες σχετικά με τη χρήση αυτού του τύπου κονσόλας %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>ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Οι απατεώνες είναι ενεργοί, λέγοντας στους χρήστες να πληκτρολογούν εντολές εδώ, κλέβοντας τα περιεχόμενα του πορτοφολιού τους. Μην χρησιμοποιείτε αυτήν την κονσόλα χωρίς να κατανοείτε πλήρως τις συνέπειες μιας εντολής.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>Η δραστηριότητα δικτύου είναι απενεργοποιημένη</translation>
+ </message>
+ <message>
+ <source>Executing command without any wallet</source>
+ <translation>Εκτέλεση εντολής χωρίς πορτοφόλι</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation> 
+Εκτελέστε εντολή χρησιμοποιώντας το πορτοφόλι "%1"</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(αναγνωριστικό κόμβου: %1)</translation>
+ </message>
+ <message>
<source>via %1</source>
<translation>μέσω %1</translation>
</message>
@@ -1380,6 +1978,34 @@
<translation>&amp;Μήνυμα:</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>Ένα προαιρετικό μήνυμα που επισυνάπτεται στο αίτημα πληρωμής, το οποίο θα εμφανιστεί όταν το αίτημα ανοίξει. Σημείωση: Το μήνυμα δεν θα αποσταλεί με την πληρωμή μέσω του δικτύου Bitcoin.</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation>Μια προαιρετική ετικέτα για να συσχετιστεί με τη νέα διεύθυνση λήψης.</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation>Χρησιμοποιήστε αυτήν τη φόρμα για να ζητήσετε πληρωμές. Όλα τα πεδία είναι &lt;b&gt;προαιρετικά&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
+ <translation>Ένα προαιρετικό ποσό για να ζητήσετε. Αφήστε αυτό το κενό ή το μηδέν για να μην ζητήσετε ένα συγκεκριμένο ποσό.</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>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Καθαρισμός όλων των πεδίων της φόρμας.</translation>
</message>
@@ -1388,6 +2014,22 @@
<translation>Καθαρισμός</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>Οι εγγενείς διευθύνσεις αλληλογραφίας (aka Bech32 ή BIP-173) μειώνουν αργότερα τις αμοιβές συναλλαγών σας και προσφέρουν καλύτερη προστασία από τυπογραφικά λάθη, αλλά τα παλιά πορτοφόλια δεν τα υποστηρίζουν. Όταν δεν έχει επιλεγεί, θα δημιουργηθεί μια διεύθυνση συμβατή με παλιότερα πορτοφόλια.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Δημιουργήστε τη διεύθυνση native segwit (Bech32)</translation>
+ </message>
+ <message>
+ <source>Requested payments history</source>
+ <translation> Ιστορικό πληρωμών που ζητήσατε</translation>
+ </message>
+ <message>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation> Εμφάνιση της επιλεγμένης αίτησης (κάνει το ίδιο με το διπλό κλικ σε μια καταχώρηση)</translation>
+ </message>
+ <message>
<source>Show</source>
<translation>Εμφάνιση</translation>
</message>
@@ -1435,10 +2077,18 @@
<translation>&amp;Αποθήκευση εικόνας...</translation>
</message>
<message>
+ <source>Request payment to %1</source>
+ <translation>Αίτημα πληρωμής στο %1</translation>
+ </message>
+ <message>
<source>Payment information</source>
<translation>Πληροφορίες πληρωμής</translation>
</message>
<message>
+ <source>URI</source>
+ <translation>URI</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>Διεύθυνση</translation>
</message>
@@ -1477,7 +2127,19 @@
<source>(no label)</source>
<translation>(χωρίς ετικέτα)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation>(κανένα μήνυμα)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(δεν ζητήθηκε ποσό)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>Ζητείται</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -1541,6 +2203,23 @@
<translation>Επιλογή...</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>Η χρήση του fallbackfee μπορεί να έχει ως αποτέλεσμα την αποστολή μιας συναλλαγής που θα χρειαστεί αρκετές ώρες ή ημέρες (ή ποτέ) για επιβεβαίωση. Εξετάστε το ενδεχόμενο να επιλέξετε τη χρέωση σας με μη αυτόματο τρόπο ή να περιμένετε έως ότου επικυρώσετε την πλήρη αλυσίδα.</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation> 
+Προειδοποίηση: Προς το παρόν δεν είναι δυνατή η εκτίμηση των εξόδων..</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>Καθορίστε μια προσαρμοσμένη χρέωση ανά kB (1.000 bytes) του εικονικού μεγέθους της συναλλαγής.
+
+Σημείωση: Δεδομένου ότι η χρέωση υπολογίζεται ανά βάση, η αμοιβή "100 satoshis ανά kB" για ένα μέγεθος συναλλαγής 500 bytes (το μισό του 1 kB) θα αποφέρει τέλος μόνο 50 satoshis.</translation>
+ </message>
+ <message>
<source>per kilobyte</source>
<translation>ανά kilobyte</translation>
</message>
@@ -1550,13 +2229,17 @@
</message>
<message>
<source>Recommended:</source>
- <translation>Προτεινόμενο: </translation>
+ <translation>Προτεινόμενο:</translation>
</message>
<message>
<source>Custom:</source>
<translation>Προσαρμογή:</translation>
</message>
<message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(Η έξυπνη αμοιβή δεν έχει αρχικοποιηθεί ακόμη, συνήθως χρειάζεται λίγα τετράγωνα...)</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>Αποστολή σε πολλούς αποδέκτες ταυτόχρονα</translation>
</message>
@@ -1573,6 +2256,30 @@
<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>Όταν υπάρχει λιγότερος όγκος συναλλαγών από το χώρο στα μπλοκ, οι ανθρακωρύχοι καθώς και οι κόμβοι αναμετάδοσης μπορούν να επιβάλουν ένα ελάχιστο τέλος. Η πληρωμή μόνο αυτού του ελάχιστου τέλους είναι μια χαρά, αλλά γνωρίζετε ότι αυτό μπορεί να οδηγήσει σε μια συναλλαγή που δεν επιβεβαιώνει ποτέ τη στιγμή που υπάρχει μεγαλύτερη ζήτηση για συναλλαγές bitcoin από ό, τι μπορεί να επεξεργαστεί το δίκτυο.</translation>
+ </message>
+ <message>
+ <source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
+ <translation>Μια πολύ χαμηλή χρέωση μπορεί να οδηγήσει σε μια συναλλαγή που δεν επιβεβαιώνει ποτέ (διαβάστε την επεξήγηση εργαλείου)</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>Επιβεβαίωση χρονικού στόχου :</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Ενεργοποίηση Αντικατάστασης-Aπό-Έξοδα</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>Με την υπηρεσία αντικατάστασης-πληρωμής (BIP-125) μπορείτε να αυξήσετε το τέλος μιας συναλλαγής μετά την αποστολή. Χωρίς αυτό, μπορεί να συνιστάται υψηλότερη αμοιβή για την αντιστάθμιση του αυξημένου κινδύνου καθυστέρησης της συναλλαγής.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Καθαρισμός &amp;Όλων</translation>
</message>
@@ -1601,14 +2308,159 @@
<translation>Αντιγραφή τελών</translation>
</message>
<message>
+ <source>Copy after fee</source>
+ <translation>Αντιγραφή μετά τα έξοδα</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Αντιγραφή των bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Αντιγραφή σκόνης</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Αντιγραφή αλλαγής</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 μπλοκς)</translation>
+ </message>
+ <message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Δη&amp;μιουργία Ανυπόγραφου</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation>από πορτοφόλι '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 προς το '%2'</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <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>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>
+ </message>
+ <message>
<source>or</source>
<translation>ή</translation>
</message>
<message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation> Μπορείτε να αυξήσετε αργότερα την αμοιβή (σήματα Αντικατάσταση-By-Fee, BIP-125).</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Παρακαλούμε, ελέγξτε τη συναλλαγή σας.</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Κόστος συναλλαγής</translation>
</message>
<message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation> 
+Δεν σηματοδοτεί την Aντικατάσταση-Aπό-Έξοδο, BIP-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <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>Confirm transaction proposal</source>
+ <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>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>Η διεύθυση παραλήπτη δεν είναι έγκυρη. Ελέγξτε ξανά.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Το ποσό που πρέπει να πληρώσει πρέπει να είναι μεγαλύτερο από το 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Το ποσό υπερβαίνει το υπόλοιπό σας.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation> Το σύνολο υπερβαίνει το υπόλοιπό σας όταν περιλαμβάνεται το τέλος συναλλαγής %1.</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>Βρέθηκε διπλή διεύθυνση: οι διευθύνσεις θα πρέπει να χρησιμοποιούνται μόνο μία φορά.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Η δημιουργία της συναλλαγής απέτυχε!</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>Ένα τέλος υψηλότερο από το %1 θεωρείται ένα παράλογο υψηλό έξοδο.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Η αίτηση πληρωμής έληξε.</translation>
+ </message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>Εκτιμάται η έναρξη επιβεβαίωσης εντός %n μπλοκ.</numerusform><numerusform>Εκτιμάται η έναρξη επιβεβαίωσης εντός %n μπλοκ.</numerusform></translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Προειδοποίηση: Μη έγκυρη διεύθυνση Bitcoin</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Προειδοποίηση: Άγνωστη διεύθυνση αλλαγής</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <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>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(χωρίς ετικέτα)</translation>
</message>
@@ -1632,10 +2484,6 @@
<translation>Επιλογή διεύθυνσης που έχει ήδη χρησιμοποιηθεί</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Αυτή είναι μια απλή πληρωμή.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Η διεύθυνση Bitcoin που θα σταλεί η πληρωμή</translation>
</message>
@@ -1656,14 +2504,38 @@
<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>Το τέλος θα αφαιρεθεί από το ποσό που αποστέλλεται. Ο παραλήπτης θα λάβει λιγότερα bitcoins από ό,τι εισάγετε στο πεδίο ποσό. Εάν επιλεγούν πολλοί παραλήπτες, το έξοδο διαιρείται εξίσου.</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>Χρησιμοποιήστε το διαθέσιμο υπόλοιπο</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Μήνυμα:</translation>
</message>
<message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>Πρόκειται για αίτημα πληρωμής χωρίς έλεγχο ταυτότητας.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>Πρόκειται για ένα πιστοποιημένο αίτημα πληρωμής.</translation>
+ </message>
+ <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<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>
+ <translation>Ένα μήνυμα που επισυνάφθηκε στο bitcoin: URI το οποίο θα αποθηκευτεί με τη συναλλαγή για αναφορά. Σημείωση: Αυτό το μήνυμα δεν θα σταλεί μέσω του δικτύου Bitcoin.</translation>
+ </message>
+ <message>
<source>Pay To:</source>
<translation>Πληρωμή σε:</translation>
</message>
@@ -1671,17 +2543,14 @@
<source>Memo:</source>
<translation>Σημείωση:</translation>
</message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ναι</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
<message>
+ <source>%1 is shutting down...</source>
+ <translation>Το %1 τερματίζεται ...</translation>
+ </message>
+ <message>
<source>Do not shut down the computer until this window disappears.</source>
<translation>Μην απενεργοποιήσετε τον υπολογιστή μέχρι να κλείσει αυτό το παράθυρο.</translation>
</message>
@@ -1690,13 +2559,17 @@
<name>SignVerifyMessageDialog</name>
<message>
<source>Signatures - Sign / Verify a Message</source>
- <translation>Υπογραφές - Είσοδος / Επαλήθευση Mηνύματος </translation>
+ <translation>Υπογραφές - Είσοδος / Επαλήθευση Mηνύματος</translation>
</message>
<message>
<source>&amp;Sign Message</source>
<translation>&amp;Υπογραφή Μηνύματος</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>Μπορείτε να υπογράψετε μηνύματα/συμφωνίες με τις διευθύνσεις σας για να αποδείξετε ότι μπορείτε να λάβετε τα bitcoins που τους αποστέλλονται. Προσέξτε να μην υπογράψετε τίποτα ασαφές ή τυχαίο, καθώς οι επιθέσεις ηλεκτρονικού "ψαρέματος" ενδέχεται να σας εξαπατήσουν να υπογράψετε την ταυτότητά σας σε αυτούς. Υπογράψτε μόνο πλήρως λεπτομερείς δηλώσεις που συμφωνείτε.</translation>
+ </message>
+ <message>
<source>The Bitcoin address to sign the message with</source>
<translation>Διεύθυνση Bitcoin που θα σταλεί το μήνυμα</translation>
</message>
@@ -1749,10 +2622,22 @@
<translation>&amp;Επιβεβαίωση Mηνύματος</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>Εισαγάγετε τη διεύθυνση του παραλήπτη, το μήνυμα (βεβαιωθείτε ότι αντιγράφετε σωστά τα διαλείμματα γραμμής, τα κενά, τις καρτέλες κλπ.) Και την υπογραφή παρακάτω για να επαληθεύσετε το μήνυμα. Προσέξτε να μην διαβάσετε περισσότερα στην υπογραφή από ό,τι είναι στο ίδιο το υπογεγραμμένο μήνυμα, για να αποφύγετε να εξαπατήσετε από μια επίθεση στον άνθρωπο στη μέση. Σημειώστε ότι αυτό αποδεικνύει μόνο ότι η υπογραφή συμβαλλόμενο μέρος λαμβάνει με τη διεύθυνση, δεν μπορεί να αποδειχθεί αποστολή οποιασδήποτε συναλλαγής!</translation>
+ </message>
+ <message>
<source>The Bitcoin address the message was signed with</source>
<translation>Διεύθυνση Bitcoin με την οποία έχει υπογραφεί το μήνυμα</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>Η υπογραφή που δόθηκε όταν υπογράφηκε το μήνυμα</translation>
+ </message>
+ <message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
<translation>Επαληθεύστε το μήνυμα για να αποδείξετε πως υπογράφθηκε από τη συγκεκριμένη διεύθυνση Bitcoin</translation>
</message>
@@ -1764,7 +2649,63 @@
<source>Reset all verify message fields</source>
<translation>Επαναφορά όλων των πεδίων επαλήθευσης μηνύματος</translation>
</message>
- </context>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Κάντε κλικ στην επιλογή "Υπογραφή μηνύματος" για να δημιουργήσετε υπογραφή</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>Η καταχωρημένη διεύθυνση δεν είναι έγκυρη.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Ελέγξτε τη διεύθυνση και δοκιμάστε ξανά.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>Η καταχωρημένη διεύθυνση δεν αναφέρεται σε ένα κλειδί.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <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>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Η υπογραφή μηνυμάτων απέτυχε.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Το μήνυμα υπογράφτηκε. </translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>Δεν ήταν δυνατή η αποκωδικοποίηση της υπογραφής.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Ελέγξτε την υπογραφή και δοκιμάστε ξανά.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>Η υπογραφή δεν ταιριάζει με το μήνυμα digest.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Επαλήθευση μηνύματος απέτυχε</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Το μήνυμα επαληθεύτηκε.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
<message>
@@ -1774,15 +2715,47 @@
</context>
<context>
<name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Ανοίξτε για %n περισσότερα μπλοκ</numerusform><numerusform>Ανοίξτε για %n περισσότερα μπλοκ</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Ανοιχτό μέχρι %1</translation>
</message>
<message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>σε σύγκρουση με μια συναλλαγή με %1 επιβεβαιώσεις</translation>
+ </message>
+ <message>
<source>0/unconfirmed, %1</source>
<translation>0/ανεπιβεβαίωτο, %1</translation>
</message>
<message>
+ <source>in memory pool</source>
+ <translation>στην πισίνα μνήμης</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>όχι στην πισίνα μνήμης</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>εγκαταλελειμμένος</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/μη επιβεβαιωμένο</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 επιβεβαιώσεις</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Κατάσταση</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Ημερομηνία</translation>
</message>
@@ -1822,11 +2795,23 @@
<source>Credit</source>
<translation>Πίστωση</translation>
</message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>ωριμάζει σε %n περισσότερα μπλοκ</numerusform><numerusform>ωριμάζει σε %n περισσότερα κομμάτια</numerusform></translation>
+ </message>
<message>
<source>not accepted</source>
<translation>μη έγκυρο</translation>
</message>
<message>
+ <source>Debit</source>
+ <translation>Χρέωση</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>Συνολική χρέωση</translation>
+ </message>
+ <message>
<source>Total credit</source>
<translation>Συνολική πίστωση</translation>
</message>
@@ -1835,21 +2820,81 @@
<translation>Κόστος συναλλαγής</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>Καθαρό ποσό</translation>
+ </message>
+ <message>
<source>Message</source>
<translation>Μήνυμα</translation>
</message>
<message>
+ <source>Comment</source>
+ <translation>Σχόλιο</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>Ταυτότητα συναλλαγής</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation>Συνολικό μέγεθος συναλλαγής</translation>
+ </message>
+ <message>
+ <source>Transaction virtual size</source>
+ <translation>Εικονικό μέγεθος συναλλαγής</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>Δείκτης εξόδου</translation>
+ </message>
+ <message>
+ <source> (Certificate was not verified)</source>
+ <translation>(Το πιστοποιητικό δεν επαληθεύτηκε)</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Έμπορος</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>Τα δημιουργημένα κέρματα πρέπει να ωριμάσουν σε %1 μπλοκ πριν να ξοδευτούν. Όταν δημιουργήσατε αυτό το μπλοκ, μεταδόθηκε στο δίκτυο για να προστεθεί στην αλυσίδα μπλοκ. Εάν αποτύχει να εισέλθει στην αλυσίδα, η κατάσταση της θα αλλάξει σε "μη αποδεκτή" και δεν θα είναι δαπανηρή. Αυτό μπορεί περιστασιακά να συμβεί εάν ένας άλλος κόμβος παράγει ένα μπλοκ μέσα σε λίγα δευτερόλεπτα από το δικό σας.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Πληροφορίες σφαλμάτων</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Συναλλαγή</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>Είσοδοι</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Ποσό</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>αληθής</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>ψευδής</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
<source>This pane shows a detailed description of the transaction</source>
<translation>Αυτό το παράθυρο δείχνει μια λεπτομερή περιγραφή της συναλλαγής</translation>
</message>
- </context>
+ <message>
+ <source>Details for %1</source>
+ <translation>Λεπτομέρειες για %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
@@ -1857,25 +2902,173 @@
<translation>Ημερομηνία</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Τύπος</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Ετικέτα</translation>
</message>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Ανοίξτε για %n περισσότερα μπλοκ</numerusform><numerusform>Ανοίξτε για %n περισσότερα μπλοκ</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Ανοιχτό μέχρι %1</translation>
</message>
<message>
+ <source>Unconfirmed</source>
+ <translation>Ανεξακρίβωτος</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation>εγκαταλελειμμένος</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>Επιβεβαίωση (%1 από %2 συνιστώμενες επιβεβαιώσεις)</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Επιβεβαίωση (%1 επιβεβαιώσεις)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation>Συγκρούεται</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>Άτομο (%1 επιβεβαιώσεις, θα είναι διαθέσιμες μετά το %2)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Δημιουργήθηκε αλλά δεν έγινε αποδεκτή</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Λήψη με</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Λήψη από</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Αποστέλλονται</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Πληρωμή στον εαυτό σας</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Εξόρυξη</translation>
+ </message>
+ <message>
<source>watch-only</source>
<translation>παρακολούθηση-μόνο</translation>
</message>
<message>
+ <source>(n/a)</source>
+ <translation>(μη διαθέσιμο)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(χωρίς ετικέτα)</translation>
</message>
- </context>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Κατάσταση συναλλαγής. Τοποθετήστε το δείκτη του ποντικιού πάνω από αυτό το πεδίο για να δείτε τον αριθμό των επιβεβαιώσεων.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Ημερομηνία και ώρα λήψης της συναλλαγής.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Είδος συναλλαγής.</translation>
+ </message>
+ <message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>Είτε πρόκειται για μια διεύθυνση μόνο για ρολόι, είτε όχι, σε αυτήν τη συναλλαγή.</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>Καθορισμένος από τον χρήστη σκοπός / σκοπός της συναλλαγής.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Ποσό που αφαιρέθηκε ή προστέθηκε στην ισορροπία.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Όλα</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Σήμερα</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Αυτή την εβδομάδα</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Αυτό τον μήνα</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Τον προηγούμενο μήνα</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Αυτή την χρονιά</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Πεδίο...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Λήψη με</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Αποστέλλονται προς</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Στον εαυτό σου</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Εξόρυξη</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Άλλα</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Εισαγάγετε τη διεύθυνση, το αναγνωριστικό συναλλαγής ή την ετικέτα για αναζήτηση</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Ελάχιστο ποσό</translation>
+ </message>
+ <message>
+ <source>Abandon transaction</source>
+ <translation>Απαλλαγή συναλλαγής</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>Αύξηση του τέλους συναλλαγής</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>Αντιγραφή διεύθυνσης</translation>
</message>
@@ -1896,10 +3089,22 @@
<translation>Αντιγραφή ανεπεξέργαστης συναλλαγής</translation>
</message>
<message>
+ <source>Copy full transaction details</source>
+ <translation>Αντιγράψτε τις πλήρεις λεπτομέρειες της συναλλαγής</translation>
+ </message>
+ <message>
<source>Edit label</source>
<translation>Επεξεργασία ετικέτας</translation>
</message>
<message>
+ <source>Show transaction details</source>
+ <translation>Εμφάνιση λεπτομερειών συναλλαγής</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>Εξαγωγή ιστορικού συναλλαγών</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Αρχείο οριοθετημένο με κόμματα (*.csv)</translation>
</message>
@@ -1908,10 +3113,18 @@
<translation>Επικυρωμένες</translation>
</message>
<message>
+ <source>Watch-only</source>
+ <translation>Παρακολουθήστε μόνο</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Ημερομηνία</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Τύπος</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Ετικέτα</translation>
</message>
@@ -1920,10 +3133,34 @@
<translation>Διεύθυνση</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ταυτότητα</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>Αποτυχία Εξαγωγής</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>Παρουσιάστηκε σφάλμα κατά την προσπάθεια αποθήκευσης του ιστορικού συναλλαγών στο %1.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Η εξαγωγή ήταν επιτυχής</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>Το ιστορικό συναλλαγών αποθηκεύτηκε επιτυχώς στο %1.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Πεδίο:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>προς</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
<message>
@@ -1933,10 +3170,26 @@
</context>
<context>
<name>WalletController</name>
- </context>
+ <message>
+ <source>Close wallet</source>
+ <translation>Κλείσιμο πορτοφολιού</translation>
+ </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>
+ </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>
+</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>Δεν έχει φορτωθεί πορτοφόλι.</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
@@ -1944,10 +3197,54 @@
<translation>Αποστολή νομισμάτων</translation>
</message>
<message>
+ <source>Fee bump error</source>
+ <translation>Σφάλμα πρόσκρουσης τέλους</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>Η αύξηση του τέλους συναλλαγής απέτυχε</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <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>
+ <message>
<source>Increase:</source>
<translation>Αύξηση:</translation>
</message>
<message>
+ <source>New fee:</source>
+ <translation>Νέο έξοδο:</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <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>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>Δεν ήταν δυνατή η ανάληψη συναλλαγής</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>Προεπιλεγμένο πορτοφόλι</translation>
</message>
@@ -1963,6 +3260,30 @@
<translation>Εξαγωγή δεδομένων καρτέλας σε αρχείο</translation>
</message>
<message>
+ <source>Backup Wallet</source>
+ <translation>Αντίγραφο ασφαλείας Πορτοφολιού</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation> Στοιχεία πορτοφολιού (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Αποτυχία δημιουργίας αντίγραφου ασφαλείας</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>Παρουσιάστηκε σφάλμα κατά την προσπάθεια αποθήκευσης των δεδομένων πορτοφολιού στο %1.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Η δημιουργία αντιγράφων ασφαλείας ήταν επιτυχής</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>Τα δεδομένα πορτοφολιού αποθηκεύτηκαν επιτυχώς στο %1.</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation>Ακύρωση</translation>
</message>
@@ -1970,10 +3291,126 @@
<context>
<name>bitcoin-core</name>
<message>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation>Διανέμεται υπό την άδεια χρήσης του λογισμικού MIT, δείτε το συνοδευτικό αρχείο %s ή %s</translation>
+ </message>
+ <message>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation>Ο δακτύλιος έχει διαμορφωθεί κάτω από το ελάχιστο %d MiB. Χρησιμοποιήστε έναν υψηλότερο αριθμό.</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>Κλάδεμα: ο τελευταίος συγχρονισμός πορτοφολιού ξεπερνά τα κλαδεμένα δεδομένα. Πρέπει να κάνετε -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>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>Δεν είναι δυνατή η εκκίνηση του διακομιστή HTTP. Δείτε το αρχείο εντοπισμού σφαλμάτων για λεπτομέρειες.</translation>
+ </message>
+ <message>
+ <source>The %s developers</source>
+ <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>Δεν είναι δυνατή η παροχή συγκεκριμένων συνδέσεων και η προσπέλαση των εξερχόμενων συνδέσεων στο ίδιο σημείο.</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>Σφάλμα κατά την ανάγνωση %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>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Παρακαλώ συμβάλλετε αν βρείτε %s χρήσιμο. Επισκεφθείτε το %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>Η βάση δεδομένων μπλοκ περιέχει ένα μπλοκ που φαίνεται να είναι από το μέλλον. Αυτό μπορεί να οφείλεται στην εσφαλμένη ρύθμιση της ημερομηνίας και της ώρας του υπολογιστή σας. Αποκαταστήστε μόνο τη βάση δεδομένων μπλοκ αν είστε βέβαιοι ότι η ημερομηνία και η ώρα του υπολογιστή σας είναι σωστές</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>Πρόκειται για δοκιμή πριν από την αποδέσμευση - χρησιμοποιήστε με δική σας ευθύνη - μην χρησιμοποιείτε για εξόρυξη ή εμπορικές εφαρμογές</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>Αυτή είναι η αμοιβή συναλλαγής που μπορείτε να απορρίψετε εάν η αλλαγή είναι μικρότερη από τη σκόνη σε αυτό το επίπεδο</translation>
+ </message>
+ <message>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>Δεν είναι δυνατή η επανάληψη των μπλοκ. Θα χρειαστεί να ξαναφτιάξετε τη βάση δεδομένων χρησιμοποιώντας το -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>Δεν είναι δυνατή η γρήγορη επαναφορά της βάσης δεδομένων σε κατάσταση προ-πιρουνιού. Θα χρειαστεί να επαναλάβετε την φόρτωση του blockchain</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Προειδοποίηση: Το δίκτυο δεν φαίνεται να συμφωνεί απόλυτα! Ορισμένοι ανθρακωρύχοι φαίνεται να αντιμετωπίζουν προβλήματα.</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>Προειδοποίηση: Δεν φαίνεται να συμφωνούμε πλήρως με τους συμμαθητές μας! Ίσως χρειαστεί να κάνετε αναβάθμιση ή ίσως χρειαστεί να αναβαθμίσετε άλλους κόμβους.</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>
+ <message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>Δεν είναι δυνατή η επίλυση -%s διεύθυνση: '%s'</translation>
+ </message>
+ <message>
+ <source>Change index out of range</source>
+ <translation>Αλλάξτε τον δείκτη εκτός εμβέλειας</translation>
+ </message>
+ <message>
+ <source>Config setting for %s only applied on %s network when in [%s] section.</source>
+ <translation>Η ρύθμιση Config για το %s εφαρμόστηκε μόνο στο δίκτυο %s όταν βρίσκεται στην ενότητα [%s].</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Πνευματικά δικαιώματα (C) %i-%i</translation>
+ </message>
+ <message>
<source>Corrupted block database detected</source>
<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>
<translation>Θέλετε να δημιουργηθεί τώρα η βάση δεδομένων των μπλοκ;</translation>
</message>
@@ -1986,6 +3423,22 @@
<translation>Σφάλμα κατά την ενεργοποίηση της βάσης δεδομένων πορτοφολιού %s!</translation>
</message>
<message>
+ <source>Error loading %s</source>
+ <translation>Σφάλμα κατά τη φόρτωση %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Σφάλμα κατά τη φόρτωση %s: Τα ιδιωτικά κλειδιά μπορούν να απενεργοποιηθούν μόνο κατά τη δημιουργία</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Σφάλμα κατά τη φόρτωση %s: Κατεστραμμένο Πορτοφόλι</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Σφάλμα κατά τη φόρτωση %s: Το Πορτοφόλι απαιτεί νεότερη έκδοση του %s</translation>
+ </message>
+ <message>
<source>Error loading block database</source>
<translation>Σφάλμα φόρτωσης της βάσης δεδομένων των μπλοκ</translation>
</message>
@@ -1998,24 +3451,198 @@
<translation>Αποτυχία παρακολούθησης σε οποιαδήποτε θύρα. Χρησιμοποιήστε -listen=0 αν θέλετε αυτό.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Αποτυχία επανεγγραφής του πορτοφολιού κατά την αρχικοποίηση</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Εισαγωγή...</translation>
</message>
<message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation>Ανακαλύφθηκε λάθος ή δεν βρέθηκε μπλοκ γενετικής. Λάθος δεδομένων για το δίκτυο;</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation> Ο έλεγχος ευελιξίας εκκίνησης απέτυχε. Το %s τερματίζεται.</translation>
+ </message>
+ <message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Μη έγκυρη άδεια P2P: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation>Μη έγκυρο ποσό για το -discardfee =&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation>Μη έγκυρο ποσό για το -fallbackfee =&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Δεν υπάρχει κατάλογος καθορισμένων μπλοκ "%s".</translation>
+ </message>
+ <message>
+ <source>Unknown address type '%s'</source>
+ <translation>Άγνωστος τύπος διεύθυνσης '%s'</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Αναβάθμιση της βάσης δεδομένων txindex</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>Φόρτωση P2P διευθύνσεων...</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is too low!</source>
+ <translation> Σφάλμα: Ο χώρος στο δίσκο είναι πολύ χαμηλός!</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>Φόρτωση λίστα απαγόρευσης...</translation>
+ </message>
+ <message>
<source>Not enough file descriptors available.</source>
<translation>Δεν υπάρχουν αρκετοί περιγραφείς αρχείων διαθέσιμοι.</translation>
</message>
<message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation>Ο δακτύλιος δεν μπορεί να ρυθμιστεί με αρνητική τιμή.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation>Η λειτουργία κοπής δεν είναι συμβατή με το -txindex.</translation>
+ </message>
+ <message>
+ <source>Replaying blocks...</source>
+ <translation>Αναπαραγωγή μπλοκ...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>Αναδίπλωση μπλοκ...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation> Ο πηγαίος κώδικας είναι διαθέσιμος από το %s.</translation>
+ </message>
+ <message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>Ο υπολογισμός των τελών συναλλαγής και της αλλαγής απέτυχε</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation>Δεν είναι δυνατή η δέσμευση του %s σε αυτόν τον υπολογιστή. Το %s πιθανώς ήδη εκτελείται.</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation>Δεν είναι δυνατή η δημιουργία κλειδιών</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation>Μη υποστηριζόμενη κατηγορία καταγραφής %s=%s.</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>Αναβάθμιση της βάσης δεδομένων UTXO</translation>
+ </message>
+ <message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation>Το σχόλιο του παράγοντα χρήστη (%s) περιέχει μη ασφαλείς χαρακτήρες.</translation>
+ </message>
+ <message>
<source>Verifying blocks...</source>
<translation>Επαλήθευση των μπλοκ...</translation>
</message>
<message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>Το πορτοφόλι χρειάζεται να ξαναγραφεί: κάντε επανεκκίνηση του %s για να ολοκληρώσετε</translation>
+ </message>
+ <message>
+ <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
+ <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 =: '%s' (πρέπει να είναι τουλάχιστον το minrelay έξοδο του %s για την αποφυγή κολλημένων συναλλαγών)</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</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 για να επιστρέψετε στη λειτουργία χωρίς εκτύπωση. Αυτό θα ξαναφορτώσει ολόκληρο το blockchain</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Σφάλμα ανάγνωσης από τη βάση δεδομένων, γίνεται τερματισμός.</translation>
</message>
<message>
+ <source>Error upgrading chainstate database</source>
+ <translation>Σφάλμα κατά την αναβάθμιση της βάσης δεδομένων chainstate</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is low for %s</source>
+ <translation>Σφάλμα: Ο χώρος στο δίσκο είναι χαμηλός για %s</translation>
+ </message>
+ <message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Μη έγκυρη διεύθυνση μητρώου ή όνομα κεντρικού υπολογιστή: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>Μη έγκυρη διεύθυνση -proxy ή όνομα κεντρικού υπολογιστή: '%s'</translation>
+ </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>
+ </message>
+ <message>
+ <source>Invalid netmask specified in -whitelist: '%s'</source>
+ <translation>Μη έγκυρη μάσκα δικτύου που καθορίζεται στο -whitelist: '%s'</translation>
+ </message>
+ <message>
+ <source>Need to specify a port with -whitebind: '%s'</source>
+ <translation>Πρέπει να καθορίσετε μια θύρα με -whitebind: '%s'</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Η λειτουργία Prune είναι ασύμβατη με το -blokfilterindex.</translation>
+ </message>
+ <message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation>Μείωση -maxconnections από %d σε %d, λόγω των περιορισμών του συστήματος.</translation>
+ </message>
+ <message>
+ <source>Section [%s] is not recognized.</source>
+ <translation>Το τμήμα [%s] δεν αναγνωρίζεται.</translation>
+ </message>
+ <message>
<source>Signing transaction failed</source>
- <translation>Η υπογραφή συναλλαγής απέτυχε </translation>
+ <translation>Η υπογραφή συναλλαγής απέτυχε</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Δεν υπάρχει καθορισμένο "%s"</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Το συγκεκριμένο -walletdir "%s" είναι μια σχετική διαδρομή</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Το συγκεκριμένο -walletdir "%s" δεν είναι κατάλογος</translation>
+ </message>
+ <message>
+ <source>The specified config file %s does not exist
+</source>
+ <translation>Το καθορισμένο αρχείο ρυθμίσεων %s δεν υπάρχει
+</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation>Το ποσό της συναλλαγής είναι πολύ μικρό για να πληρώσει το έξοδο</translation>
</message>
<message>
<source>This is experimental software.</source>
@@ -2030,10 +3657,70 @@
<translation>Η συναλλαγή είναι πολύ μεγάλη</translation>
</message>
<message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation> Δεν είναι δυνατή η δέσμευση του %s σε αυτόν τον υπολογιστή (δεσμεύει το επιστρεφόμενο σφάλμα %s)</translation>
+ </message>
+ <message>
+ <source>Unable to create the PID file '%s': %s</source>
+ <translation>Δεν είναι δυνατή η δημιουργία του PID αρχείου '%s': %s</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation>Δεν είναι δυνατή η δημιουργία αρχικών κλειδιών</translation>
+ </message>
+ <message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation> Άγνωστη -blockfilterindex τιμή %s.</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>Επαλήθευση πορτοφολιού(ιών)...</translation>
+ </message>
+ <message>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <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>
+ <message>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>Αυτό είναι το τέλος συναλλαγής που μπορείτε να πληρώσετε όταν δεν υπάρχουν εκτιμήσεις τελών.</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>Ξεκινώντας τα νήματα δικτύου ...</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>Το πορτοφόλι θα αποφύγει να πληρώσει λιγότερο από το ελάχιστο έξοδο αναμετάδοσης.</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>Αυτή είναι η ελάχιστη χρέωση συναλλαγής που πληρώνετε για κάθε συναλλαγή.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>Αυτή είναι η χρέωση συναλλαγής που θα πληρώσετε εάν στείλετε μια συναλλαγή.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>Τα ποσά των συναλλαγών δεν πρέπει να είναι αρνητικά</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>Η συναλλαγή έχει μια μακρά αλυσίδα mempool</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>Η συναλλαγή πρέπει να έχει τουλάχιστον έναν παραλήπτη</translation>
+ </message>
+ <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>Έχει οριστεί άγνωστo δίκτυο στο -onlynet: '%s'</translation>
</message>
@@ -2042,6 +3729,18 @@
<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>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Δεν είναι δυνατή η εγγραφή στον κατάλογο δεδομένων '%s'. ελέγξτε τα δικαιώματα.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Φόρτωση ευρετηρίου μπλοκ...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts
deleted file mode 100644
index 85d5c62c91..0000000000
--- a/src/qt/locale/bitcoin_el_GR.ts
+++ /dev/null
@@ -1,2095 +0,0 @@
-<TS language="el_GR" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Δεξί-κλικ για επεξεργασία της διεύθυνσης ή της ετικέτας</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Δημιουργία νέας διεύθυνσης</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Νέo</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Αντέγραψε την επιλεγμένη διεύθυνση στο πρόχειρο του συστήματος</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Αντιγραφή</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>Κ&amp;λείσιμο</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <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>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Εξαγωγή</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Διαγραφή</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Επιλέξτε διεύθυνση αποστολής των νομισμάτων σας</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Επιλέξτε διεύθυνση παραλαβής νομισμάτων</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>Ε&amp;πιλογή</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Διευθύνσεις αποστολής</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <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>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Αυτές είναι οι Bitcoin διευθύνσεις σας για να λαμβάνετε πληρωμές. Προτείνετε να χρησιμοποιείτε μια νέα διεύθυνση παραλήπτη για κάθε συναλλαγή.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Αντιγραφή Διεύθυνσης</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Αντιγραφή&amp;Ετικέτα</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Διόρθωση</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Εξαγωγή Λίστας Διευθύνσεων</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Αρχείο οριοθετημένο με κόμματα (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Αποτυχία Εξαγωγής</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Σφάλμα κατά την προσπάθεια αποθήκευσης της λίστας διευθύνσεων στο %1. Παρακαλώ δοκιμάστε ξανά.</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Ετικέτα</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Διεύθυνση</translation>
- </message>
- <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>
- <message>
- <source>New passphrase</source>
- <translation>&amp;Αλλαγή κωδικού</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Επανέλαβε τον νέο κωδικό πρόσβασης</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Προβολή κωδικού πρόσβασης</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>&amp;Κρυπτογράφηση πορτοφολιού</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>
- <message>
- <source>Decrypt wallet</source>
- <translation>Αποκρυπτογράφησε το πορτοφόλι</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Αλλάξτε Φράση Πρόσβασης</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Εισάγετε την παλιά φράση κλειδί και την νέα φράση κλειδί στο πορτοφόλι.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Επιβεβαίωσε κρυπτογράφηση πορτοφολιού</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Προσόχη! Εάν κρυπτογραφήσεις το πορτοφόλι σου και χάσεις τη φράση αποκατάστασης, θα &lt;b&gt; ΧΑΣΕΙΣ ΟΛΑ ΣΟΥ ΤΑ BITCOIN &lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Είστε σίγουρος/η ότι θέλετε να κρυπτογραφήσετε το πορτοφόλι σας;</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Πορτοφόλι κρυπτογραφήθηκε</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 θα κλείσει τώρα για να τελειώσει η διαδικασία κρυπτογράφησης. Να θυμάστε ότι κρυπτογραφόντας το πορτοφόλι σας δεν μπορείτε να προστατεύσετε πλήρως τα bitcoin σας απο κλοπή μέσω malware που μπορεί να προσβάλει τον υπολογιστή σας.</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>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Η κρυπτογράφηση του πορτοφολιού απέτυχε</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Η κρυπτογράφηση του πορτοφολιού απέτυχε λογω εσωτερικού σφάλματος. Το πορτοφολι δεν κρυπτογραφηθηκε.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Οι εισαχθέντες κωδικοί δεν ταιριάζουν.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Το ξεκλείδωμα του πορτοφολιού απέτυχε</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Ο κωδικος που εισήχθη για την αποκρυπτογραφηση του πορτοφολιού ήταν λαθος.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation> Η αποκρυπτογράφηση του πορτοφολιού απέτυχε </translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Η φράση πρόσβασης άλλαξε επιτυχώς</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Προσοχη: το πλήκτρο Caps Lock είναι ενεργο.</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmask</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Απαγορευμένο έως</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Υπογραφή &amp;μηνύματος...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Συγχρονισμός με το δίκτυο...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Επισκόπηση</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Κόμβος</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Εμφάνισε τη γενική εικόνα του πορτοφολιού</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Συναλλαγές</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Περιήγηση στο ιστορικό συναλλαγών</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>Έ&amp;ξοδος</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Έξοδος από την εφαρμογή</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Περί %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Εμφάνισε πληροφορίες σχετικά με %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Σχετικά με &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Εμφάνισε πληροφορίες σχετικά με Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Επιλογές...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Επεργασία ρυθμισεων επιλογών για το %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Κρυπτογράφησε το πορτοφόλι</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Αντίγραφο ασφαλείας του πορτοφολιού</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Άλλαξε Φράση Πρόσβασης</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>Διευθύνσεις αποστολής</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Διευθύνσεις λήψης</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>'Ανοιγμα &amp;URI</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>Πορτοφόλι</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>Προεπιλεγμένο πορτοφόλι</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Κάντε κλικ για να απενεργοποιήσετε το δίκτυο.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Η δραστηριότητα δικτύου είναι απενεργοποιημένη.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Κάντε κλικ για να ενεργοποιήσετε τo δίκτυο ξανά.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Συγχρονισμός Επικεφαλίδων (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρό δίσκο...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Στείλε νομίσματα σε μια διεύθυνση bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Δημιουργία αντιγράφου ασφαλείας πορτοφολιού σε άλλη τοποθεσία</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Αλλαγή του κωδικού κρυπτογράφησης του πορτοφολιού</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Παράθυρο αποσφαλμάτωσης</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Άνοιγμα κονσόλας αποσφαλμάτωσης και διαγνωστικών</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Επιβεβαίωση μηνύματος</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Πορτοφόλι</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Αποστολή</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Παραλαβή </translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Εμφάνισε/Κρύψε</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Εμφάνιση ή απόκρυψη του κεντρικού παραθύρου</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Κρυπτογραφήστε τα ιδιωτικά κλειδιά που ανήκουν στο πορτοφόλι σας </translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Υπογράψτε ένα μήνυμα για να βεβαιώσετε πως είστε ο κάτοχος αυτής της διεύθυνσης</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Υπογράψτε ένα μήνυμα για ν' αποδείξετε πως ανήκει μια συγκεκριμένη διεύθυνση Bitcoin</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Αρχείο</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Ρυθμίσεις</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Βοήθεια</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Εργαλειοθήκη καρτελών</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Αίτηση πληρωμών (δημιουργεί QR codes και διευθύνσεις bitcoin: )</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Προβολή της λίστας των χρησιμοποιημένων διευθύνσεων και ετικετών αποστολής</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Προβολή της λίστας των χρησιμοποιημένων διευθύνσεων και ετικετών λήψεως</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Άνοιγμα bitcoin: URI αίτησης πληρωμής</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Επιλογές γραμμής εντολών</translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρο δισκο...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρο δισκο...</translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 πίσω</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Το τελευταίο μπλοκ που ελήφθη δημιουργήθηκε %1 πριν.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Οι συναλλαγές μετά από αυτό δεν θα είναι ακόμη ορατές.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Σφάλμα</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Προειδοποίηση</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Πληροφορία</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Ενημερωμένο</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Ενημέρωση...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Ημερομηνία: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Ποσό: %1
-</translation>
- </message>
- <message>
- <source>Wallet: %1
-</source>
- <translation>Πορτοφόλι: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Τύπος: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Ετικέτα: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Διεύθυνση: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Η συναλλαγή απεστάλη</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Εισερχόμενη συναλλαγή</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>Το πορτοφόλι είναι &lt;b&gt;κρυπτογραφημένο&lt;/b&gt; και &lt;b&gt;ξεκλείδωτο&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation>Το πορτοφόλι είναι &lt;b&gt;κρυπτογραφημένο&lt;/b&gt; και &lt;b&gt;κλειδωμένο&lt;/b&gt;</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Επιλογή κερμάτων</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Ποσότητα:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Ποσό:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Ταρίφα:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Σκόνη:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Ταρίφα αλλαγής:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Ρέστα:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(από)επιλογή όλων</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Εμφάνιση τύπου δέντρο</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Λίστα εντολών</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Ποσό</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Παραλήφθηκε με επιγραφή</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Παραλείφθηκε με την εξής διεύθυνση</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Ημερομηνία</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Επικυρώσεις</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Επικυρωμένες</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Αντιγραφή διεύθυνσης</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Αντιγραφή ετικέτας</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Αντιγραφή ποσού</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Αντιγραφή ταυτότητας συναλλαγής</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Αντιγραφή ποσότητας</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <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>
- <message>
- <source>(change)</source>
- <translation>(αλλαγή)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Επεξεργασία Διεύθυνσης</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Επιγραφή</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>Η ετικέτα που συνδέεται με αυτήν την καταχώρηση στο βιβλίο διευθύνσεων</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>Η διεύθυνση σχετίζεται με αυτή την καταχώρηση του βιβλίου διευθύνσεων. Μπορεί να τροποποιηθεί μόνο για τις διευθύνσεις αποστολής.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Διεύθυνση</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Νέα Διεύθυνση Αποστολής</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Διόρθωση Διεύθυνσης Λήψης</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <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>
- </message>
- <message>
- <source>The entered address "%1" is already in the address book with label "%2".</source>
- <translation>Η διεύθυνση "%1" βρίσκεται ήδη στο βιβλίο διευθύνσεων με ετικέτα "%2".</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Δεν είναι δυνατό το ξεκλείδωμα του πορτοφολιού.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Η δημιουργία νέου κλειδιού απέτυχε.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Θα δημιουργηθεί ένας νέος φάκελος δεδομένων.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>όνομα</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>Κατάλογος ήδη υπάρχει. Προσθήκη %1, αν σκοπεύετε να δημιουργήσετε έναν νέο κατάλογο εδώ.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Η διαδρομή υπάρχει ήδη αλλά δεν είναι φάκελος</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Δεν μπορεί να δημιουργηθεί φάκελος δεδομένων εδώ.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>έκδοση</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>Σχετικά %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Επιλογές γραμμής εντολών</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Καλώς ήρθατε</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Χρήση του προεπιλεγμένου φακέλου δεδομένων</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Προσαρμογή του φακέλου δεδομένων: </translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Σφάλμα: Ο καθορισμένος φάκελος δεδομένων "%1" δεν μπορεί να δημιουργηθεί.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Σφάλμα</translation>
- </message>
- <message numerus="yes">
- <source>%n GB of free space available</source>
- <translation><numerusform>%n GB ελεύθερου χώρου διαθέσιμα</numerusform><numerusform>%n GB ελεύθερου χώρου διαθέσιμα</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>(of %n GB needed)</source>
- <translation><numerusform>(από το %n GB που απαιτείται)</numerusform><numerusform>(από τα %n GB που απαιτούνται)</numerusform></translation>
- </message>
-</context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Φόρμα</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Άγνωστο...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Χρόνος τελευταίου μπλοκ</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Απόκρυψη</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Άνοιγμα &amp;URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Ανοιχτό αίτημα πληρωμής από URI ή από αρχείο</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Επιλέξτε πληρωμή αρχείου αίτησης</translation>
- </message>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Ρυθμίσεις</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Κύριο</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Μέγεθος κρυφής μνήμης βάσης δεδομένων.</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>Αριθμός script και γραμμές επαλήθευσης </translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Διεύθυνση IP του διαμεσολαβητή (π.χ. 127.0.0.1 / IPv6: ::1)</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>Ελαχιστοποίηση αντί για έξοδο κατά το κλείσιμο του παραθύρου. Όταν αυτή η επιλογή είναι ενεργοποιημένη, η εφαρμογή θα κλείνει μόνο αν επιλεχθεί η Έξοδος στο μενού.</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>URLs από τρίτους (π.χ. ένας εξερευνητής μπλοκ) τα οποία εμφανίζονται στην καρτέλα συναλλαγών ως στοιχεία μενού. Το %s στα URL αντικαθίσταται από την τιμή της κατατεμαχισμένης συναλλαγής.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Ενεργές επιλογές γραμμής-εντολών που παρακάμπτουν τις παραπάνω επιλογές:</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Άνοιγμα Αρχείου Ρυθμίσεων</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Επαναφορά όλων των επιλογών του πελάτη στις αρχικές.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>Επαναφορά ρυθμίσεων</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Δίκτυο</translation>
- </message>
- <message>
- <source>GB</source>
- <translation>GB</translation>
- </message>
- <message>
- <source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = αυτόματο, &lt;0 = ελεύθεροι πυρήνες)</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>Π&amp;ορτοφόλι</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Έμπειρος</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Ενεργοποίηση δυνατοτήτων ελέγχου κερμάτων</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>Εάν απενεργοποιήσετε το ξόδεμα μη επικυρωμένων ρέστων, τα ρέστα από μια συναλλαγή δεν μπορούν να χρησιμοποιηθούν έως ότου αυτή η συναλλαγή έχει έστω μια επικύρωση. Αυτό επίσης επηρεάζει το πως υπολογίζεται το υπόλοιπό σας.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <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>
- <translation>Αυτόματο άνοιγμα των θυρών Bitcoin στον δρομολογητή. Λειτουργεί μόνο αν ο δρομολογητής σας υποστηρίζει τη λειτουργία UPnP.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Απόδοση θυρών με χρήστη &amp;UPnP</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Σύνδεση στο δίκτυο Bitcoin μέσω διαμεσολαβητή SOCKS5 (π.χ. για σύνδεση μέσω Tor)</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Σύνδεση μέσω διαμεσολαβητή SOCKS5 (προεπιλεγμένος)</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>&amp;IP διαμεσολαβητή:</translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>&amp;Θύρα:</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Θύρα διαμεσολαβητή</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;Παράθυρο</translation>
- </message>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Εμφάνιση μόνο εικονιδίου στην περιοχή ειδοποιήσεων κατά την ελαχιστοποίηση.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Ελαχιστοποίηση στην περιοχή ειδοποιήσεων αντί της γραμμής εργασιών</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>Ε&amp;λαχιστοποίηση κατά το κλείσιμο</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Απεικόνιση</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>Γλώσσα περιβάλλοντος εργασίας:</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Μονάδα μέτρησης:</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Διαλέξτε την προεπιλεγμένη υποδιαίρεση που θα εμφανίζεται όταν στέλνετε νομίσματα.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Επιλογή κατά πόσο να αναδείχνονται οι δυνατότητες ελέγχου κερμάτων.</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;ΟΚ</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Ακύρωση</translation>
- </message>
- <message>
- <source>default</source>
- <translation>προεπιλογή</translation>
- </message>
- <message>
- <source>none</source>
- <translation>κανένα</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Επιβεβαίωση των επιλογών επαναφοράς</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Χρειάζεται επανεκκίνηση του προγράμματος για να ενεργοποιηθούν οι αλλαγές.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Σφάλμα</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Η αλλαγή αυτή θα χρειαστεί επανεκκίνηση του προγράμματος</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Δεν είναι έγκυρη η διεύθυνση διαμεσολαβητή</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Φόρμα</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>Οι πληροφορίες που εμφανίζονται μπορεί να είναι ξεπερασμένες. Το πορτοφόλι σας συγχρονίζεται αυτόματα με το δίκτυο Bitcoin μετά από μια σύνδεση, αλλά αυτή η διαδικασία δεν έχει ακόμη ολοκληρωθεί. </translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Επίβλεψη μόνο:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Διαθέσιμο:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Το τρέχον διαθέσιμο υπόλοιπο</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Εκκρεμούν:</translation>
- </message>
- <message>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Το άθροισμα των συναλλαγών που δεν έχουν ακόμα επιβεβαιωθεί και δεν προσμετρώνται στο τρέχον διαθέσιμο υπόλοιπό σας</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Ανώριμος</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>Εξορυγμένο υπόλοιπο που δεν έχει ακόμα ωριμάσει</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Υπόλοιπο:</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Σύνολο:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Το τρέχον συνολικό υπόλοιπο</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>Το τρέχον υπόλοιπο σας σε διευθύνσεις παρακολούθησης μόνο</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Ξοδεμένα:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Πρόσφατες συναλλαγές</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Μη επικυρωμένες συναλλαγές σε διευθύνσεις παρακολούθησης μόνο</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Εξορυγμένο υπόλοιπο σε διευθύνσεις παρακολούθησης μόνο που δεν έχει ωριμάσει ακόμα</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>Το τρέχον συνολικό υπόλοιπο σε διευθύνσεις παρακολούθησης μόνο</translation>
- </message>
-</context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Σφάλμα αίτησης πληρωμής</translation>
- </message>
- <message>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>Δεν είναι δυνατή η εκκίνηση του bitcoin: χειριστής click-to-pay</translation>
- </message>
- <message>
- <source>URI handling</source>
- <translation>URI χειριστής</translation>
- </message>
- <message>
- <source>Payment request file handling</source>
- <translation>Επεξεργασία αρχείου αίτησης πληρωμής</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Η αίτηση πληρωμής απορρίφθηκε</translation>
- </message>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>Sent</source>
- <translation>Αποστολή</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Παραλήφθησαν</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Ποσό</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Εισάγετε μια διεύθυνση Bitcoin (π.χ. %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>Κανένα</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>Μη διαθέσιμο</translation>
- </message>
- <message>
- <source>%1 ms</source>
- <translation>%1 ms</translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 και %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>unknown</source>
- <translation>Άγνωστο</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>Μη διαθέσιμο</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Έκδοση Πελάτη</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Πληροφορία</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Παράθυρο αποσφαλμάτωσης</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Γενικά</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>Χρήση BerkeleyDB έκδοσης</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Χρόνος εκκίνησης</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Δίκτυο</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Όνομα</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Αριθμός συνδέσεων</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Αλυσίδα μπλοκ</translation>
- </message>
- <message>
- <source>Current number of blocks</source>
- <translation>Τρέχον αριθμός μπλοκ</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>χρήση Μνήμης</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Παραλήφθησαν</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Αποστολή</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Χρήστες</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <translation>Επιλέξτε ένα χρήστη για να δείτε αναλυτικές πληροφορίες.</translation>
- </message>
- <message>
- <source>Version</source>
- <translation>Έκδοση</translation>
- </message>
- <message>
- <source>Decrease font size</source>
- <translation>Μείωση μεγέθους γραμματοσειράς</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation>Αύξηση μεγέθους γραμματοσειράς</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Υπηρεσίες</translation>
- </message>
- <message>
- <source>Ban Score</source>
- <translation>Σκορ Aποκλεισμού</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Χρόνος σύνδεσης</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Τελευταία αποστολή</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Τελευταία λήψη</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Χρόνος καθυστέρησης</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Χρόνος τελευταίου μπλοκ</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Άνοιγμα</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Κονσόλα</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Κίνηση δικτύου</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Σύνολα</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Εισερχόμενα:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Εξερχόμενα:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Αρχείο καταγραφής εντοπισμού σφαλμάτων </translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Καθαρισμός κονσόλας</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;ώρα</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;μέρα</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;εβδομάδα</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;χρόνος</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>Προεπιλεγμένο πορτοφόλι</translation>
- </message>
- <message>
- <source>via %1</source>
- <translation>μέσω %1</translation>
- </message>
- <message>
- <source>never</source>
- <translation>ποτέ</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Εισερχόμενα</translation>
- </message>
- <message>
- <source>Outbound</source>
- <translation>Εξερχόμενα</translation>
- </message>
- <message>
- <source>Yes</source>
- <translation>Ναι</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Όχι</translation>
- </message>
- <message>
- <source>Unknown</source>
- <translation>Άγνωστο(α)</translation>
- </message>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>&amp;Ποσό:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Επιγραφή</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Μήνυμα:</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Καθαρισμός όλων των πεδίων της φόρμας.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Καθαρισμός</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Αίτηση πληρωμής</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Εμφάνιση</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Αφαίρεση επιλεγμένων καταχωρίσεων από τη λίστα</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Αφαίρεση</translation>
- </message>
- <message>
- <source>Copy URI</source>
- <translation>Αντιγραφή της επιλεγμένης διεύθυνσης στο πρόχειρο του συστήματος</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Αντιγραφή ετικέτας</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Αντιγραφή μηνύματος</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Αντιγραφή ποσού</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>Κώδικας QR</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Αντιγραφή της επιλεγμένης διεύθυνσης στο πρόχειρο του συστήματος</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Αντιγραφή &amp;Διεύθυνσης</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Αποθήκευση εικόνας...</translation>
- </message>
- <message>
- <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>
- <message>
- <source>Date</source>
- <translation>Ημερομηνία</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Ετικέτα</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Μήνυμα</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(χωρίς ετικέτα)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Αποστολή νομισμάτων</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Χαρακτηριστικά επιλογής κερμάτων</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Εισροές...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>επιλεγμένο αυτόματα</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Ανεπαρκές κεφάλαιο!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Ποσότητα:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Ποσό:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Ταρίφα:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Ταρίφα αλλαγής:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Ρέστα:</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>Όταν ενεργό, αλλά η διεύθυνση ρέστων είναι κενή ή άκυρη, τα ρέστα θα σταλούν σε μία πρόσφατα δημιουργημένη διεύθυνση.</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Προσαρμοσμένη διεύθυνση ρέστων</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Τέλος συναλλαγής:</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Επιλογή...</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>ανά kilobyte</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Απόκρυψη</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Προτεινόμενο: </translation>
- </message>
- <message>
- <source>Custom:</source>
- <translation>Προσαρμογή:</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Αποστολή σε πολλούς αποδέκτες ταυτόχρονα</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>&amp;Προσθήκη αποδέκτη</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Καθαρισμός όλων των πεδίων της φόρμας.</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Σκόνη:</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Καθαρισμός &amp;Όλων</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Υπόλοιπο:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Επιβεβαίωση αποστολής</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>Αποστολή</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Αντιγραφή ποσότητας</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Αντιγραφή ποσού</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Αντιγραφή τελών</translation>
- </message>
- <message>
- <source>or</source>
- <translation>ή</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Κόστος συναλλαγής</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(χωρίς ετικέτα)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>&amp;Ποσό:</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>Πληρωμή &amp;σε:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Επιγραφή</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Επιλογή διεύθυνσης που έχει ήδη χρησιμοποιηθεί</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Αυτή είναι μια απλή πληρωμή.</translation>
- </message>
- <message>
- <source>The Bitcoin address to send the payment to</source>
- <translation>Η διεύθυνση Bitcoin που θα σταλεί η πληρωμή</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Επικόλληση διεύθυνσης από το βιβλίο διευθύνσεων</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Αφαίρεση αυτής της καταχώρησης</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Μήνυμα:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Εισάγετε μία ετικέτα για αυτή την διεύθυνση για να προστεθεί στη λίστα με τις χρησιμοποιημένες διευθύνσεις</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Πληρωμή σε:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Σημείωση:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ναι</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>Μην απενεργοποιήσετε τον υπολογιστή μέχρι να κλείσει αυτό το παράθυρο.</translation>
- </message>
-</context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Υπογραφές - Είσοδος / Επαλήθευση Mηνύματος </translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Υπογραφή Μηνύματος</translation>
- </message>
- <message>
- <source>The Bitcoin address to sign the message with</source>
- <translation>Διεύθυνση Bitcoin που θα σταλεί το μήνυμα</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Επιλογή διεύθυνσης που έχει ήδη χρησιμοποιηθεί</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Επικόλληση διεύθυνσης από το βιβλίο διευθύνσεων</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Εισάγετε εδώ το μήνυμα που θέλετε να υπογράψετε</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Υπογραφή</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Αντιγραφή της επιλεγμένης υπογραφής στο πρόχειρο του συστήματος</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Υπογράψτε το μήνυμα για να αποδείξετε πως σας ανήκει η συγκεκριμένη διεύθυνση Bitcoin</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Υπογραφη μήνυματος</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Επαναφορά όλων των πεδίων μήνυματος</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Καθαρισμός &amp;Όλων</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Επιβεβαίωση Mηνύματος</translation>
- </message>
- <message>
- <source>The Bitcoin address the message was signed with</source>
- <translation>Διεύθυνση Bitcoin με την οποία έχει υπογραφεί το μήνυμα</translation>
- </message>
- <message>
- <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Επαληθεύστε το μήνυμα για να αποδείξετε πως υπογράφθηκε από τη συγκεκριμένη διεύθυνση Bitcoin</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Επιβεβαίωση Mηνύματος</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Επαναφορά όλων των πεδίων επαλήθευσης μηνύματος</translation>
- </message>
- </context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KB/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Open until %1</source>
- <translation>Ανοιχτό μέχρι %1</translation>
- </message>
- <message>
- <source>0/unconfirmed, %1</source>
- <translation>0/ανεπιβεβαίωτο, %1</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Ημερομηνία</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Πηγή</translation>
- </message>
- <message>
- <source>Generated</source>
- <translation>Παράχθηκε</translation>
- </message>
- <message>
- <source>From</source>
- <translation>Από</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>Άγνωστο</translation>
- </message>
- <message>
- <source>To</source>
- <translation>Προς</translation>
- </message>
- <message>
- <source>own address</source>
- <translation>δική σας διεύθυνση</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>παρακολούθηση-μόνο</translation>
- </message>
- <message>
- <source>label</source>
- <translation>ετικέτα</translation>
- </message>
- <message>
- <source>Credit</source>
- <translation>Πίστωση</translation>
- </message>
- <message>
- <source>not accepted</source>
- <translation>μη έγκυρο</translation>
- </message>
- <message>
- <source>Total credit</source>
- <translation>Συνολική πίστωση</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Κόστος συναλλαγής</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Μήνυμα</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Ποσό</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Αυτό το παράθυρο δείχνει μια λεπτομερή περιγραφή της συναλλαγής</translation>
- </message>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Ημερομηνία</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Ετικέτα</translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Ανοιχτό μέχρι %1</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>παρακολούθηση-μόνο</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(χωρίς ετικέτα)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Copy address</source>
- <translation>Αντιγραφή διεύθυνσης</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Αντιγραφή ετικέτας</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Αντιγραφή ποσού</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Αντιγραφή ταυτότητας συναλλαγής</translation>
- </message>
- <message>
- <source>Copy raw transaction</source>
- <translation>Αντιγραφή ανεπεξέργαστης συναλλαγής</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Επεξεργασία ετικέτας</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Αρχείο οριοθετημένο με κόμματα (*.csv)</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Ημερομηνία</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Ετικέτα</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Διεύθυνση</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Αποτυχία Εξαγωγής</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- <message>
- <source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Μονάδα μέτρησης προβολής ποσών. Κάντε κλικ για επιλογή άλλης μονάδας.</translation>
- </message>
-</context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Increase:</source>
- <translation>Αύξηση:</translation>
- </message>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>Cancel</source>
- <translation>Ακύρωση</translation>
- </message>
-</context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>Corrupted block database detected</source>
- <translation>Εντοπίσθηκε διεφθαρμένη βάση δεδομένων των μπλοκ</translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Θέλετε να δημιουργηθεί τώρα η βάση δεδομένων των μπλοκ;</translation>
- </message>
- <message>
- <source>Error initializing block database</source>
- <translation>Σφάλμα κατά την ενεργοποίηση της βάσης δεδομένων των μπλοκ</translation>
- </message>
- <message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Σφάλμα κατά την ενεργοποίηση της βάσης δεδομένων πορτοφολιού %s!</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Σφάλμα φόρτωσης της βάσης δεδομένων των μπλοκ</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Σφάλμα φόρτωσης της βάσης δεδομένων των μπλοκ</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Σφάλμα: Χαμηλός χώρος στο δίσκο!</translation>
- </message>
- <message>
- <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>Αποτυχία παρακολούθησης σε οποιαδήποτε θύρα. Χρησιμοποιήστε -listen=0 αν θέλετε αυτό.</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>Εισαγωγή...</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>Δεν υπάρχουν αρκετοί περιγραφείς αρχείων διαθέσιμοι.</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Επαλήθευση των μπλοκ...</translation>
- </message>
- <message>
- <source>Error reading from database, shutting down.</source>
- <translation>Σφάλμα ανάγνωσης από τη βάση δεδομένων, γίνεται τερματισμός.</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Πληροφορία</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Η υπογραφή συναλλαγής απέτυχε </translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>Η εφαρμογή είναι σε πειραματικό στάδιο.</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Το ποσό της συναλλαγής είναι πολύ μικρό</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Η συναλλαγή είναι πολύ μεγάλη</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Προειδοποίηση</translation>
- </message>
- <message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Μεταφορά όλων των συναλλαγών από το πορτοφόλι</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Έχει οριστεί άγνωστo δίκτυο στο -onlynet: '%s'</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Ανεπαρκές κεφάλαιο</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Φόρτωση ευρετηρίου μπλοκ...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Φόρτωση πορτοφολιού...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Δεν μπορώ να υποβαθμίσω το πορτοφόλι</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Ανίχνευση...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Η φόρτωση ολοκληρώθηκε</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Σφάλμα</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index d34fd9eb45..6b4174f313 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -312,7 +312,7 @@
<context>
<name>BanTableModel</name>
<message>
- <location filename="../bantablemodel.cpp" line="+88"/>
+ <location filename="../bantablemodel.cpp" line="+86"/>
<source>IP/Netmask</source>
<translation type="unfinished"></translation>
</message>
@@ -330,12 +330,12 @@
<translation>Sign &amp;message...</translation>
</message>
<message>
- <location line="+623"/>
+ <location line="+630"/>
<source>Synchronizing with network...</source>
<translation>Synchronizing with network...</translation>
</message>
<message>
- <location line="-701"/>
+ <location line="-708"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
@@ -420,17 +420,17 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+2"/>
<source>Create a new wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+190"/>
+ <location line="+191"/>
<source>Wallet:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+334"/>
+ <location line="+339"/>
<source>Click to disable network activity.</source>
<translation type="unfinished"></translation>
</message>
@@ -460,7 +460,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1021"/>
+ <location line="-1028"/>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
@@ -475,17 +475,7 @@
<translation>Change the passphrase used for wallet encryption</translation>
</message>
<message>
- <location line="+6"/>
- <source>&amp;Debug window</source>
- <translation>&amp;Debug window</translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Open debugging and diagnostic console</source>
- <translation>Open debugging and diagnostic console</translation>
- </message>
- <message>
- <location line="-4"/>
+ <location line="+3"/>
<source>&amp;Verify message...</source>
<translation>&amp;Verify message...</translation>
</message>
@@ -525,7 +515,7 @@
<translation>Verify messages to ensure they were signed with specified Bitcoin addresses</translation>
</message>
<message>
- <location line="+110"/>
+ <location line="+111"/>
<source>&amp;File</source>
<translation>&amp;File</translation>
</message>
@@ -535,7 +525,7 @@
<translation>&amp;Settings</translation>
</message>
<message>
- <location line="+58"/>
+ <location line="+59"/>
<source>&amp;Help</source>
<translation>&amp;Help</translation>
</message>
@@ -545,7 +535,7 @@
<translation>Tabs toolbar</translation>
</message>
<message>
- <location line="-256"/>
+ <location line="-258"/>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished"></translation>
</message>
@@ -560,17 +550,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>Open a bitcoin: URI or payment request</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+13"/>
+ <location line="+17"/>
<source>&amp;Command-line options</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location line="+522"/>
+ <location line="+528"/>
<source>%n active connection(s) to Bitcoin network</source>
<translation>
<numerusform>%n active connection to Bitcoin network</numerusform>
@@ -631,7 +616,17 @@
<translation>Up to date</translation>
</message>
<message>
- <location line="-642"/>
+ <location line="-655"/>
+ <source>Node window</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Open node debugging and diagnostic console</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+5"/>
<source>&amp;Sending addresses</source>
<translation type="unfinished"></translation>
</message>
@@ -641,7 +636,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+4"/>
+ <source>Open a bitcoin: URI</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
<source>Open Wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -661,7 +661,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+8"/>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation type="unfinished"></translation>
</message>
@@ -696,7 +696,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+232"/>
+ <location line="+238"/>
<source>%1 client</source>
<translation type="unfinished"></translation>
</message>
@@ -792,7 +792,7 @@
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="+386"/>
+ <location filename="../bitcoin.cpp" line="+384"/>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
<translation type="unfinished"></translation>
</message>
@@ -885,7 +885,7 @@
<translation type="unfinished">Confirmed</translation>
</message>
<message>
- <location filename="../coincontroldialog.cpp" line="+54"/>
+ <location filename="../coincontroldialog.cpp" line="+53"/>
<source>Copy address</source>
<translation type="unfinished"></translation>
</message>
@@ -990,7 +990,7 @@
<context>
<name>CreateWalletActivity</name>
<message>
- <location filename="../walletcontroller.cpp" line="+201"/>
+ <location filename="../walletcontroller.cpp" line="+209"/>
<source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
<translation type="unfinished"></translation>
</message>
@@ -1124,7 +1124,7 @@
<context>
<name>FreespaceChecker</name>
<message>
- <location filename="../intro.cpp" line="+73"/>
+ <location filename="../intro.cpp" line="+71"/>
<source>A new data directory will be created.</source>
<translation>A new data directory will be created.</translation>
</message>
@@ -1152,18 +1152,12 @@
<context>
<name>HelpMessageDialog</name>
<message>
- <location filename="../utilitydialog.cpp" line="+39"/>
+ <location filename="../utilitydialog.cpp" line="+35"/>
<source>version</source>
<translation type="unfinished">version</translation>
</message>
<message>
- <location line="+5"/>
- <location line="+2"/>
- <source>(%1-bit)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+5"/>
+ <location line="+4"/>
<source>About %1</source>
<translation type="unfinished"></translation>
</message>
@@ -1221,27 +1215,27 @@
<translation>Use a custom data directory:</translation>
</message>
<message>
- <location filename="../intro.cpp" line="+22"/>
+ <location filename="../intro.cpp" line="+32"/>
<source>Bitcoin</source>
<translation type="unfinished">Bitcoin</translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+8"/>
<source>Discard blocks after verification, except most recent %1 GB (prune)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+212"/>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+3"/>
<source>Approximately %1 GB of data will be stored in this directory.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+4"/>
<source>%1 will download and store a copy of the Bitcoin block chain.</source>
<translation type="unfinished"></translation>
</message>
@@ -1251,7 +1245,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+78"/>
+ <location line="-137"/>
<source>Error: Specified data directory &quot;%1&quot; cannot be created.</source>
<translation type="unfinished"></translation>
</message>
@@ -1261,7 +1255,7 @@
<translation>Error</translation>
</message>
<message numerus="yes">
- <location line="+9"/>
+ <location line="+21"/>
<source>%n GB of free space available</source>
<translation>
<numerusform>%n GB of free space available</numerusform>
@@ -1269,7 +1263,7 @@
</translation>
</message>
<message numerus="yes">
- <location line="+3"/>
+ <location line="+2"/>
<source>(of %n GB needed)</source>
<translation>
<numerusform>(of %n GB needed)</numerusform>
@@ -1277,7 +1271,7 @@
</translation>
</message>
<message numerus="yes">
- <location line="+4"/>
+ <location line="+3"/>
<source>(%n GB needed for full chain)</source>
<translation type="unfinished">
<numerusform></numerusform>
@@ -1310,7 +1304,7 @@
<message>
<location line="+7"/>
<location line="+26"/>
- <location filename="../modaloverlay.cpp" line="+141"/>
+ <location filename="../modaloverlay.cpp" line="+145"/>
<source>Unknown...</source>
<translation type="unfinished"></translation>
</message>
@@ -1346,36 +1340,31 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../modaloverlay.cpp" line="+6"/>
- <source>Unknown. Syncing Headers (%1, %2%)...</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <location filename="../forms/openuridialog.ui" line="+14"/>
- <source>Open URI</source>
+ <location line="+3"/>
+ <source>Esc</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
- <source>Open payment request from URI or file</source>
+ <location filename="../modaloverlay.cpp" line="-111"/>
+ <source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+9"/>
- <source>URI:</source>
+ <location line="+117"/>
+ <source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation type="unfinished"></translation>
</message>
+</context>
+<context>
+ <name>OpenURIDialog</name>
<message>
- <location line="+10"/>
- <source>Select payment request file</source>
+ <location filename="../forms/openuridialog.ui" line="+14"/>
+ <source>Open bitcoin URI</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../openuridialog.cpp" line="+45"/>
- <source>Select payment request file to open</source>
+ <location line="+8"/>
+ <source>URI:</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1474,7 +1463,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+76"/>
+ <location line="+79"/>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished"></translation>
</message>
@@ -1494,7 +1483,7 @@
<translation>&amp;Reset Options</translation>
</message>
<message>
- <location line="-529"/>
+ <location line="-532"/>
<source>&amp;Network</source>
<translation>&amp;Network</translation>
</message>
@@ -1682,7 +1671,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+41"/>
+ <location line="+44"/>
<source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
<translation type="unfinished"></translation>
</message>
@@ -1702,7 +1691,7 @@
<translation>default</translation>
</message>
<message>
- <location line="+67"/>
+ <location line="+65"/>
<source>none</source>
<translation type="unfinished"></translation>
</message>
@@ -1850,65 +1839,48 @@
<context>
<name>PaymentServer</name>
<message>
- <location filename="../paymentserver.cpp" line="+226"/>
- <location line="+350"/>
- <location line="+42"/>
- <location line="+108"/>
- <location line="+14"/>
- <location line="+18"/>
+ <location filename="../paymentserver.cpp" line="+174"/>
<source>Payment request error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-531"/>
+ <location line="+1"/>
<source>Cannot start bitcoin: click-to-pay handler</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+62"/>
- <location line="+9"/>
- <location line="+16"/>
- <location line="+16"/>
- <location line="+7"/>
+ <location line="+50"/>
+ <location line="+13"/>
+ <location line="+6"/>
<location line="+7"/>
<source>URI handling</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-55"/>
+ <location line="-26"/>
<source>&apos;bitcoin://&apos; is not a valid URI. Use &apos;bitcoin:&apos; instead.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+16"/>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+16"/>
- <location line="+38"/>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
+ <location line="+14"/>
+ <location line="+23"/>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-37"/>
- <location line="+38"/>
+ <location line="-22"/>
+ <location line="+23"/>
<source>Due to widespread security flaws in BIP70 it&apos;s strongly recommended that any merchant instructions to switch wallets be ignored.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-37"/>
- <location line="+38"/>
+ <location line="-22"/>
+ <location line="+23"/>
<source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-34"/>
+ <location line="-20"/>
<source>Invalid payment address %1</source>
<translation type="unfinished"></translation>
</message>
@@ -1918,97 +1890,15 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+14"/>
<location line="+9"/>
<source>Payment request file handling</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location line="-8"/>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+201"/>
- <location line="+9"/>
- <location line="+31"/>
- <location line="+10"/>
- <location line="+17"/>
- <location line="+83"/>
- <source>Payment request rejected</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="-150"/>
- <source>Payment request network doesn&apos;t match client network.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+9"/>
- <source>Payment request expired.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+6"/>
- <source>Payment request is not initialized.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+26"/>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+9"/>
- <location line="+17"/>
- <source>Invalid payment request.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="-10"/>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+63"/>
- <source>Refund from %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+31"/>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+9"/>
- <source>Error communicating with %1: %2</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+20"/>
- <source>Payment request cannot be parsed!</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+13"/>
- <source>Bad response from server %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+22"/>
- <source>Network request error</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+6"/>
- <source>Payment acknowledged</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
<message>
- <location filename="../peertablemodel.cpp" line="+110"/>
+ <location filename="../peertablemodel.cpp" line="+107"/>
<source>User Agent</source>
<translation type="unfinished"></translation>
</message>
@@ -2046,12 +1936,12 @@
<translation type="unfinished">Amount</translation>
</message>
<message>
- <location filename="../guiutil.cpp" line="+108"/>
+ <location filename="../guiutil.cpp" line="+111"/>
<source>Enter a Bitcoin address (e.g. %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+699"/>
+ <location line="+618"/>
<source>%1 d</source>
<translation type="unfinished"></translation>
</message>
@@ -2067,7 +1957,7 @@
</message>
<message>
<location line="+2"/>
- <location line="+47"/>
+ <location line="+48"/>
<source>%1 s</source>
<translation type="unfinished"></translation>
</message>
@@ -2161,7 +2051,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="+118"/>
+ <location filename="../bitcoin.cpp" line="+114"/>
<source>Error: Specified data directory &quot;%1&quot; does not exist.</source>
<translation type="unfinished"></translation>
</message>
@@ -2176,7 +2066,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+64"/>
+ <location line="+65"/>
<source>%1 didn&apos;t yet exit safely...</source>
<translation type="unfinished"></translation>
</message>
@@ -2209,7 +2099,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+38"/>
+ <location line="+39"/>
<source>QR code support not available.</source>
<translation type="unfinished"></translation>
</message>
@@ -2257,11 +2147,13 @@
<location line="+26"/>
<location line="+23"/>
<location line="+23"/>
+ <location line="+26"/>
+ <location filename="../rpcconsole.cpp" line="+1121"/>
<source>N/A</source>
<translation>N/A</translation>
</message>
<message>
- <location line="-1430"/>
+ <location line="-1456"/>
<source>Client version</source>
<translation>Client version</translation>
</message>
@@ -2271,12 +2163,7 @@
<translation>&amp;Information</translation>
</message>
<message>
- <location line="-29"/>
- <source>Debug window</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+44"/>
+ <location line="+15"/>
<source>General</source>
<translation type="unfinished"></translation>
</message>
@@ -2389,8 +2276,8 @@
</message>
<message>
<location line="+65"/>
- <location filename="../rpcconsole.cpp" line="+497"/>
- <location line="+759"/>
+ <location filename="../rpcconsole.cpp" line="-624"/>
+ <location line="+756"/>
<source>Select a peer to view detailed information.</source>
<translation type="unfinished"></translation>
</message>
@@ -2425,23 +2312,38 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1164"/>
+ <location line="+256"/>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Mapped AS</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-1423"/>
<location line="+1072"/>
<source>User Agent</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-737"/>
+ <location line="-1146"/>
+ <source>Node window</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+409"/>
<source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+87"/>
+ <location line="+84"/>
<source>Decrease font size</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+29"/>
+ <location line="+32"/>
<source>Increase font size</source>
<translation type="unfinished"></translation>
</message>
@@ -2521,7 +2423,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../rpcconsole.cpp" line="-411"/>
+ <location filename="../rpcconsole.cpp" line="-408"/>
<source>In:</source>
<translation type="unfinished"></translation>
</message>
@@ -2609,7 +2511,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+70"/>
+ <location line="+66"/>
<source>Executing command without any wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -2655,7 +2557,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+13"/>
<location line="+6"/>
<source>Unknown</source>
<translation type="unfinished"></translation>
@@ -2680,13 +2582,11 @@
</message>
<message>
<location line="-3"/>
- <location line="+46"/>
<source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-30"/>
- <location line="+14"/>
+ <location line="+30"/>
<source>An optional label to associate with the new receiving address.</source>
<translation type="unfinished"></translation>
</message>
@@ -2702,7 +2602,17 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-76"/>
+ <location line="-121"/>
+ <source>An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+30"/>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+15"/>
<source>&amp;Create new receiving address</source>
<translation type="unfinished"></translation>
</message>
@@ -2752,7 +2662,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../receivecoinsdialog.cpp" line="+46"/>
+ <location filename="../receivecoinsdialog.cpp" line="+45"/>
<source>Copy URI</source>
<translation type="unfinished"></translation>
</message>
@@ -2795,7 +2705,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../receiverequestdialog.cpp" line="+63"/>
+ <location filename="../receiverequestdialog.cpp" line="+64"/>
<source>Request payment to %1</source>
<translation type="unfinished"></translation>
</message>
@@ -2877,7 +2787,7 @@
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+601"/>
+ <location filename="../sendcoinsdialog.cpp" line="+622"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -2962,12 +2872,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+26"/>
- <source>collapse fee-settings</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+51"/>
+ <location line="+77"/>
<source>Specify a custom fee per kB (1,000 bytes) of the transaction&apos;s virtual size.
Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satoshis per kB&quot; for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
@@ -3019,7 +2924,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+543"/>
+ <location line="+457"/>
+ <source>Hide transaction fee settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+86"/>
<source>When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
<translation type="unfinished"></translation>
</message>
@@ -3064,7 +2974,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation>S&amp;end</translation>
</message>
<message>
- <location filename="../sendcoinsdialog.cpp" line="-513"/>
+ <location filename="../sendcoinsdialog.cpp" line="-533"/>
<source>Copy quantity</source>
<translation type="unfinished"></translation>
</message>
@@ -3104,29 +3014,47 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+118"/>
+ <location line="+22"/>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+100"/>
<source> from wallet &apos;%1&apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+14"/>
<location line="+11"/>
<source>%1 to &apos;%2&apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-6"/>
- <location line="+10"/>
+ <location line="+5"/>
<source>%1 to %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+8"/>
+ <source>Do you want to draft this transaction?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
<source>Are you sure you want to send?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+42"/>
+ <location line="+5"/>
+ <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 type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+43"/>
<source>or</source>
<translation type="unfinished"></translation>
</message>
@@ -3136,12 +3064,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-21"/>
+ <location line="-22"/>
<source>Please, review your transaction.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+8"/>
<source>Transaction fee</source>
<translation type="unfinished"></translation>
</message>
@@ -3161,12 +3089,37 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+5"/>
<source>Confirm send coins</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+190"/>
+ <location line="+0"/>
+ <source>Confirm transaction proposal</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy PSBT to clipboard</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Send</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>PSBT copied</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+166"/>
+ <source>Watch-only balance:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+24"/>
<source>The recipient address is not valid. Please recheck.</source>
<translation type="unfinished"></translation>
</message>
@@ -3197,11 +3150,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+4"/>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+4"/>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished"></translation>
</message>
@@ -3211,7 +3159,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="+120"/>
+ <location line="+125"/>
<source>Estimated to begin confirmation within %n block(s).</source>
<translation>
<numerusform>Estimated to begin confirmation within %n block.</numerusform>
@@ -3248,13 +3196,13 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<name>SendCoinsEntry</name>
<message>
<location filename="../forms/sendcoinsentry.ui" line="+155"/>
- <location line="+546"/>
+ <location line="+550"/>
<location line="+533"/>
<source>A&amp;mount:</source>
<translation>A&amp;mount:</translation>
</message>
<message>
- <location line="-1192"/>
+ <location line="-1199"/>
<source>Pay &amp;To:</source>
<translation>Pay &amp;To:</translation>
</message>
@@ -3269,12 +3217,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-46"/>
- <source>This is a normal payment.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+39"/>
+ <location line="-7"/>
<source>The Bitcoin address to send the payment to</source>
<translation type="unfinished"></translation>
</message>
@@ -3295,13 +3238,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+7"/>
- <location line="+555"/>
+ <location line="+562"/>
<location line="+533"/>
<source>Remove this entry</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1028"/>
+ <location line="-1035"/>
+ <source>The amount to send in the selected unit</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+7"/>
<source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source>
<translation type="unfinished"></translation>
</message>
@@ -3331,12 +3279,13 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1016"/>
+ <location line="-1023"/>
+ <location line="+3"/>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+54"/>
+ <location line="+58"/>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished"></translation>
</message>
@@ -3352,20 +3301,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<source>Memo:</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location filename="../sendcoinsentry.cpp" line="+39"/>
- <source>Enter a label for this address to add it to your address book</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <location filename="../sendcoinsdialog.cpp" line="+88"/>
- <location line="+5"/>
- <source>Yes</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -3404,18 +3339,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+7"/>
- <location line="+210"/>
+ <location line="+216"/>
<source>Choose previously used address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-200"/>
- <location line="+210"/>
+ <location line="-206"/>
+ <location line="+216"/>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
<message>
- <location line="-200"/>
+ <location line="-206"/>
<source>Paste address from clipboard</source>
<translation>Paste address from clipboard</translation>
</message>
@@ -3426,6 +3361,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+12"/>
+ <location line="+3"/>
<source>Enter the message you want to sign here</source>
<translation>Enter the message you want to sign here</translation>
</message>
@@ -3435,7 +3371,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation>Signature</translation>
</message>
<message>
- <location line="+27"/>
+ <location line="+30"/>
<source>Copy the current signature to the system clipboard</source>
<translation>Copy the current signature to the system clipboard</translation>
</message>
@@ -3456,12 +3392,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+3"/>
- <location line="+143"/>
+ <location line="+157"/>
<source>Clear &amp;All</source>
<translation>Clear &amp;All</translation>
</message>
<message>
- <location line="-84"/>
+ <location line="-98"/>
<source>&amp;Verify Message</source>
<translation>&amp;Verify Message</translation>
</message>
@@ -3476,7 +3412,19 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+37"/>
+ <location line="+29"/>
+ <location line="+3"/>
+ <source>The signed message to verify</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <location line="+3"/>
+ <source>The signature given when the message was signed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+9"/>
<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>
@@ -3491,63 +3439,68 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation>Reset all verify message fields</translation>
</message>
<message>
- <location filename="../signverifymessagedialog.cpp" line="+39"/>
+ <location line="-210"/>
<source>Click &quot;Sign Message&quot; to generate signature</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+81"/>
- <location line="+78"/>
+ <location filename="../signverifymessagedialog.cpp" line="+117"/>
+ <location line="+99"/>
<source>The entered address is invalid.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-78"/>
+ <location line="-99"/>
+ <location line="+7"/>
+ <location line="+93"/>
<location line="+7"/>
- <location line="+71"/>
- <location line="+6"/>
<source>Please check the address and try again.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-77"/>
- <location line="+77"/>
+ <location line="-100"/>
+ <location line="+99"/>
<source>The entered address does not refer to a key.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-69"/>
+ <location line="-91"/>
<source>Wallet unlock was cancelled.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+11"/>
+ <source>No error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Private key for the entered address is not available.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+3"/>
<source>Message signing failed.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+12"/>
<source>Message signed.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+55"/>
+ <location line="+69"/>
<source>The signature could not be decoded.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+0"/>
- <location line="+13"/>
+ <location line="+1"/>
+ <location line="+7"/>
<source>Please check the signature and try again.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+0"/>
+ <location line="-1"/>
<source>The signature did not match the message digest.</source>
<translation type="unfinished"></translation>
</message>
@@ -3557,7 +3510,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
+ <location line="-32"/>
<source>Message verified.</source>
<translation type="unfinished"></translation>
</message>
@@ -3621,7 +3574,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+22"/>
+ <location line="+50"/>
<source>Status</source>
<translation type="unfinished"></translation>
</message>
@@ -3756,7 +3709,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+16"/>
+ <source> (Certificate was not verified)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Merchant</source>
<translation type="unfinished"></translation>
</message>
@@ -3907,7 +3865,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+15"/>
+ <location line="+16"/>
<source>(n/a)</source>
<translation type="unfinished"></translation>
</message>
@@ -4157,7 +4115,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>WalletController</name>
<message>
- <location filename="../walletcontroller.cpp" line="-205"/>
+ <location filename="../walletcontroller.cpp" line="-211"/>
<source>Close wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -4175,7 +4133,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="+29"/>
+ <location filename="../walletframe.cpp" line="+28"/>
<source>No wallet has been loaded.</source>
<translation type="unfinished"></translation>
</message>
@@ -4183,28 +4141,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>WalletModel</name>
<message>
- <location filename="../walletmodel.cpp" line="+219"/>
+ <location filename="../walletmodel.cpp" line="+195"/>
<source>Send Coins</source>
<translation type="unfinished">Send Coins</translation>
</message>
<message>
- <location line="+309"/>
- <location line="+39"/>
+ <location line="+288"/>
+ <location line="+45"/>
+ <location line="+13"/>
<location line="+5"/>
<source>Fee bump error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-44"/>
+ <location line="-63"/>
<source>Increasing transaction fee failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+8"/>
<source>Do you want to increase the fee?</source>
<translation type="unfinished"></translation>
</message>
<message>
+ <location line="+0"/>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+4"/>
<source>Current fee:</source>
<translation type="unfinished"></translation>
@@ -4225,7 +4189,17 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+17"/>
+ <location line="+21"/>
+ <source>Can&apos;t draft transaction.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>PSBT copied</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
<source>Can&apos;t sign transaction.</source>
<translation type="unfinished"></translation>
</message>
@@ -4235,7 +4209,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+30"/>
+ <location line="+20"/>
<source>default wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -4243,7 +4217,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>WalletView</name>
<message>
- <location filename="../walletview.cpp" line="+47"/>
+ <location filename="../walletview.cpp" line="+46"/>
<source>&amp;Export</source>
<translation type="unfinished">&amp;Export</translation>
</message>
@@ -4253,7 +4227,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished">Export the data in the current tab to a file</translation>
</message>
<message>
- <location line="+206"/>
+ <location line="+182"/>
<source>Backup Wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -4306,12 +4280,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+70"/>
+ <location line="+68"/>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation type="unfinished"></translation>
</message>
@@ -4326,7 +4295,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-167"/>
+ <location line="-162"/>
<source>The %s developers</source>
<translation type="unfinished"></translation>
</message>
@@ -4361,7 +4330,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+11"/>
+ <location line="+8"/>
<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>
@@ -4376,7 +4345,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+8"/>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
<translation type="unfinished"></translation>
</message>
@@ -4437,6 +4406,16 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+1"/>
+ <source>Could not find asmap file %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Could not parse asmap file %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Do you want to rebuild the block database now?</source>
<translation>Do you want to rebuild the block database now?</translation>
</message>
@@ -4631,7 +4610,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-156"/>
+ <location line="-151"/>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation type="unfinished"></translation>
</message>
@@ -4641,17 +4620,17 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+22"/>
+ <location line="+19"/>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+35"/>
+ <location line="+31"/>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+27"/>
<source>Error reading from database, shutting down.</source>
<translation type="unfinished"></translation>
</message>
@@ -4787,22 +4766,17 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-179"/>
+ <location line="-174"/>
<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="+53"/>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+2"/>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+4"/>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation type="unfinished"></translation>
</message>
@@ -4817,7 +4791,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+18"/>
+ <location line="+20"/>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation type="unfinished"></translation>
</message>
@@ -4867,7 +4841,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation>Insufficient funds</translation>
</message>
<message>
- <location line="-107"/>
+ <location line="-102"/>
<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 type="unfinished"></translation>
</message>
@@ -4877,7 +4851,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+48"/>
+ <location line="+41"/>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
<translation type="unfinished"></translation>
</message>
@@ -4887,7 +4861,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+37"/>
+ <location line="+39"/>
<source>Loading block index...</source>
<translation>Loading block index...</translation>
</message>
@@ -4897,12 +4871,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation>Loading wallet...</translation>
</message>
<message>
- <location line="-40"/>
+ <location line="-42"/>
<source>Cannot downgrade wallet</source>
<translation>Cannot downgrade wallet</translation>
</message>
<message>
- <location line="+49"/>
+ <location line="+51"/>
<source>Rescanning...</source>
<translation>Rescanning...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_en_AU.ts b/src/qt/locale/bitcoin_en_AU.ts
deleted file mode 100644
index 4a63994b8a..0000000000
--- a/src/qt/locale/bitcoin_en_AU.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-<TS language="en_AU" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Enter address or label to search</source>
- <translation>Enter address or label to search</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- </context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Passphrase Dialogue</translation>
- </message>
- </context>
-<context>
- <name>BanTableModel</name>
- </context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Synchronising with network...</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- </context>
-<context>
- <name>EditAddressDialog</name>
- </context>
-<context>
- <name>FreespaceChecker</name>
- </context>
-<context>
- <name>HelpMessageDialog</name>
- </context>
-<context>
- <name>Intro</name>
- </context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation>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 synchronising with the bitcoin network, as detailed below.</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
- <translation>Minimise 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>Show only a tray icon after minimizing the window.</source>
- <translation>Show only a tray icon after minimising the window.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimise to the tray instead of the taskbar</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>M&amp;inimise on close</translation>
- </message>
- </context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
- <translation>The displayed information may be out of date. Your wallet automatically synchronises with the Bitcoin network after a connection is established, but this process has not completed yet.</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Payment request is not initialised.</translation>
- </message>
- </context>
-<context>
- <name>PeerTableModel</name>
- </context>
-<context>
- <name>QObject</name>
- </context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- </context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Wallet</source>
- <translation>Wallet</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(Smart fee not initialised yet. This usually takes a few blocks...)</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Transaction fee</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsEntry</name>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- </context>
-<context>
- <name>SplashScreen</name>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- </context>
-<context>
- <name>TransactionView</name>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Error initializing block database</source>
- <translation>Error initialising block database</translation>
- </message>
- <message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Error initialising wallet database environment %s!</translation>
- </message>
- <message>
- <source>Failed to rescan the wallet during initialization</source>
- <translation>Failed to rescan the wallet during initialisation</translation>
- </message>
- <message>
- <source>Initialization sanity check failed. %s is shutting down.</source>
- <translation>Initialisation sanity check failed. %s is shutting down.</translation>
- </message>
- </context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_en_GB.ts b/src/qt/locale/bitcoin_en_GB.ts
index 20c6f3bd15..ab674f0c7d 100644
--- a/src/qt/locale/bitcoin_en_GB.ts
+++ b/src/qt/locale/bitcoin_en_GB.ts
@@ -70,6 +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>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;Copy Address</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Repeat new passphrase</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Show passphrase</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Encrypt wallet</translation>
</message>
@@ -172,6 +180,30 @@
<translation>Wallet encrypted</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>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.</translation>
</message>
@@ -294,6 +326,14 @@
<translation>Open &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>Wallet:</translation>
</message>
@@ -334,14 +374,6 @@
<translation>Change the passphrase used for wallet encryption</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Debug window</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Open debugging and diagnostic console</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verify message ...</translation>
</message>
@@ -402,10 +434,6 @@
<translation>Show the list of used receiving addresses and labels</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Open a bitcoin: URI or payment request</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Command-line options</translation>
</message>
@@ -454,6 +482,14 @@
<translation>Up to date</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>
@@ -462,6 +498,10 @@
<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>Open Wallet</translation>
</message>
@@ -522,6 +562,10 @@
<translation>Error: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Warning: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Date: %1
@@ -743,10 +787,58 @@
</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>
@@ -832,10 +924,6 @@
<translation>version</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>About %1</translation>
</message>
@@ -863,6 +951,10 @@
<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>
@@ -883,6 +975,10 @@
<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>
@@ -914,7 +1010,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(of %n GB needed)</numerusform><numerusform>(of %n GB needed)</numerusform></translation>
</message>
- </context>
+ <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>
@@ -962,6 +1062,14 @@
<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>
@@ -969,28 +1077,24 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Open URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Open payment request from URI or file</translation>
+ <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>Select payment request file</source>
- <translation>Select payment request file</translation>
+ <source>Open wallet failed</source>
+ <translation>Open wallet failed</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Select payment request file to open</translation>
+ <source>Open wallet warning</source>
+ <translation>Open wallet warning</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>default wallet</translation>
@@ -1369,16 +1473,16 @@
<translation>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>You are using a BIP70 URL which will be unsupported in the future.</translation>
+ <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>Payment request fetch URL is invalid: %1</source>
- <translation>Payment request fetch URL is invalid: %1</translation>
+ <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>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Cannot process payment request because BIP70 support was not compiled in.</translation>
+ <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>
@@ -1392,66 +1496,6 @@
<source>Payment request file handling</source>
<translation>Payment request file handling</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Payment request file cannot be read! This can be caused by an invalid payment request file.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Payment request rejected.</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Payment request network doesn't match client network.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Payment request expired.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Payment request is not initialised.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Unverified payment requests to custom payment scripts are unsupported.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Invalid payment request.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Requested payment amount of %1 is too small (considered dust).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Refund from %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Error communicating with %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Payment request cannot be parsed!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Bad response from server %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Network request error</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Payment acknowledged</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1602,6 +1646,10 @@
<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>
@@ -1625,10 +1673,6 @@
<translation>&amp;Information</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Debug window</translation>
- </message>
- <message>
<source>General</source>
<translation>General</translation>
</message>
@@ -1749,6 +1793,10 @@
<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>
@@ -1960,6 +2008,18 @@
<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>
@@ -2165,10 +2225,6 @@
<translation>Warning: Fee estimation is currently not possible.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>collapse fee-settings</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>
@@ -2213,6 +2269,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -2281,14 +2341,38 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>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>
@@ -2313,10 +2397,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>The recipient address is not valid. Please recheck.</translation>
</message>
@@ -2341,10 +2449,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Transaction creation failed!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>The transaction was rejected with the following reason: %1</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>
@@ -2396,10 +2500,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Choose previously used address</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>This is a normal payment.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>The Bitcoin address to send the payment to</translation>
</message>
@@ -2420,6 +2520,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -2459,17 +2563,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Enter a label for this address to add it to your address book</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Yes</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2557,6 +2650,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -2589,6 +2690,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -2763,6 +2868,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -3086,6 +3195,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Close 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>
@@ -3116,6 +3229,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -3132,6 +3249,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -3198,10 +3323,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</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>
@@ -3302,6 +3423,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -3358,6 +3487,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Initialisation 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>
@@ -3390,6 +3523,10 @@ 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>
@@ -3498,6 +3635,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>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>
@@ -3556,6 +3697,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -3576,10 +3721,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>This is the transaction fee you may pay when fee estimates are not available.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</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>
diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts
index 78ff6254ce..f4ce75f428 100644
--- a/src/qt/locale/bitcoin_eo.ts
+++ b/src/qt/locale/bitcoin_eo.ts
@@ -294,14 +294,6 @@
<translation>Ŝanĝi la pasfrazon por ĉifri la monujon</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Sen&amp;cimiga fenestro</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Malfermi konzolon de sencimigo kaj diagnozo</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Kontroli mesaĝon...</translation>
</message>
@@ -362,10 +354,6 @@
<translation>Vidigi la liston de uzitaj ricevaj adresoj kaj etikedoj</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Malfermi bitcoin:-URI-on aŭ pagpeton</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Komandliniaj agordaĵoj</translation>
</message>
@@ -451,7 +439,11 @@
<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>
- </context>
+ <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>
<name>CoinControlDialog</name>
<message>
@@ -535,6 +527,14 @@
<translation>Kopii transakcian ID-on</translation>
</message>
<message>
+ <source>Lock unspent</source>
+ <translation>Ŝlosi la neelspezitajn</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Malŝlosi la neelspezitajn</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation>Kopii kvanton</translation>
</message>
@@ -559,10 +559,30 @@
<translation>Kopii restmonon</translation>
</message>
<message>
+ <source>(%1 locked)</source>
+ <translation>(%1 ŝlosita)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>jes</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>ne</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(neniu etikedo)</translation>
</message>
- </context>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>restmono de %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(restmono)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
</context>
@@ -591,7 +611,31 @@
<source>&amp;Address</source>
<translation>&amp;Adreso</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Nova adreso por sendi</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Redakti adreson por ricevi</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Redakti adreson por sendi</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>La adreso enigita "%1" ne estas valida Bitmon-adreso.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Ne eblis malŝlosi monujon.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Fiaskis kreo de nova ŝlosilo.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
@@ -667,22 +711,10 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Malfermi URI-on</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Malfermi pagpeton el URI aŭ dosiero</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Elektu la dosieron de la pagpeto</translation>
- </message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
</context>
@@ -862,6 +894,22 @@
</context>
<context>
<name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Eraro dum pagopeto</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Ne eblas lanĉi la ilon 'klaki-por-pagi'</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>Traktado de URI-oj</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Nevalida pagadreso %1</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -936,6 +984,10 @@
<translation>&amp;Konservi Bildon...</translation>
</message>
<message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;Kopii Bildon</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>La rezultanta URI estas tro longa. Provu malplilongigi la tekston de la etikedo / mesaĝo.</translation>
</message>
@@ -943,7 +995,15 @@
<source>Error encoding URI into QR Code.</source>
<translation>Eraro de kodigo de URI en la QR-kodon.</translation>
</message>
- </context>
+ <message>
+ <source>Save QR Code</source>
+ <translation>Konservi QR-kodon</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>PNG-bildo (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -959,10 +1019,6 @@
<translation>&amp;Informoj</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Sencimiga fenestro</translation>
- </message>
- <message>
<source>General</source>
<translation>Ĝenerala</translation>
</message>
@@ -1342,10 +1398,6 @@
<translation>Elektu la jam uzitan adreson</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Tio estas normala pago.</translation>
- </message>
- <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -1377,15 +1429,8 @@
<source>Memo:</source>
<translation>Memorando:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Tajpu etikedon por tiu ĉi adreso kaj aldonu ĝin al via adresaro</translation>
- </message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
<message>
<source>Do not shut down the computer until this window disappears.</source>
diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts
index 3e38139b45..b681cff011 100644
--- a/src/qt/locale/bitcoin_es.ts
+++ b/src/qt/locale/bitcoin_es.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Clic derecho para editar la dirección o etiqueta</translation>
+ <translation>Haga clic con el botón derecho para editar una dirección o etiqueta</translation>
</message>
<message>
<source>Create a new address</source>
@@ -23,19 +23,19 @@
</message>
<message>
<source>C&amp;lose</source>
- <translation>C&amp;errar</translation>
+ <translation>Cerrar</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>Eliminar la dirección seleccionada de la lista</translation>
+ <translation>Borrar de la lista la dirección seleccionada</translation>
</message>
<message>
<source>Enter address or label to search</source>
- <translation>Introduzca una dirección o etiqueta que buscar</translation>
+ <translation>Introduzca la dirección, ID de transacción o etiqueta a buscar.</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>Exportar los datos en la ficha actual a un archivo</translation>
+ <translation>Exportar a un archivo los datos de esta pestaña</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -43,19 +43,19 @@
</message>
<message>
<source>&amp;Delete</source>
- <translation>&amp;Eliminar</translation>
+ <translation>Eliminar</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Seleccione la dirección a la que enviar monedas</translation>
+ <translation>Escoja la dirección a la que se enviarán monedas</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>Seleccione la dirección de la que recibir monedas</translation>
+ <translation>Escoja la dirección donde quiere recibir monedas</translation>
</message>
<message>
<source>C&amp;hoose</source>
- <translation>E&amp;scoger</translation>
+ <translation>Escoger</translation>
</message>
<message>
<source>Sending addresses</source>
@@ -67,11 +67,15 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>Estas son sus direcciones Bitcoin para enviar pagos. Verifique siempre la cantidad y la dirección de recepción antes de enviar bitcoins.</translation>
+ <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>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>&amp;Copiar Dirección</translation>
+ <translation>Copiar dirección</translation>
</message>
<message>
<source>Copy &amp;Label</source>
@@ -83,19 +87,19 @@
</message>
<message>
<source>Export Address List</source>
- <translation>Exportar lista de direcciones</translation>
+ <translation>Exportar la Lista de Direcciones</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>Archivo separado de coma (*.csv)</translation>
+ <translation>Archivo de columnas separadas por coma (*.csv)</translation>
</message>
<message>
<source>Exporting Failed</source>
- <translation>Falló la exportación</translation>
+ <translation>La exportación falló</translation>
</message>
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Había un error intentando guardar la lista de direcciones en %1. Por favor inténtelo de nuevo.</translation>
+ <translation>Hubo un error al intentar guardar la lista de direcciones a %1. Por favor, inténtelo de nuevo.</translation>
</message>
</context>
<context>
@@ -132,12 +136,16 @@
<translation>Repita la nueva contraseña</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Mostrar contraseña</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Cifrar monedero</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Esta operación necesita su contraseña de monedero para desbloquear el monedero.</translation>
+ <translation>Esta operación requiere su contraseña para desbloquear el monedero.</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -145,7 +153,7 @@
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Esta operación necesita su contraseña para descifrar el monedero.</translation>
+ <translation>Esta operación requiere su contraseña para descifrar el monedero.</translation>
</message>
<message>
<source>Decrypt wallet</source>
@@ -157,11 +165,11 @@
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation>Confirmar cifrado del monedero</translation>
+ <translation>Confirmar el cifrado del monedero</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Advertencia: Si cifra su monedero y pierde su contraseña&lt;b&gt;¡PERDERÁ TODOS SUS BITCOINS!&lt;/b&gt;</translation>
+ <translation>Atención: Si cifra su monedero y pierde la contraseña, perderá ¡&lt;b&gt;TODOS SUS BITCOINS&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -172,55 +180,75 @@
<translation>Monedero cifrado</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>
+ </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>
+ </message>
+ <message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>Recuerda que encriptando tu cartera no garantiza mantener a salvo tus bitcoins en caso de tener viruses en el ordenador.</translation>
+ <translation>Recuerde que cifrar su monedero no garantiza mantener a salvo sus bitcoins en caso de tener virus en el computador.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Monedero para cifrar</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Su monedero va a ser cifrado</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Su monedero está ahora cifrado</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation>IMPORTANTE: Cualquier copia de seguridad anterior que haya hecho en su archivo de monedero debería ser reemplazada con el archivo de monedero cifrado generado recientemente. Por razones de seguridad, las copias de seguridad anteriores del archivo de monedero descifrado serán inútiles en cuanto empiece a utilizar el nuevo monedero cifrado.</translation>
+ <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>
</message>
<message>
<source>Wallet encryption failed</source>
- <translation>Fracasó el cifrado del monedero</translation>
+ <translation>Cifrado del monedero fallido</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Falló el cifrado del monedero debido a un error interno. Su monedero no fue cifrado.</translation>
+ <translation>El cifrado del monedero falló debido a un error interno. Su monedero no fue cifrado.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
- <translation>La contraseña introducida no coincide.</translation>
+ <translation>Las contraseñas dadas no coinciden.</translation>
</message>
<message>
<source>Wallet unlock failed</source>
- <translation>Fracasó el desbloqueo del monedero</translation>
+ <translation>Desbloquear el monedero falló.</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>La contraseña introducida para el cifrado del monedero es incorrecta.</translation>
+ <translation>La contraseña ingresada para el descifrado del monedero es incorrecta.</translation>
</message>
<message>
<source>Wallet decryption failed</source>
- <translation>Fracasó el cifrado del monedero</translation>
+ <translation>El descifrado del monedero falló</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
- <translation>La contraseña del monedero se ha cambiado con éxito.</translation>
+ <translation>La contraseña del monedero ha sido cambiada con éxito.</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
- <translation>Alerta: ¡La clave de bloqueo Caps está activa!</translation>
+ <translation>Advertencia: ¡La tecla Bloq Mayus está activada!</translation>
</message>
</context>
<context>
<name>BanTableModel</name>
<message>
<source>IP/Netmask</source>
- <translation>IP/Máscara</translation>
+ <translation>IP/Máscara de red</translation>
</message>
<message>
<source>Banned Until</source>
- <translation>Bloqueado Hasta</translation>
+ <translation>Prohibido Hasta</translation>
</message>
</context>
<context>
@@ -251,7 +279,7 @@
</message>
<message>
<source>E&amp;xit</source>
- <translation>S&amp;alir</translation>
+ <translation>&amp;Salir</translation>
</message>
<message>
<source>Quit application</source>
@@ -287,7 +315,7 @@
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>&amp;Guardar copia del monedero...</translation>
+ <translation>&amp;Copia de respaldo del monedero...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
@@ -295,15 +323,23 @@
</message>
<message>
<source>Open &amp;URI...</source>
- <translation>Abrir &amp;URI...</translation>
+ <translation>Abrir URI...</translation>
+ </message>
+ <message>
+ <source>Create Wallet...</source>
+ <translation>Crear monedero...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Crear monedero nuevo</translation>
</message>
<message>
<source>Wallet:</source>
- <translation>Monedero</translation>
+ <translation>Monedero:</translation>
</message>
<message>
<source>Click to disable network activity.</source>
- <translation>Pulsar para deshabilitar la actividad de red.</translation>
+ <translation>Haga clic para desactivar la actividad de la red.</translation>
</message>
<message>
<source>Network activity disabled.</source>
@@ -311,11 +347,11 @@
</message>
<message>
<source>Click to enable network activity again.</source>
- <translation>Pulsar para volver a habilitar la actividad de red.</translation>
+ <translation>Haga clic para habilitar nuevamente la actividad de la red.</translation>
</message>
<message>
<source>Syncing Headers (%1%)...</source>
- <translation>Sincronizando cabeceras (%1%)</translation>
+ <translation>Sincronizando cabeceras (%1%) ...</translation>
</message>
<message>
<source>Reindexing blocks on disk...</source>
@@ -323,29 +359,21 @@
</message>
<message>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>Proxy está&lt;b&gt;habilitado&lt;/b&gt;: %1</translation>
+ <translation>El proxy está &lt;b&gt;habilitado&lt;/b&gt;: %1</translation>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation>Enviar bitcoins a una dirección Bitcoin</translation>
+ <translation>Enviar monedas a una dirección Bitcoin</translation>
</message>
<message>
<source>Backup wallet to another location</source>
- <translation>Copia de seguridad del monedero en otra ubicación</translation>
+ <translation>Copia de seguridad del monedero en otra ubicación.</translation>
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
<translation>Cambiar la contraseña utilizada para el cifrado del monedero</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Ventana de depuración</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abrir la consola de depuración y diagnóstico</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verificar mensaje...</translation>
</message>
@@ -395,7 +423,7 @@
</message>
<message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Solicitar pagos (generando códigos QR e identificadores URI "bitcoin:")</translation>
+ <translation>Solicitar pagos (genera código QR y URL's de Bitcoin)</translation>
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
@@ -406,12 +434,8 @@
<translation>Muestra la lista de direcciones de recepción y etiquetas</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abrir un identificador URI "bitcoin:" o una petición de pago</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
- <translation>&amp;Opciones de consola de comandos</translation>
+ <translation>&amp;Opciones de línea de comandos</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
@@ -419,11 +443,11 @@
</message>
<message>
<source>Indexing blocks on disk...</source>
- <translation>Indexando bloques en disco...</translation>
+ <translation>Bloques de indexación en el disco ...</translation>
</message>
<message>
<source>Processing blocks on disk...</source>
- <translation>Procesando bloques en disco...</translation>
+ <translation>Procesamiento de bloques en el disco ...</translation>
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
@@ -458,12 +482,24 @@
<translation>Actualizado</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Ventana de nodo</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Abrir consola de depuración y diagnóstico de nodo</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
- <translation>Direcciones de &amp;envío</translation>
+ <translation>&amp;Direcciones de envío</translation>
</message>
<message>
<source>&amp;Receiving addresses</source>
- <translation>Direcciones de &amp;recepción</translation>
+ <translation>Direcciones de recepción</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Abrir una bitcoin: URI</translation>
</message>
<message>
<source>Open Wallet</source>
@@ -483,7 +519,7 @@
</message>
<message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Mostrar el mensaje de ayuda %1 para obtener una lista de los posibles comandos de linea de comandos de Bitcoin</translation>
+ <translation>Muestre el mensaje de ayuda %1 para obtener una lista con posibles opciones de línea de comandos de Bitcoin</translation>
</message>
<message>
<source>default wallet</source>
@@ -491,7 +527,7 @@
</message>
<message>
<source>No wallets available</source>
- <translation>No hay carteras disponibles</translation>
+ <translation>No hay monederos disponibles.</translation>
</message>
<message>
<source>&amp;Window</source>
@@ -515,7 +551,7 @@
</message>
<message>
<source>Connecting to peers...</source>
- <translation>Conectando a pares...</translation>
+ <translation>Conectando con sus pares ...</translation>
</message>
<message>
<source>Catching up...</source>
@@ -538,13 +574,14 @@
<message>
<source>Amount: %1
</source>
- <translation>Amount: %1
+ <translation>Cantidad: %1
</translation>
</message>
<message>
<source>Wallet: %1
</source>
- <translation>Monedero: %1</translation>
+ <translation>Monedero: %1
+</translation>
</message>
<message>
<source>Type: %1
@@ -582,7 +619,7 @@
</message>
<message>
<source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>Clave privada &lt;b&gt;deshabilitado&lt;/b&gt;</translation>
+ <translation>Llave privada &lt;b&gt;deshabilitada&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
@@ -594,14 +631,14 @@
</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>
+ <translation>Se produjo un error fatal. Bitcoin ya no puede continuar de manera segura y se cerrará</translation>
</message>
</context>
<context>
<name>CoinControlDialog</name>
<message>
<source>Coin Selection</source>
- <translation>Selección de la moneda</translation>
+ <translation>Selección de moneda</translation>
</message>
<message>
<source>Quantity:</source>
@@ -613,7 +650,7 @@
</message>
<message>
<source>Amount:</source>
- <translation>Cuantía:</translation>
+ <translation>Cantidad:</translation>
</message>
<message>
<source>Fee:</source>
@@ -625,7 +662,7 @@
</message>
<message>
<source>After Fee:</source>
- <translation>Después de aplicar la comisión:</translation>
+ <translation>Después de comisión:</translation>
</message>
<message>
<source>Change:</source>
@@ -633,7 +670,7 @@
</message>
<message>
<source>(un)select all</source>
- <translation>(des)marcar todos</translation>
+ <translation>(des)selecciona todos</translation>
</message>
<message>
<source>Tree mode</source>
@@ -669,7 +706,7 @@
</message>
<message>
<source>Copy address</source>
- <translation>Copiar ubicación</translation>
+ <translation>Copiar dirección</translation>
</message>
<message>
<source>Copy label</source>
@@ -681,7 +718,7 @@
</message>
<message>
<source>Copy transaction ID</source>
- <translation>Copiar ID de transacción</translation>
+ <translation>Copiar ID de la transacción</translation>
</message>
<message>
<source>Lock unspent</source>
@@ -701,7 +738,7 @@
</message>
<message>
<source>Copy after fee</source>
- <translation>Copiar después de comisión</translation>
+ <translation>Copiar después de la comisión</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -729,7 +766,7 @@
</message>
<message>
<source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Esta etiqueta se vuelve roja si algún destinatario recibe una cantidad inferior al actual umbral de polvo.</translation>
+ <translation>Esta etiqueta se vuelve roja si algún receptor recibe una cantidad inferior al umbral actual establecido para el polvo.</translation>
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
@@ -750,10 +787,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Creando monedero &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Crear monedero falló</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Advertencia sobre crear monedero</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Crear monedero</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Nombre de monedero</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>Encriptar monedero. El monedero será cifrado con la contraseña que elija.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Cifrar monedero</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>Deshabilita las claves privadas para este monedero. Los monederos con claves privadas deshabilitadas no tendrán claves privadas y no podrán tener ni una semilla HD ni claves privadas importadas. Esto es ideal para monederos de solo lectura.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>Deshabilitar 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>Crear un monedero vacío. Los monederos vacíos no tienen claves privadas ni scripts. Las claves privadas y direcciones pueden importarse después o también establecer una semilla HD.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Crear monedero vacío</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Crear</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -790,7 +875,7 @@
</message>
<message>
<source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>La dirección introducida "%1" no es una dirección Bitcoin válida.</translation>
+ <translation>La dirección ingresada "%1" no es una dirección válida de 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>
@@ -806,7 +891,7 @@
</message>
<message>
<source>New key generation failed.</source>
- <translation>Falló la generación de la nueva clave.</translation>
+ <translation>Nueva generación de claves fallida.</translation>
</message>
</context>
<context>
@@ -821,7 +906,7 @@
</message>
<message>
<source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>El directorio ya existe. Añada %1 si pretende crear un directorio nuevo.</translation>
+ <translation>El directorio ya existe. Añada %1 si pretende crear aquí un directorio nuevo.</translation>
</message>
<message>
<source>Path already exists, and is not a directory.</source>
@@ -839,12 +924,8 @@
<translation>versión</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
- <translation>Acerca de %1</translation>
+ <translation>Alrededor de %1</translation>
</message>
<message>
<source>Command-line options</source>
@@ -859,23 +940,27 @@
</message>
<message>
<source>Welcome to %1.</source>
- <translation>Bienvenido a %1</translation>
+ <translation>Bienvenido a %1.</translation>
</message>
<message>
<source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
- <translation>Al ser la primera vez que se ejecuta el programa, puede elegir dónde %1 almacenará sus datos.</translation>
+ <translation>Como esta es la primera vez que se lanza el programa, puede elegir dónde %1 almacenará sus datos.</translation>
</message>
<message>
<source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation>Cuando haga click en OK, %1 se empezará a descargar la %4 cadena de bloques completa (%2GB) empezando por la transacción más antigua en %3 cuando se publicó %4 originalmente.</translation>
+ <translation>Al hacer clic en OK, %1 se iniciará el proceso de descarga y se procesará la cadena de bloques completa de %4 (%2 GB), iniciando desde la transacción más antigua %3 cuando %4 se ejecutó inicialmente.</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain. It is faster to download the full chain first and prune it later. Disables some advanced features.</source>
+ <translation>Revertir este parámetro requiere volver a descargar todos los bloques. Es más rápido descargar primero todos los bloques y podar después. Deshabilita algunas características avanzadas.</translation>
</message>
<message>
<source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
- <translation>La sincronización inicial demanda muchos recursos y podría revelar problemas de hardware que no se han notado previamente. Cada vez que ejecuta %1, continuará descargando a partir del punto anterior.</translation>
+ <translation>Esta sincronización inicial es muy exigente y puede exponer problemas de hardware con su computadora que anteriormente habían pasado desapercibidos. Cada vez que ejecuta %1, continuará la descarga desde donde la 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>Si ha elegido limitar el almacenamiento de la cadena de bloques ("prunning"), se descargarán y procesarán los datos históricos igualmente, sin embargo, estos se eliminarán después para mantener un bajo uso del disco.</translation>
+ <translation>Si ha elegido limitar el almacenamiento de la cadena de bloques (pruning), los datos históricos todavía se deben descargar y procesar, pero se eliminarán posteriormente para mantener el uso del disco bajo.</translation>
</message>
<message>
<source>Use the default data directory</source>
@@ -883,19 +968,23 @@
</message>
<message>
<source>Use a custom data directory:</source>
- <translation>Utilizar un directorio de datos personalizado:</translation>
+ <translation>Utilice un directorio de datos personalizado:</translation>
</message>
<message>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Descartar los bloques después de la verificación, excepto los %1 GB más recientes (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>Se almacenará cuanto menos %1 GB de datos en este directorio, y crecerá con el transcurso del tiempo.</translation>
+ <translation>Al menos %1 GB de información será almacenada en este directorio, y seguirá creciendo a través del tiempo.</translation>
</message>
<message>
<source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>Se almacenará aproximadamente %1 GB de datos en este directorio.</translation>
+ <translation>Aproximadamente %1 GB de datos se almacenarán en este directorio.</translation>
</message>
<message>
<source>%1 will download and store a copy of the Bitcoin block chain.</source>
@@ -903,11 +992,11 @@
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
- <translation>El monedero se almacenará en este directorio.</translation>
+ <translation>El monedero también se almacenará en este directorio.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Error: no ha podido crearse el directorio de datos especificado "%1".</translation>
+ <translation>Error: Directorio de datos especificado "%1" no puede ser creado.</translation>
</message>
<message>
<source>Error</source>
@@ -915,13 +1004,17 @@
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
- <translation><numerusform>%n GB de espacio libre</numerusform><numerusform>%n GB de espacio disponible</numerusform></translation>
+ <translation><numerusform>%n GB de espacio libre disponible</numerusform><numerusform>%n GB de espacio libre disponible</numerusform></translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
- <translation><numerusform>(de %n GB necesitados)</numerusform><numerusform>(de %n GB requeridos)</numerusform></translation>
+ <translation><numerusform>(de %n GB requerido)</numerusform><numerusform>(de %n GB requeridos)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB necesarios para la cadena completa)</numerusform><numerusform>(%n GB necesarios para la cadena completa)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -930,15 +1023,15 @@
</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>Las transacciones recientes aún no pueden ser visibles, y por lo tanto el saldo de su monedero podría ser incorrecto. Esta información será correcta cuando su monedero haya terminado de sincronizarse con la red de bitcoin, como se detalla abajo.</translation>
+ <translation>Es posible que las transacciones recientes aún no estén visibles y, por lo tanto, el saldo de su monedero podría ser incorrecto. Esta información será correcta una vez que su monedero haya terminado de sincronizarse con la red bitcoin, como se detalla a continuación.</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation>La red no aceptará el intentar gastar bitcoins que están afectados por transacciones aún no mostradas.</translation>
+ <translation>La red no aceptará intentar gastar bitcoins que se vean afectados por transacciones aún no mostradas.</translation>
</message>
<message>
<source>Number of blocks left</source>
- <translation>Número de bloques restantes</translation>
+ <translation>Cantidad de bloques restantes.</translation>
</message>
<message>
<source>Unknown...</source>
@@ -946,15 +1039,15 @@
</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>
- <translation>Avance del progreso por hora</translation>
+ <translation>Aumento de progreso por hora.</translation>
</message>
<message>
<source>calculating...</source>
@@ -962,42 +1055,46 @@
</message>
<message>
<source>Estimated time left until synced</source>
- <translation>Tiempo estimado restante hasta la sincronización</translation>
+ <translation>Tiempo estimado restante hasta la sincronización.</translation>
</message>
<message>
<source>Hide</source>
<translation>Ocultar</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 está actualmente sincronizándose. Descargará cabeceras y bloques de nodos semejantes y los validará hasta alcanzar la cabeza de la cadena de bloques.</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
- <translation>Desconocido. Sincronizando Cabeceras (%1, %2%)...</translation>
+ <translation>Desconocido. Sincronizando cabeceras (%1, %2%)...</translation>
</message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Abrir URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Abrir solicitud de pago a partir de un identificador URI o de un archivo</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Abrir URI de bitcoin</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Seleccionar archivo de solicitud de pago</translation>
+ <source>Open wallet failed</source>
+ <translation>La apertura del monedero falló</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Seleccionar el archivo de solicitud de pago para abrir</translation>
+ <source>Open wallet warning</source>
+ <translation>Advertencia sobre apertura de monedero</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>Monedero predeterminado</translation>
@@ -1018,40 +1115,36 @@
<translation>&amp;Principal</translation>
</message>
<message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation>Iniciar automaticamente %1 al encender el sistema.</translation>
- </message>
- <message>
<source>&amp;Start %1 on system login</source>
- <translation>&amp;Iniciar %1 al iniciar el sistema</translation>
+ <translation>&amp; Comience %1 en el inicio de sesión del sistema</translation>
</message>
<message>
<source>Size of &amp;database cache</source>
- <translation>Tamaño del cache de la &amp;base de datos</translation>
+ <translation>Tamaño de la memoria caché de la base de datos</translation>
</message>
<message>
<source>Number of script &amp;verification threads</source>
- <translation>Número de hilos de &amp;verificación de scripts</translation>
+ <translation>Cantidad de secuencias de comandos y verificación</translation>
</message>
<message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Dirección IP del proxy (p. ej. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ <translation>Dirección IP del proxy (ej. 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>Muestra si el proxy SOCKS5 predeterminado se utiliza para conectarse a pares a través de este tipo de red.</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>Usar proxy SOCKS&amp;5 para alcanzar nodos via servicios ocultos Tor:</translation>
+ <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 ícono de la bandeja de sistema.</translation>
+ <translation>Ocultar el icono de la bandeja del sistema.</translation>
</message>
<message>
<source>&amp;Hide tray icon</source>
- <translation>&amp;Ocultar ícono de la barra de tareas</translation>
+ <translation>Ocultar icono de 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>
@@ -1059,19 +1152,19 @@
</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>Identificadores URL de terceros (por ejemplo, un explorador de bloques) que aparecen en la pestaña de transacciones como elementos del menú contextual. El %s en la URL es reemplazado por el valor hash de la transacción. Se pueden separar URL múltiples por una barra vertical |.</translation>
+ <translation>URL de terceros (por ejemplo, un explorador de bloques) que aparecen en la pestaña de transacciones como elementos del menú contextual. %s en la URL se reemplaza por hash de transacción. Varias URL están separadas por una barra vertical |.</translation>
</message>
<message>
<source>Open the %1 configuration file from the working directory.</source>
- <translation>Abre el fichero de configuración %1 en el directorio de trabajo.</translation>
+ <translation>Abrir el archivo de configuración %1 en el directorio de trabajo.</translation>
</message>
<message>
<source>Open Configuration File</source>
- <translation>Abrir fichero de configuración</translation>
+ <translation>Abrir archivo de configuración</translation>
</message>
<message>
<source>Reset all client options to default.</source>
- <translation>Restablecer todas las opciones predeterminadas del cliente.</translation>
+ <translation>Restablecer todas las opciones del cliente a las predeterminadas.</translation>
</message>
<message>
<source>&amp;Reset Options</source>
@@ -1083,7 +1176,7 @@
</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>Desactiva algunas características avanzadas, pero todos los bloques se validarán por completo. Revertir esta configuración requiere volver a descargar todo el blockchain. El uso real del disco puede ser algo mayor.</translation>
+ <translation>Desactiva algunas características avanzadas, pero todos los bloques se validarán por completo. Revertir esta configuración requiere volver a descargar toda la blockchain. El uso real del disco puede ser algo mayor.</translation>
</message>
<message>
<source>Prune &amp;block storage to</source>
@@ -1095,7 +1188,7 @@
</message>
<message>
<source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation>Revertir estas configuraciones requiere re-descargar el blockchain entero.</translation>
+ <translation>Revertir estas configuraciones requiere descargar de nuevo la blockchain entera.</translation>
</message>
<message>
<source>MiB</source>
@@ -1103,11 +1196,11 @@
</message>
<message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = automático, &lt;0 = dejar libres ese número de núcleos)</translation>
+ <translation>(0 = auto, &lt;0 = deja estos núcleos libres)</translation>
</message>
<message>
<source>W&amp;allet</source>
- <translation>&amp;Monedero</translation>
+ <translation>Monedero</translation>
</message>
<message>
<source>Expert</source>
@@ -1115,15 +1208,15 @@
</message>
<message>
<source>Enable coin &amp;control features</source>
- <translation>Habilitar funcionalidad de &amp;Coin Control</translation>
+ <translation>Habilitar características de &amp;Control de Moneda.</translation>
</message>
<message>
<source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
- <translation>Si desactiva el gasto del cambio no confirmado, no se podrá usar el cambio de una transacción hasta que se alcance al menos una confirmación. Esto afecta también a cómo se calcula su saldo.</translation>
+ <translation>Si deshabilita el gasto de un cambio no confirmado, el cambio de una transacción no se puede usar hasta que esa transacción tenga al menos una confirmación. Esto también afecta a cómo se calcula su saldo.</translation>
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
- <translation>&amp;Gastar cambio no confirmado</translation>
+ <translation>&amp; Gastar 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>
@@ -1131,11 +1224,11 @@
</message>
<message>
<source>Map port using &amp;UPnP</source>
- <translation>Mapear el puerto mediante &amp;UPnP</translation>
+ <translation>Mapear el puerto usando &amp;UPnP</translation>
</message>
<message>
<source>Accept connections from outside.</source>
- <translation>Aceptar conexiones desde el exterior.</translation>
+ <translation>Acepta conexiones desde afuera.</translation>
</message>
<message>
<source>Allow incomin&amp;g connections</source>
@@ -1143,11 +1236,11 @@
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Conectarse a la red Bitcoin a través de un proxy SOCKS5.</translation>
+ <translation>Conéctese a la red de Bitcoin a través de un proxy SOCKS5.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Conectarse a través de proxy SOCKS5 (proxy predeterminado):</translation>
+ <translation>Conectar a través del proxy SOCKS5 (proxy predeterminado):</translation>
</message>
<message>
<source>Proxy &amp;IP:</source>
@@ -1163,7 +1256,7 @@
</message>
<message>
<source>Used for reaching peers via:</source>
- <translation>Usado para alcanzar pares via:</translation>
+ <translation>Utilizado para llegar a los compañeros a través de:</translation>
</message>
<message>
<source>IPv4</source>
@@ -1179,7 +1272,7 @@
</message>
<message>
<source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Conectar a la red Bitcoin mediante un proxy SOCKS5 por separado para los servicios ocultos de Tor.</translation>
+ <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>
@@ -1207,19 +1300,19 @@
</message>
<message>
<source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation>El idioma de la interfaz de usuario puede establecerse aquí. Esta configuración tendrá efecto tras reiniciar %1.</translation>
+ <translation>El idioma de la interfaz de usuario puede establecerse aquí. Esta configuración tendrá efecto después de reiniciar %1.</translation>
</message>
<message>
<source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Unidad en la cual mostrar las cantidades:</translation>
+ <translation>Mostrar las cantidades en la &amp;unidad:</translation>
</message>
<message>
<source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Elegir la subdivisión predeterminada para mostrar cantidades en la interfaz y cuando se envían bitcoins.</translation>
+ <translation>Elegir la subdivisión predeterminada para mostrar cantidades en la interfaz y cuando se envían monedas.</translation>
</message>
<message>
<source>Whether to show coin control features or not.</source>
- <translation>Mostrar o no funcionalidad de Coin Control</translation>
+ <translation>Mostrar o no características de control de moneda</translation>
</message>
<message>
<source>&amp;Third party transaction URLs</source>
@@ -1243,7 +1336,7 @@
</message>
<message>
<source>none</source>
- <translation>ninguna</translation>
+ <translation>ninguno</translation>
</message>
<message>
<source>Confirm options reset</source>
@@ -1255,7 +1348,7 @@
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
- <translation>El cliente se cerrará. ¿Desea continuar?</translation>
+ <translation>El cliente se cerrará. ¿Quiere proceder?</translation>
</message>
<message>
<source>Configuration options</source>
@@ -1263,7 +1356,7 @@
</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>El fichero de configuración se utiliza para especificar opciones de usuario avanzadas que reemplazar las configuraciones de la interfaz gráfica de usuario. Adicionalmente, cualquier opción introducida en la línea de comandos reemplazará a este fichero de configuración.</translation>
+ <translation>El archivo de configuración se utiliza para especificar opciones de usuario avanzadas que anulan la configuración de la GUI. Además, cualquier opción de línea de comandos anulará este archivo de configuración.</translation>
</message>
<message>
<source>Error</source>
@@ -1271,11 +1364,11 @@
</message>
<message>
<source>The configuration file could not be opened.</source>
- <translation>No se pudo abrir el fichero de configuración.</translation>
+ <translation>El archivo de configuración no se pudo abrir.</translation>
</message>
<message>
<source>This change would require a client restart.</source>
- <translation>Este cambio exige el reinicio del cliente.</translation>
+ <translation>Este cambio requiere reiniciar el cliente.</translation>
</message>
<message>
<source>The supplied proxy address is invalid.</source>
@@ -1286,7 +1379,7 @@
<name>OverviewPage</name>
<message>
<source>Form</source>
- <translation>Formulario</translation>
+ <translation>Desde</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>
@@ -1294,7 +1387,7 @@
</message>
<message>
<source>Watch-only:</source>
- <translation>Solo observación:</translation>
+ <translation>Ver-solo:</translation>
</message>
<message>
<source>Available:</source>
@@ -1302,7 +1395,7 @@
</message>
<message>
<source>Your current spendable balance</source>
- <translation>Su saldo disponible actual</translation>
+ <translation>Su balance actual gastable</translation>
</message>
<message>
<source>Pending:</source>
@@ -1310,19 +1403,19 @@
</message>
<message>
<source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Total de transacciones pendientes de confirmar y que aún no contribuye al saldo disponible</translation>
+ <translation>Total de transacciones que deben ser confirmadas y que no cuentan aun con el balance gastable necesario.</translation>
</message>
<message>
<source>Immature:</source>
- <translation>No madurado:</translation>
+ <translation>No disponible:</translation>
</message>
<message>
<source>Mined balance that has not yet matured</source>
- <translation>Saldo recién minado que aún no ha madurado.</translation>
+ <translation>Saldo recién minado que aún no está disponible.</translation>
</message>
<message>
<source>Balances</source>
- <translation>Saldos</translation>
+ <translation>Balances</translation>
</message>
<message>
<source>Total:</source>
@@ -1330,15 +1423,15 @@
</message>
<message>
<source>Your current total balance</source>
- <translation>Su saldo actual total</translation>
+ <translation>Su balance actual total</translation>
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>Su saldo actual en direcciones watch-only (solo-observación)</translation>
+ <translation>Su saldo actual en direcciones solo-ver</translation>
</message>
<message>
<source>Spendable:</source>
- <translation>Gastable:</translation>
+ <translation>Utilizable:</translation>
</message>
<message>
<source>Recent transactions</source>
@@ -1346,26 +1439,26 @@
</message>
<message>
<source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Transacciones sin confirmar en direcciones watch-only (solo-observación)</translation>
+ <translation>Transacciones no confirmadas para direcciones ver-solo</translation>
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Saldo minado en direcciones watch-only que aún no ha madurado</translation>
+ <translation>Balance minado en direcciones ver-solo que aún no ha madurado</translation>
</message>
<message>
<source>Current total balance in watch-only addresses</source>
- <translation>Saldo total en las direcciones watch-only (solo-observación)</translation>
+ <translation>Saldo total actual en direcciones de solo-ver</translation>
</message>
</context>
<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
- <translation>Fallo en la solicitud de pago</translation>
+ <translation>Error de solicitud de pago</translation>
</message>
<message>
<source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>No se puede iniciar bitcoin: encargado click-para-pagar</translation>
+ <translation>No se puede iniciar Bitcoin: controlador de clic para pagar</translation>
</message>
<message>
<source>URI handling</source>
@@ -1376,16 +1469,16 @@
<translation>'bitcoin: //' no es un URI válido. Use 'bitcoin:' en su lugar.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Está utilizando una URL BIP70 la cual dejará de tener soporte en el futuro.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>No se puede procesar la solicitud de pago debido a que no se ha incluido el soporte de BIP70.</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>La búsqueda de solicitud de pago URL es válida: %1</translation>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Debido a fallos de seguridad conocidos en BIP70 se recomienda encarecidamente que se ignore cualquier instrucción sobre el intercambio de monederos.</translation>
</message>
<message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>No se puede procesar la petición de pago debido a que no se ha incluido el soporte de BIP70.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Si está recibiendo este error debería solicitar al comerciante que le proporcione una URI compatible con BIP21</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1393,86 +1486,26 @@
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>URI no puede ser analizado! Esto puede ser causado por una dirección Bitcoin inválida o parametros URI mal formados.</translation>
+ <translation>¡No se puede interpretar la URI! Esto puede deberse a una dirección Bitcoin inválida o a parámetros de URI mal formados.</translation>
</message>
<message>
<source>Payment request file handling</source>
- <translation>Manejo del archivo de solicitud de pago</translation>
- </message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>¡El archivo de solicitud de pago no puede ser leído! Esto puede ser causado por un archivo de solicitud de pago inválido.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Solicitud de pago rechazada</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>La red de solicitud de pago no coincide con la red cliente.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Solicitud de pago caducada.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>La solicitud de pago no se ha iniciado.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Solicitudes de pago sin verificar a scripts de pago habitual no se soportan.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Solicitud de pago inválida.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Cantidad de pago solicitada de %1 es demasiado pequeña (considerado polvo).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Reembolsar desde %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Solicitud de pago de %1 es demasiado grande (%2 bytes, permitidos %3 bytes).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Fallo al comunicar con %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>¡La solicitud de pago no puede ser analizada!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Mala respuesta desde el servidor %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Fallo de solicitud de red</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Pago declarado</translation>
+ <translation>Manejo de archivos de solicitud de pago</translation>
</message>
</context>
<context>
<name>PeerTableModel</name>
<message>
<source>User Agent</source>
- <translation>User Agent</translation>
+ <translation>Agente de usuario</translation>
</message>
<message>
<source>Node/Service</source>
- <translation>Nodo/Servicio</translation>
+ <translation>Nodo / Servicio</translation>
</message>
<message>
<source>NodeId</source>
- <translation>ID de nodo</translation>
+ <translation>NodeId</translation>
</message>
<message>
<source>Ping</source>
@@ -1495,7 +1528,7 @@
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Introducir una dirección Bitcoin (p. ej. %1)</translation>
+ <translation>Ingrese una dirección de Bitcoin (por ejemplo, %1)</translation>
</message>
<message>
<source>%1 d</source>
@@ -1527,23 +1560,23 @@
</message>
<message numerus="yes">
<source>%n second(s)</source>
- <translation><numerusform>%n segundo</numerusform><numerusform>%n segundos</numerusform></translation>
+ <translation><numerusform>%n segundos</numerusform><numerusform>%n segundos</numerusform></translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
- <translation><numerusform>%n minuto</numerusform><numerusform>%n minutos</numerusform></translation>
+ <translation><numerusform>%n minutos</numerusform><numerusform>%n minutos</numerusform></translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
- <translation><numerusform>%n hora</numerusform><numerusform>%n horas</numerusform></translation>
+ <translation><numerusform>%n horas</numerusform><numerusform>%n horas</numerusform></translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
- <translation><numerusform>%n dia</numerusform><numerusform>%n dias</numerusform></translation>
+ <translation><numerusform>%n días </numerusform><numerusform>%n días </numerusform></translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
- <translation><numerusform>%n semana</numerusform><numerusform>%n semanas</numerusform></translation>
+ <translation><numerusform>%n semanas</numerusform><numerusform>%n semanas</numerusform></translation>
</message>
<message>
<source>%1 and %2</source>
@@ -1551,7 +1584,7 @@
</message>
<message numerus="yes">
<source>%n year(s)</source>
- <translation><numerusform>%n año</numerusform><numerusform>%n años</numerusform></translation>
+ <translation><numerusform>%n años</numerusform><numerusform>%n años</numerusform></translation>
</message>
<message>
<source>%1 B</source>
@@ -1571,7 +1604,7 @@
</message>
<message>
<source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Error: El directorio de datos «%1» especificado no existe.</translation>
+ <translation>Error: El directorio de datos especificado "%1" no existe.</translation>
</message>
<message>
<source>Error: Cannot parse configuration file: %1.</source>
@@ -1583,7 +1616,7 @@
</message>
<message>
<source>%1 didn't yet exit safely...</source>
- <translation>%1 no se ha cerrado de forma segura todavía...</translation>
+ <translation>%1 aún no salió de forma segura ...</translation>
</message>
<message>
<source>unknown</source>
@@ -1594,19 +1627,19 @@
<name>QRImageWidget</name>
<message>
<source>&amp;Save Image...</source>
- <translation>&amp;Guardar imagen...</translation>
+ <translation>Guardar Imagen...</translation>
</message>
<message>
<source>&amp;Copy Image</source>
- <translation>&amp;Copiar imagen</translation>
+ <translation>Copiar imagen</translation>
</message>
<message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation>URI resultante demasiado grande, trate de reducir el texto de etiqueta / mensaje.</translation>
+ <translation>URI resultante demasiado larga. Intente reducir el texto de la etiqueta / mensaje.</translation>
</message>
<message>
<source>Error encoding URI into QR Code.</source>
- <translation>Fallo al codificar URI en código QR.</translation>
+ <translation>Error al codificar la URI en el código QR.</translation>
</message>
<message>
<source>QR code support not available.</source>
@@ -1633,11 +1666,7 @@
</message>
<message>
<source>&amp;Information</source>
- <translation>&amp;Información</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Ventana de depuración</translation>
+ <translation>Información</translation>
</message>
<message>
<source>General</source>
@@ -1645,7 +1674,7 @@
</message>
<message>
<source>Using BerkeleyDB version</source>
- <translation>Utilizando la versión de BerkeleyDB</translation>
+ <translation>Usando la versión BerkeleyDB</translation>
</message>
<message>
<source>Datadir</source>
@@ -1689,7 +1718,7 @@
</message>
<message>
<source>Memory Pool</source>
- <translation>Piscina de Memoria</translation>
+ <translation>Grupo de memoria</translation>
</message>
<message>
<source>Current number of transactions</source>
@@ -1709,7 +1738,7 @@
</message>
<message>
<source>&amp;Reset</source>
- <translation>&amp;Reiniciar</translation>
+ <translation>Reiniciar</translation>
</message>
<message>
<source>Received</source>
@@ -1721,19 +1750,19 @@
</message>
<message>
<source>&amp;Peers</source>
- <translation>&amp;Pares</translation>
+ <translation>Pares</translation>
</message>
<message>
<source>Banned peers</source>
- <translation>Pares bloqueados</translation>
+ <translation>Pares prohibidos</translation>
</message>
<message>
<source>Select a peer to view detailed information.</source>
- <translation>Seleccionar un par para ver su información detallada.</translation>
+ <translation>Seleccione un par para ver información detallada.</translation>
</message>
<message>
<source>Whitelisted</source>
- <translation>En la lista blanca</translation>
+ <translation>Incluido en la lista blanca</translation>
</message>
<message>
<source>Direction</source>
@@ -1745,19 +1774,23 @@
</message>
<message>
<source>Starting Block</source>
- <translation>Importando bloques...</translation>
+ <translation>Bloque de inicio</translation>
</message>
<message>
<source>Synced Headers</source>
- <translation>Cabeceras Sincronizadas</translation>
+ <translation>Encabezados sincronizados</translation>
</message>
<message>
<source>Synced Blocks</source>
- <translation>Bloques Sincronizados</translation>
+ <translation>Bloques sincronizados</translation>
</message>
<message>
<source>User Agent</source>
- <translation>User Agent</translation>
+ <translation>Agente de usuario</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation>Ventana de nodo</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>
@@ -1769,7 +1802,7 @@
</message>
<message>
<source>Increase font size</source>
- <translation>Aumentar tamaño de letra</translation>
+ <translation>Aumentar el tamaño de la fuente</translation>
</message>
<message>
<source>Services</source>
@@ -1777,11 +1810,11 @@
</message>
<message>
<source>Ban Score</source>
- <translation>Puntuación de bloqueo</translation>
+ <translation>Puntuación Ban</translation>
</message>
<message>
<source>Connection Time</source>
- <translation>Duración de la conexión</translation>
+ <translation>Tiempo de conexión</translation>
</message>
<message>
<source>Last Send</source>
@@ -1793,15 +1826,15 @@
</message>
<message>
<source>Ping Time</source>
- <translation>Tiempo de Ping</translation>
+ <translation>Tiempo Ping</translation>
</message>
<message>
<source>The duration of a currently outstanding ping.</source>
- <translation>La duración de un ping actualmente en proceso.</translation>
+ <translation>La duración de un ping actualmente pendiente.</translation>
</message>
<message>
<source>Ping Wait</source>
- <translation>Espera de Ping</translation>
+ <translation>Ping en espera</translation>
</message>
<message>
<source>Min Ping</source>
@@ -1833,11 +1866,11 @@
</message>
<message>
<source>In:</source>
- <translation>Entrante:</translation>
+ <translation>Dentro:</translation>
</message>
<message>
<source>Out:</source>
- <translation>Saliente:</translation>
+ <translation>Fuera:</translation>
</message>
<message>
<source>Debug log file</source>
@@ -1849,51 +1882,51 @@
</message>
<message>
<source>1 &amp;hour</source>
- <translation>1 &amp;hora</translation>
+ <translation>1 hora</translation>
</message>
<message>
<source>1 &amp;day</source>
- <translation>1 &amp;día</translation>
+ <translation>1 día</translation>
</message>
<message>
<source>1 &amp;week</source>
- <translation>1 &amp;semana</translation>
+ <translation>1 semana</translation>
</message>
<message>
<source>1 &amp;year</source>
- <translation>1 &amp;año</translation>
+ <translation>1 año</translation>
</message>
<message>
<source>&amp;Disconnect</source>
- <translation>&amp;Desconectar</translation>
+ <translation>Desconectar</translation>
</message>
<message>
<source>Ban for</source>
- <translation>Prohibir para</translation>
+ <translation>Prohibición de</translation>
</message>
<message>
<source>&amp;Unban</source>
- <translation>&amp;Unban</translation>
+ <translation>&amp;Desbloquear</translation>
</message>
<message>
<source>Welcome to the %1 RPC console.</source>
- <translation>Bienvenido a la consola RPC %1.</translation>
+ <translation>Bienvenido a la consola %1 RPC.</translation>
</message>
<message>
<source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
- <translation>Utilice las teclas de navegación para revisar el historial, y %1 para limpiar la pantalla.</translation>
+ <translation>Use las flechas hacia arriba y hacia abajo para navegar por el historial, y %1 para borrar la pantalla.</translation>
</message>
<message>
<source>Type %1 for an overview of available commands.</source>
- <translation>Presione %1 para una vista previa de los comandos disponibles.</translation>
+ <translation>Escriba %1 para obtener una descripción general de los comandos disponibles.</translation>
</message>
<message>
<source>For more information on using this console type %1.</source>
- <translation>Para mas información sobre el uso de este tipo de consola %1</translation>
+ <translation>Para obtener más información sobre el uso de esta consola, escriba %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>ADVERTENCIA: Los estafadores están solicitando a los usuarios introducir ordenes aquí, lo que ocasiona que estos roben los contenidos del monedero. No utilice esta consola sin comprender completamente las implicancias de cada orden.</translation>
+ <translation>ADVERTENCIA: los estafadores han estado activos pidiendo a los usuarios que escriban comandos aquí, robando el contenido de su monedero. No use esta consola sin entender completamente las ramificaciones de un comando.</translation>
</message>
<message>
<source>Network activity disabled</source>
@@ -1909,15 +1942,15 @@
</message>
<message>
<source>(node id: %1)</source>
- <translation>(nodo: %1)</translation>
+ <translation>(ID de nodo: %1)</translation>
</message>
<message>
<source>via %1</source>
- <translation>via %1</translation>
+ <translation>a través de %1</translation>
</message>
<message>
<source>never</source>
- <translation>nunca</translation>
+ <translation>nunca </translation>
</message>
<message>
<source>Inbound</source>
@@ -1925,7 +1958,7 @@
</message>
<message>
<source>Outbound</source>
- <translation>Saliente</translation>
+ <translation>Salida</translation>
</message>
<message>
<source>Yes</source>
@@ -1956,31 +1989,35 @@
</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 mensaje opcional para adjuntar a la solicitud de pago, que se muestra cuando se abre la solicitud. Nota: El mensaje no se enviará con el pago por la red Bitcoin.</translation>
+ <translation>Mensaje opcional para agregar a la solicitud de pago, el cual será mostrado cuando la solicitud esté abierta. Nota: El mensaje no se enviará con el pago a través de la red de Bitcoin.</translation>
</message>
<message>
<source>An optional label to associate with the new receiving address.</source>
- <translation>Etiqueta opcional para asociar con la nueva dirección de recepción.</translation>
+ <translation>Una etiqueta opcional para asociar con la nueva dirección de recepción</translation>
</message>
<message>
<source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Utilice este formulario para solicitar pagos. Todos los campos son &lt;b&gt;opcionales&lt;/b&gt;.</translation>
+ <translation>Use este formulario para la solicitud de pagos. Todos los campos son &lt;b&gt;opcionales&lt;/b&gt;</translation>
</message>
<message>
<source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation>Para solicitar una cantidad opcional. Deje este vacío o cero para no solicitar una cantidad específica.</translation>
+ <translation>Monto opcional a solicitar. Dejarlo vacío o en cero para no solicitar un monto específico.</translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation>Crear nueva dirección para recepción</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
- <translation>Vaciar todos los campos del formulario.</translation>
+ <translation>Limpiar todos los campos del formulario</translation>
</message>
<message>
<source>Clear</source>
- <translation>Vaciar</translation>
+ <translation>Limpiar</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>Las direcciones segwit nativas (también conocidas como Bech32 o BIP-173) reducen las comisiones de transacción más adelante y ofrecen una mejor protección contra errores tipográficos, pero las billeteras antiguas no las admiten. Cuando no está marcada, se creará una dirección compatible con billeteras más antiguas.</translation>
+ <translation>Las direcciones segwit nativas (también conocidas como Bech32 o BIP-173) reducen las comisiones de transacción más adelante y ofrecen una mejor protección contra errores tipográficos, pero los monederos antiguos no las admiten. Cuando no está marcada, se creará una dirección compatible con monederos más antiguos.</translation>
</message>
<message>
<source>Generate native segwit (Bech32) address</source>
@@ -1988,7 +2025,7 @@
</message>
<message>
<source>Requested payments history</source>
- <translation>Historial de pagos solicitados</translation>
+ <translation>Historial de pagos solicitado</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -2000,7 +2037,7 @@
</message>
<message>
<source>Remove the selected entries from the list</source>
- <translation>Borrar las entradas seleccionadas de la lista</translation>
+ <translation>Eliminar de la lista las direcciones actualmente seleccionadas.</translation>
</message>
<message>
<source>Remove</source>
@@ -2016,7 +2053,7 @@
</message>
<message>
<source>Copy message</source>
- <translation>Copiar imagen</translation>
+ <translation>Copiar mensaje</translation>
</message>
<message>
<source>Copy amount</source>
@@ -2047,7 +2084,7 @@
</message>
<message>
<source>Payment information</source>
- <translation>Información de pago</translation>
+ <translation>Información del pago</translation>
</message>
<message>
<source>URI</source>
@@ -2094,11 +2131,11 @@
</message>
<message>
<source>(no message)</source>
- <translation>(no hay mensaje)</translation>
+ <translation>(sin mensaje)</translation>
</message>
<message>
<source>(no amount requested)</source>
- <translation>(no hay solicitud de cantidad)</translation>
+ <translation>(no existe monto solicitado)</translation>
</message>
<message>
<source>Requested</source>
@@ -2109,11 +2146,11 @@
<name>SendCoinsDialog</name>
<message>
<source>Send Coins</source>
- <translation>Enviar bitcoins</translation>
+ <translation>Enviar monedas</translation>
</message>
<message>
<source>Coin Control Features</source>
- <translation>Características de Coin Control</translation>
+ <translation>Características de control de la moneda</translation>
</message>
<message>
<source>Inputs...</source>
@@ -2121,11 +2158,11 @@
</message>
<message>
<source>automatically selected</source>
- <translation>seleccionado automáticamente</translation>
+ <translation>Seleccionado automaticamente</translation>
</message>
<message>
<source>Insufficient funds!</source>
- <translation>Fondos insuficientes!</translation>
+ <translation>¡Fondos insuficientes!</translation>
</message>
<message>
<source>Quantity:</source>
@@ -2145,7 +2182,7 @@
</message>
<message>
<source>After Fee:</source>
- <translation>Después de comisión:</translation>
+ <translation>Después de la comisión:</translation>
</message>
<message>
<source>Change:</source>
@@ -2153,7 +2190,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>Si se marca esta opción pero la dirección de cambio está vacía o es inválida, el cambio se enviará a una nueva dirección recién generada.</translation>
+ <translation>Al activarse, si la dirección de cambio está vacía o es inválida, las monedas serán enviadas a una nueva dirección generada.</translation>
</message>
<message>
<source>Custom change address</source>
@@ -2161,25 +2198,21 @@
</message>
<message>
<source>Transaction Fee:</source>
- <translation>Comisión de Transacción:</translation>
+ <translation>Comisión por transacción: </translation>
</message>
<message>
<source>Choose...</source>
- <translation>Elija...</translation>
+ <translation>Seleccione</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>Si utilizas la comisión por defecto, la transacción puede tardar varias horas o incluso días (o nunca) en confirmarse. Considera elegir la comisión de forma manual o espera hasta que se haya validado completamente la cadena.</translation>
+ <translation>Si utiliza la comisión por defecto, la transacción puede tardar varias horas o incluso días (o nunca) en confirmar. Considere elegir la comisión de forma manual o espere hasta que se haya validado completamente la cadena.</translation>
</message>
<message>
<source>Warning: Fee estimation is currently not possible.</source>
<translation>Advertencia: En este momento no se puede estimar la comisión.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>Colapsar ajustes de comisión.</translation>
- </message>
- <message>
<source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
Note: Since the fee is calculated on a per-byte basis, a fee 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>
@@ -2197,11 +2230,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Recommended:</source>
- <translation>Recomendada:</translation>
+ <translation>Recomendado:</translation>
</message>
<message>
<source>Custom:</source>
- <translation>Personalizada:</translation>
+ <translation>Personalizado:</translation>
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
@@ -2217,7 +2250,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Clear all fields of the form.</source>
- <translation>Vaciar todos los campos del formulario</translation>
+ <translation>Limpiar todos los campos del formulario</translation>
</message>
<message>
<source>Dust:</source>
@@ -2225,11 +2258,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</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>Cuando hay menos volumen de transacciónes que espacio en los bloques, los mineros y los nodos de retransmisión pueden imponer una comisión mínima. Pagar solo esta comisión mínima está bien, pero tenga en cuenta que esto puede resultar en una transacción nunca confirmada una vez que haya más demanda de transacciones de Bitcoin de la que la red puede procesar.</translation>
+ <translation>Cuando hay menos volumen de transacciones que espacio en los bloques, los mineros y los nodos de retransmisión pueden imponer una comisión mínima. Pagar solo esta comisión mínima está bien, pero tenga en cuenta que esto puede resultar en una transacción nunca confirmada una vez que haya más demanda de transacciones de Bitcoin de la que la red puede procesar.</translation>
</message>
<message>
<source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
- <translation>Una comisión muy pequeña puede derivar en una transacción que nunca será confirmada</translation>
+ <translation>Una comisión muy pequeña puede derivar en una transacción que nunca será confirmada (leer herramientas de información).</translation>
</message>
<message>
<source>Confirmation time target:</source>
@@ -2245,7 +2278,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Clear &amp;All</source>
- <translation>Vaciar &amp;todo</translation>
+ <translation>Limpiar &amp;todo</translation>
</message>
<message>
<source>Balance:</source>
@@ -2273,7 +2306,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Copy after fee</source>
- <translation>Copiar después de comisión</translation>
+ <translation>Copiar después de la comisión</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -2292,6 +2325,10 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>%1 (%2 bloques)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Cr&amp;ear sin firmar</translation>
+ </message>
+ <message>
<source> from wallet '%1'</source>
<translation>de monedero %1</translation>
</message>
@@ -2313,15 +2350,15 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
- <translation>Puede incrementar la comisión más tarde (usa Replace-By-Fee, BIP-125).</translation>
+ <translation>Puede incrementar la comisión más tarde (use Replace-By-Fee, BIP-125).</translation>
</message>
<message>
<source>Please, review your transaction.</source>
- <translation>Por favor, revisa tu transacción</translation>
+ <translation>Por favor, revise su transacción.</translation>
</message>
<message>
<source>Transaction fee</source>
- <translation>Comisión de transacción</translation>
+ <translation>Comisión por transacción. </translation>
</message>
<message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
@@ -2332,24 +2369,32 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Monto total</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Para ver la lista de receptores haga clic en "Mostrar detalles"</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
- <translation>Confirmar enviar monedas</translation>
+ <translation>Confirmar el envío de monedas</translation>
+ </message>
+ <message>
+ <source>Send</source>
+ <translation>Enviar</translation>
</message>
<message>
<source>The recipient address is not valid. Please recheck.</source>
- <translation>La dirección de destinatario no es válida. Por favor revísela.</translation>
+ <translation>La dirección de envío no es válida. Por favor, revísela.</translation>
</message>
<message>
<source>The amount to pay must be larger than 0.</source>
- <translation>La cantidad a pagar debe de ser mayor que 0.</translation>
+ <translation>La cantidad a pagar tiene que ser mayor que 0.</translation>
</message>
<message>
<source>The amount exceeds your balance.</source>
- <translation>La cantidad excede su saldo.</translation>
+ <translation>El monto sobrepasa su saldo.</translation>
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>El total excede su saldo cuando la comisión de transacción de %1 es incluida.</translation>
+ <translation>El total sobrepasa su saldo cuando se incluyen %1 como comisión por transacción.</translation>
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
@@ -2357,15 +2402,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Transaction creation failed!</source>
- <translation>¡Falló la creación de transacción!</translation>
- </message>
- <message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Se ha rechazado la transacción por la siguiente razón: %1</translation>
+ <translation>¡Fallo al crear la transacción!</translation>
</message>
<message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation>Una comisión mayor que %1 se considera una comisión irracionalmente alta.</translation>
+ <translation>Una comisión mayor que %1 se considera una comisión absurdamente alta.</translation>
</message>
<message>
<source>Payment request expired.</source>
@@ -2377,19 +2418,19 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
- <translation>Alerta: dirección Bitcoin inválida</translation>
+ <translation>Peligro: Dirección de Bitcoin inválida</translation>
</message>
<message>
<source>Warning: Unknown change address</source>
- <translation>Alerta: dirección de cambio desconocida</translation>
+ <translation>Peligro: Dirección de cambio desconocida</translation>
</message>
<message>
<source>Confirm custom change address</source>
- <translation>Confirmar dirección de cambio personalizada</translation>
+ <translation>Confirma 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>La dirección que ha seleccionado para cambiar no es parte de este monedero. ninguno o todos los fondos de su monedero pueden ser enviados a esta dirección. ¿Está seguro?</translation>
+ <translation>La dirección de cambio seleccionada no es parte de su monedero. Parte de sus fondos serán enviados a esta dirección. ¿Está seguro?</translation>
</message>
<message>
<source>(no label)</source>
@@ -2400,11 +2441,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<name>SendCoinsEntry</name>
<message>
<source>A&amp;mount:</source>
- <translation>Ca&amp;ntidad:</translation>
+ <translation>&amp;Cantidad:</translation>
</message>
<message>
<source>Pay &amp;To:</source>
- <translation>&amp;Pagar a:</translation>
+ <translation>Pagar &amp;a:</translation>
</message>
<message>
<source>&amp;Label:</source>
@@ -2412,15 +2453,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Choose previously used address</source>
- <translation>Escoger direcciones previamente usadas</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Esto es un pago ordinario.</translation>
+ <translation>Escoger dirección previamente usada</translation>
</message>
<message>
<source>The Bitcoin address to send the payment to</source>
- <translation>Dirección Bitcoin a la que enviar el pago</translation>
+ <translation>Dirección Bitcoin a la que se enviará el pago</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2428,7 +2465,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Paste address from clipboard</source>
- <translation>Pegar dirección desde portapapeles</translation>
+ <translation>Pegar dirección desde el portapapeles</translation>
</message>
<message>
<source>Alt+P</source>
@@ -2436,19 +2473,19 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Remove this entry</source>
- <translation>Eliminar esta transacción</translation>
+ <translation>Eliminar esta entrada.</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>La comisión será deducida de la cantidad que sea mandada. El destinatario recibirá menos bitcoins de la cantidad introducida en el campo Cantidad. Si hay varios destinatarios, la comisión será distribuida a partes iguales.</translation>
+ <translation>La comisión será deducida de la cantidad que sea enviada. El destinatario recibirá menos bitcoins que la cantidad introducida en el campo Cantidad. Si hay varios destinatarios seleccionados, la comisión será distribuida a partes iguales.</translation>
</message>
<message>
<source>S&amp;ubtract fee from amount</source>
- <translation>Restar comisiones de la cantidad.</translation>
+ <translation>Restar comisiones del monto.</translation>
</message>
<message>
<source>Use available balance</source>
- <translation>Usar balance disponible</translation>
+ <translation>Usar el balance disponible</translation>
</message>
<message>
<source>Message:</source>
@@ -2464,7 +2501,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation>
+ <translation>Introduzca 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>
@@ -2478,27 +2515,16 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Introduzca una etiqueta para esta dirección para añadirla a su lista de direcciones.</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Sí</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
<message>
<source>%1 is shutting down...</source>
- <translation>%1 se esta cerrando...</translation>
+ <translation>%1 se está cerrando...</translation>
</message>
<message>
<source>Do not shut down the computer until this window disappears.</source>
- <translation>No apague el equipo hasta que desaparezca esta ventana.</translation>
+ <translation>No apague el equipo hasta que esta ventana desaparezca.</translation>
</message>
</context>
<context>
@@ -2521,7 +2547,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Choose previously used address</source>
- <translation>Escoger dirección previamente usada</translation>
+ <translation>Escoger direcciones previamente usadas</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2529,7 +2555,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Paste address from clipboard</source>
- <translation>Pegar dirección desde portapapeles</translation>
+ <translation>Pegar dirección desde el portapapeles</translation>
</message>
<message>
<source>Alt+P</source>
@@ -2557,11 +2583,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Reset all sign message fields</source>
- <translation>Vaciar todos los campos de la firma de mensaje</translation>
+ <translation>Limpiar todos los campos de la firma de mensaje</translation>
</message>
<message>
<source>Clear &amp;All</source>
- <translation>Vaciar &amp;todo</translation>
+ <translation>Limpiar &amp;todo</translation>
</message>
<message>
<source>&amp;Verify Message</source>
@@ -2569,7 +2595,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</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>Introduzca la dirección para la firma, el mensaje (asegurándose de copiar tal cual los saltos de línea, espacios, tabulaciones, etc.) y la firma a continuación para verificar el mensaje. Tenga cuidado de no asumir más información de lo que dice el propio mensaje firmado para evitar fraudes basados en ataques de tipo man-in-the-middle. </translation>
+ <translation>Introduzca la dirección para la firma, el mensaje (asegurándose de copiar tal cual los saltos de línea, espacios, tabulaciones, etc.) y la firma a continuación para verificar el mensaje. Tenga cuidado de no asumir más información de lo que dice el propio mensaje firmado para evitar fraudes basados en ataques de tipo man-in-the-middle.</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
@@ -2585,23 +2611,23 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Reset all verify message fields</source>
- <translation>Vaciar todos los campos de la verificación de mensaje</translation>
+ <translation>Limpiar todos los campos de la verificación de mensaje</translation>
</message>
<message>
<source>Click "Sign Message" to generate signature</source>
- <translation>Click en "Fírmar mensaje" para generar una firma</translation>
+ <translation>Clic en "Firmar mensaje" para generar una firma.</translation>
</message>
<message>
<source>The entered address is invalid.</source>
- <translation>La dirección introducida no es válida.</translation>
+ <translation>La dirección ingresada es inválida</translation>
</message>
<message>
<source>Please check the address and try again.</source>
- <translation>Por favor revise la dirección e inténtelo de nuevo.</translation>
+ <translation>Por favor, revise la dirección e inténtelo nuevamente.</translation>
</message>
<message>
<source>The entered address does not refer to a key.</source>
- <translation>La dirección introducida no remite a una clave.</translation>
+ <translation>La dirección ingresada no corresponde a una llave válida.</translation>
</message>
<message>
<source>Wallet unlock was cancelled.</source>
@@ -2609,7 +2635,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Private key for the entered address is not available.</source>
- <translation>La clave privada de la dirección introducida no está disponible.</translation>
+ <translation>La llave privada para la dirección introducida no está disponible.</translation>
</message>
<message>
<source>Message signing failed.</source>
@@ -2621,15 +2647,15 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>The signature could not be decoded.</source>
- <translation>La firma no pudo descodificarse.</translation>
+ <translation>La firma no pudo decodificarse.</translation>
</message>
<message>
<source>Please check the signature and try again.</source>
- <translation>Por favor compruebe la firma y pruebe de nuevo.</translation>
+ <translation>Por favor, compruebe la firma e inténtelo de nuevo.</translation>
</message>
<message>
<source>The signature did not match the message digest.</source>
- <translation>La firma no se combinó con el mensaje.</translation>
+ <translation>La firma no coincide con el resumen del mensaje.</translation>
</message>
<message>
<source>Message verification failed.</source>
@@ -2659,7 +2685,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
- <translation>Hay un conflicto con una transacción con %1 confirmaciones</translation>
+ <translation>Hay un conflicto con una transacción con %1 confirmaciones.</translation>
</message>
<message>
<source>0/unconfirmed, %1</source>
@@ -2667,11 +2693,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>in memory pool</source>
- <translation>en el pool de memoria</translation>
+ <translation>en el "pool" de memoria</translation>
</message>
<message>
<source>not in memory pool</source>
- <translation>no en el pool de memoria</translation>
+ <translation>no está en el "pool" de memoria</translation>
</message>
<message>
<source>abandoned</source>
@@ -2715,11 +2741,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>own address</source>
- <translation>dirección propia</translation>
+ <translation>dirección personal</translation>
</message>
<message>
<source>watch-only</source>
- <translation>de observación</translation>
+ <translation>Solo observación</translation>
</message>
<message>
<source>label</source>
@@ -2727,7 +2753,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Credit</source>
- <translation>Credito</translation>
+ <translation>Crédito</translation>
</message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
@@ -2739,7 +2765,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Debit</source>
- <translation>Enviado</translation>
+ <translation>Débito</translation>
</message>
<message>
<source>Total debit</source>
@@ -2747,15 +2773,15 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Total credit</source>
- <translation>Total recibido</translation>
+ <translation>Crédito total</translation>
</message>
<message>
<source>Transaction fee</source>
- <translation>Comisión de transacción</translation>
+ <translation>Comisión por transacción.</translation>
</message>
<message>
<source>Net amount</source>
- <translation>Cantidad neta</translation>
+ <translation>Cantidad total</translation>
</message>
<message>
<source>Message</source>
@@ -2779,7 +2805,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Output index</source>
- <translation>Indice de salida</translation>
+ <translation>Índice de salida</translation>
+ </message>
+ <message>
+ <source> (Certificate was not verified)</source>
+ <translation>(El certificado no ha sido verificado)</translation>
</message>
<message>
<source>Merchant</source>
@@ -2869,7 +2899,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Immature (%1 confirmations, will be available after %2)</source>
- <translation>No disponible (%1 confirmaciones. Estarán disponibles al cabo de %2)</translation>
+ <translation>Inmaduro (%1 confirmación(es), Estarán disponibles después de %2)</translation>
</message>
<message>
<source>Generated but not accepted</source>
@@ -2881,7 +2911,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Received from</source>
- <translation>Recibidos de</translation>
+ <translation>Recibido de</translation>
</message>
<message>
<source>Sent to</source>
@@ -2889,7 +2919,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Payment to yourself</source>
- <translation>Pago proprio</translation>
+ <translation>Pago a usted mismo.</translation>
</message>
<message>
<source>Mined</source>
@@ -2897,11 +2927,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>watch-only</source>
- <translation>de observación</translation>
+ <translation>Solo-ver.</translation>
</message>
<message>
<source>(n/a)</source>
- <translation>(nd)</translation>
+ <translation>(n/a)</translation>
</message>
<message>
<source>(no label)</source>
@@ -2909,11 +2939,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>Estado de transacción. Pasa el ratón sobre este campo para ver el número de confirmaciones.</translation>
+ <translation>Estado de transacción. Pase el ratón sobre este campo para ver el número de confirmaciones.</translation>
</message>
<message>
<source>Date and time that the transaction was received.</source>
- <translation>Fecha y hora en que se recibió la transacción.</translation>
+ <translation>Fecha y hora cuando se recibió la transacción</translation>
</message>
<message>
<source>Type of transaction.</source>
@@ -2925,11 +2955,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>User-defined intent/purpose of the transaction.</source>
- <translation>Descripción de la transacción definido por el usuario.</translation>
+ <translation>Descripción de la transacción definida por el usuario.</translation>
</message>
<message>
<source>Amount removed from or added to balance.</source>
- <translation>Cantidad retirada o añadida al saldo.</translation>
+ <translation>Cantidad restada o añadida al balance</translation>
</message>
</context>
<context>
@@ -2996,11 +3026,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Increase transaction fee</source>
- <translation>Incrementar cuota de transacción</translation>
+ <translation>Incrementar la comisión por transacción</translation>
</message>
<message>
<source>Copy address</source>
- <translation>Copiar ubicación</translation>
+ <translation>Copiar dirección</translation>
</message>
<message>
<source>Copy label</source>
@@ -3012,11 +3042,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Copy transaction ID</source>
- <translation>Copiar ID de transacción</translation>
+ <translation>Copiar ID de la transacción</translation>
</message>
<message>
<source>Copy raw transaction</source>
- <translation>Copiar transacción raw</translation>
+ <translation>Copiar transacción bruta</translation>
</message>
<message>
<source>Copy full transaction details</source>
@@ -3036,7 +3066,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>Archivo separado de coma (*.csv)</translation>
+ <translation>Archivo de columnas separadas por coma (*.csv)</translation>
</message>
<message>
<source>Confirmed</source>
@@ -3044,7 +3074,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Watch-only</source>
- <translation>De observación</translation>
+ <translation>Solo observación</translation>
</message>
<message>
<source>Date</source>
@@ -3068,7 +3098,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Exporting Failed</source>
- <translation>Falló la exportación</translation>
+ <translation>La exportación falló</translation>
</message>
<message>
<source>There was an error trying to save the transaction history to %1.</source>
@@ -3105,8 +3135,12 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Cerrar monedero</translation>
</message>
<message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>¿Está seguro que desea cerrar el monedero &lt;i&gt;%1&lt;/i&gt;?</translation>
+ </message>
+ <message>
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
- <translation>Cerrar la monedero durante demasiado tiempo puede causar resincronizado de toda la cadena si la poda es habilitado.</translation>
+ <translation>Cerrar el monedero durante demasiado tiempo puede causar la resincronización de toda la cadena si la poda es habilitada.</translation>
</message>
</context>
<context>
@@ -3120,7 +3154,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<name>WalletModel</name>
<message>
<source>Send Coins</source>
- <translation>Enviar</translation>
+ <translation>Enviar monedas</translation>
</message>
<message>
<source>Fee bump error</source>
@@ -3128,7 +3162,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Increasing transaction fee failed</source>
- <translation>Ha fallado el incremento de la comisión de transacción.</translation>
+ <translation>Ha fallado el incremento de la comisión por transacción.</translation>
</message>
<message>
<source>Do you want to increase the fee?</source>
@@ -3148,7 +3182,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Confirm fee bump</source>
- <translation>Confirmar incremento de comisión.</translation>
+ <translation>Confirmar incremento de comisión</translation>
</message>
<message>
<source>Can't sign transaction.</source>
@@ -3175,23 +3209,23 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Backup Wallet</source>
- <translation>Copia de seguridad del monedero</translation>
+ <translation>Respaldar monedero</translation>
</message>
<message>
<source>Wallet Data (*.dat)</source>
- <translation>Datos de monedero (*.dat)</translation>
+ <translation>Archivo de respaldo (*.dat)</translation>
</message>
<message>
<source>Backup Failed</source>
- <translation>La copia de seguridad ha fallado</translation>
+ <translation>Ha fallado el respaldo</translation>
</message>
<message>
<source>There was an error trying to save the wallet data to %1.</source>
- <translation>Ha habido un error al intentar guardar los datos del monedero en %1.</translation>
+ <translation>Ha habido un error al intentar guardar los datos del monedero a %1.</translation>
</message>
<message>
<source>Backup Successful</source>
- <translation>Se ha completado con éxito la copia de respaldo</translation>
+ <translation>Respaldo exitoso</translation>
</message>
<message>
<source>The wallet data was successfully saved to %1.</source>
@@ -3210,27 +3244,23 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation>La Poda se ha configurado por debajo del minimo de %d MiB. Por favor utiliza un valor más alto.</translation>
+ <translation>La Poda se ha configurado por debajo del mínimo de %d MiB. Por favor, utilice un valor mas alto.</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>Poda: la ultima sincronizacion del monedero sobrepasa los datos podados. Necesitas reindexar con -reindex (o descargar la cadena de bloques de nuevo en el caso de un nodo podado)</translation>
- </message>
- <message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Nos es posible re-escanear en modo podado.Necesitas utilizar -reindex el cual descargara la cadena de bloques al completo de nuevo.</translation>
+ <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>Un error interno fatal ocurrió, ver debug.log para detalles</translation>
+ <translation>Error: Un error interno fatal ha ocurrido. Ver debug.log para detalles</translation>
</message>
<message>
<source>Pruning blockstore...</source>
- <translation>Poda blockstore ...</translation>
+ <translation>Poda blockstore...</translation>
</message>
<message>
<source>Unable to start HTTP server. See debug log for details.</source>
- <translation>No se ha podido comenzar el servidor HTTP. Ver debug log para detalles.</translation>
+ <translation>No se ha podido iniciar el servidor HTTP. Ver debug log para detalles.</translation>
</message>
<message>
<source>The %s developers</source>
@@ -3238,7 +3268,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</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 cojunto de claves internas y no se pueden generar claves.</translation>
+ <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>
@@ -3250,27 +3280,27 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</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 leyendo %s!. Todas las claves se han leido correctamente, pero los datos de transacciones o la libreta de direcciones pueden faltar o ser incorrectos.</translation>
+ <translation>Error leyendo %s!. Todas las claves se han leído correctamente, pero los datos de la transacción o el libro de direcciones pueden faltar o ser incorrectos.</translation>
</message>
<message>
<source>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, compruebe si la fecha y hora en su computadora son correctas! Si su reloj esta mal, %s no trabajara correctamente. </translation>
+ <translation>¡Por favor, compruebe si la fecha y hora en su computadora son correctas! Si su reloj está mal, %s no trabajará correctamente.</translation>
</message>
<message>
<source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <translation>Contribuya si encuentra %s de utilidad. Visite %s para mas información acerca del programa.</translation>
+ <translation>Contribuya si encuentra %s de utilidad. Visite %s para más información acerca del programa.</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 datos de bloques contiene un bloque que parece ser del futuro. Esto puede ser porque la fecha y hora de tu ordenador están mal ajustados. Reconstruye la base de datos de bloques solo si estas seguro de que la fecha y hora de tu ordenador estan ajustados correctamente.</translation>
+ <translation>La base de datos de bloques contiene un bloque que parece ser del futuro. Esto puede ser porque la fecha y hora de su ordenador están mal ajustados. Reconstruya la base de datos de bloques solo si está seguro de que la fecha y hora de su ordenador están ajustadas correctamente.</translation>
</message>
<message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
- <translation>Esta es una versión de prueba prelanzada - utilícelo a su propio riesgo - no lo utilice para aplicaciones de minería o comerciales</translation>
+ <translation>Esta es una versión de prueba prelanzada - utilícela bajo su propio riesgo - no la utilice para aplicaciones de minería o comerciales</translation>
</message>
<message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>Esta es la comisión de transacción que puedes descartar si el cambio es menor que el polvo a este nivel</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>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
@@ -3286,15 +3316,15 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</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>Advertencia: ¡No parecemos estar del todo con nuestros pares! Puede que necesite actualizarse, o puede que otros nodos necesiten actualizarse.</translation>
+ <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 versión no esperada</translation>
+ <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 recuperacion</translation>
+ <translation>%s corrupto. Fracasó la recuperación</translation>
</message>
<message>
<source>-maxmempool must be at least %d MB</source>
@@ -3306,7 +3336,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Change index out of range</source>
- <translation>Cambio de indice fuera de rango</translation>
+ <translation>Cambio de índice fuera de rango</translation>
</message>
<message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
@@ -3322,7 +3352,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Do you want to rebuild the block database now?</source>
- <translation>¿Quieres reconstruir la base de datos de bloques ahora?</translation>
+ <translation>¿Quiere reconstruir la base de datos de bloques ahora?</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3338,15 +3368,15 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Error loading %s: Private keys can only be disabled during creation</source>
- <translation>Error cargando %s: las claves privadas solo pueden ser deshabilitado durante la creación</translation>
+ <translation>Error cargando %s: Las claves privadas solo pueden ser deshabilitadas durante la creación</translation>
</message>
<message>
<source>Error loading %s: Wallet corrupted</source>
- <translation>Error cargando %s: Monedero dañado</translation>
+ <translation>Error cargando %s: Monedero corrupto</translation>
</message>
<message>
<source>Error loading %s: Wallet requires newer version of %s</source>
- <translation>Error cargando %s: Monedero requiere un versión mas reciente de %s</translation>
+ <translation>Error cargando %s: El monedero requiere una versión más reciente de %s</translation>
</message>
<message>
<source>Error loading block database</source>
@@ -3370,7 +3400,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>Incorrecto o bloque de génesis no encontrado. Datadir equivocada para la red?</translation>
+ <translation>Incorrecto o bloque de génesis no encontrado. ¿Datadir equivocada para la red?</translation>
</message>
<message>
<source>Initialization sanity check failed. %s is shutting down.</source>
@@ -3382,15 +3412,15 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>Cantidad no valida para -%s=&lt;amount&gt;: '%s'</translation>
+ <translation>Monto inválido para -%s=&lt;amount&gt;: '%s'</translation>
</message>
<message>
<source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
- <translation>Cantidad inválida para -discardfee=&lt;amount&gt;: '%s'</translation>
+ <translation>Monto inválido para -discardfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
<source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>Cantidad inválida para -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ <translation>Monto inválido para -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
<source>Specified blocks directory "%s" does not exist.</source>
@@ -3410,7 +3440,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Loading P2P addresses...</source>
- <translation>Cargando direcciones P2P ...</translation>
+ <translation>Cargando direcciones P2P...</translation>
</message>
<message>
<source>Error: Disk space is too low!</source>
@@ -3422,11 +3452,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Not enough file descriptors available.</source>
- <translation>No hay suficientes descriptores de archivo disponibles. </translation>
+ <translation>No hay suficientes descriptores de archivo disponibles.</translation>
</message>
<message>
<source>Prune cannot be configured with a negative value.</source>
- <translation>Pode no se puede configurar con un valor negativo.</translation>
+ <translation>Prune no se puede configurar con un valor negativo.</translation>
</message>
<message>
<source>Prune mode is incompatible with -txindex.</source>
@@ -3434,23 +3464,23 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Replaying blocks...</source>
- <translation>Reproduciendo bloques ...</translation>
+ <translation>Reproduciendo bloques...</translation>
</message>
<message>
<source>Rewinding blocks...</source>
- <translation>Verificando bloques...</translation>
+ <translation>Rebobinando bloques...</translation>
</message>
<message>
<source>The source code is available from %s.</source>
- <translation>El código fuente esta disponible desde %s.</translation>
+ <translation>El código fuente está disponible desde %s.</translation>
</message>
<message>
<source>Transaction fee and change calculation failed</source>
- <translation>El cálculo de la comisión de transacción y del cambio han fallado</translation>
+ <translation>El cálculo de la comisión por transacción y del cambio han fallado</translation>
</message>
<message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
- <translation>No se ha podido conectar con %s en este equipo. %s es posible que este todavia en ejecución.</translation>
+ <translation>No se ha podido conectar con %s en este equipo. %s es posible que esté todavía en ejecución.</translation>
</message>
<message>
<source>Unable to generate keys</source>
@@ -3478,7 +3508,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Error: la escucha para conexiones entrantes falló (la escucha regresó el error %s)</translation>
+ <translation>Error: La escucha para conexiones entrantes falló (la escucha devolvió el 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>
@@ -3486,15 +3516,15 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>Monto de transacción muy pequeña luego de la deducción por comisión</translation>
+ <translation>Monto de transacción muy pequeño después de la deducción de la comisión</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>Necesitas reconstruir la base de datos utilizando -reindex para volver al modo sin recorte. Esto volverá a descargar toda la cadena de bloques</translation>
+ <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>Error reading from database, shutting down.</source>
- <translation>Error al leer la base de datos, cerrando.</translation>
+ <translation>Error al leer la base de datos, cerrando la aplicación.</translation>
</message>
<message>
<source>Error upgrading chainstate database</source>
@@ -3506,11 +3536,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Invalid -onion address or hostname: '%s'</source>
- <translation>Dirección -onion o nombre de host inválido: '%s'</translation>
+ <translation>Dirección de -onion o dominio '%s' inválido</translation>
</message>
<message>
<source>Invalid -proxy address or hostname: '%s'</source>
- <translation>Dirección -proxy o nombre de host inválido: '%s'</translation>
+ <translation>Dirección de -proxy o dominio ' %s' inválido</translation>
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
@@ -3525,6 +3555,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>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>El modo de poda es incompatible con -blockfilterindex</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reduciendo -maxconnections de %d a %d, debido a limitaciones del sistema.</translation>
</message>
@@ -3534,7 +3568,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Signing transaction failed</source>
- <translation>Transacción falló</translation>
+ <translation>La transacción falló</translation>
</message>
<message>
<source>Specified -walletdir "%s" does not exist</source>
@@ -3556,23 +3590,23 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
- <translation>Cantidad de la transacción demasiado pequeña para pagar la comisión</translation>
+ <translation>El monto de la transacción es muy pequeño para pagar la comisión</translation>
</message>
<message>
<source>This is experimental software.</source>
- <translation>Este software es experimental.</translation>
+ <translation>Este es un software experimental.</translation>
</message>
<message>
<source>Transaction amount too small</source>
- <translation>Cantidad de la transacción demasiado pequeña</translation>
+ <translation>El monto de la transacción es demasiado pequeño para pagar la comisión.</translation>
</message>
<message>
<source>Transaction too large</source>
- <translation>Transacción demasiado grande, intenta dividirla en varias.</translation>
+ <translation>Transacción demasiado grande</translation>
</message>
<message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation>No es posible conectar con %s en este sistema (bind ha dado el error %s)</translation>
+ <translation>No es posible conectar con %s en este sistema (bind ha devuelto el error %s)</translation>
</message>
<message>
<source>Unable to create the PID file '%s': %s</source>
@@ -3583,8 +3617,12 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>No es posible generar llaves iniciales</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>%s es un valor desconocido para -blockfilterindex</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
- <translation>Verificando monedero(s)...</translation>
+ <translation>Verificando monedero...</translation>
</message>
<message>
<source>Warning: unknown new rules activated (versionbit %i)</source>
@@ -3596,15 +3634,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <translation>-maxtxfee tiene un ajuste muy elevado! Comisiones muy grandes podrían ser pagadas en una única transaccion.</translation>
+ <translation>-maxtxfee tiene un valor muy elevado. Comisiones muy grandes podrían ser pagadas en una única transacción.</translation>
</message>
<message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation>Esta es la comisión de transacción que debe pagar cuando las estimaciones de comisión no estén disponibles.</translation>
- </message>
- <message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Este producto incluye software desarrollado por el Proyecto OpenSSL para utilizarlo en el juego de herramientas OpenSSL %s y software criptográfico escrito por Eric Young y software UPnP escrito por Thomas Bernard.</translation>
+ <translation>Esta es la comisión por transacción que deberá pagar cuando la estimación de comisión no esté disponible.</translation>
</message>
<message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
@@ -3612,11 +3646,11 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</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>Aviso: fichero 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>
+ <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 se establece muy alto!</translation>
+ <translation>¡%s está configurado muy alto!</translation>
</message>
<message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
@@ -3624,31 +3658,31 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Starting network threads...</source>
- <translation>Iniciando funciones de red...</translation>
+ <translation>Iniciando procesos de red...</translation>
</message>
<message>
<source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation>El monedero evitará pagar menos que la cuota de retransmisión mínima.</translation>
+ <translation>El monedero no permitirá pagar menos que la comisión mínima para retransmitir llamada relay fee.</translation>
</message>
<message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Esta es la comisión mínima de transacción que usted paga en cada transacción.</translation>
+ <translation>Esta es la tarifa mínima a pagar en cada transacción.</translation>
</message>
<message>
<source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Esta es la comisión de transacción que pagará si envía una transacción.</translation>
+ <translation>Esta es la comisión por transacción a pagar si realiza una transacción.</translation>
</message>
<message>
<source>Transaction amounts must not be negative</source>
- <translation>Las cantidades de transacción no deben ser negativa</translation>
+ <translation>Los montos de la transacción no deben ser negativos</translation>
</message>
<message>
<source>Transaction has too long of a mempool chain</source>
- <translation>La transacción tiene demasiado tiempo de una cadena de mempool</translation>
+ <translation>La transacción tiene largo tiempo en una cadena mempool</translation>
</message>
<message>
<source>Transaction must have at least one recipient</source>
- <translation>La transacción debe de tener al menos un receptor</translation>
+ <translation>La transacción debe tener al menos un destinatario</translation>
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
@@ -3668,7 +3702,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <translation>Advertencia: claves privadas detectadas en el monedero {%s} con claves privadas deshabilitadas</translation>
+ <translation>Advertencia: Claves privadas detectadas en el monedero {%s} con clave privada deshabilitada</translation>
</message>
<message>
<source>Cannot write to data directory '%s'; check permissions.</source>
@@ -3684,7 +3718,7 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
</message>
<message>
<source>Cannot downgrade wallet</source>
- <translation>No se puede cambiar a una versión mas antigua el monedero</translation>
+ <translation>No se puede rebajar el monedero</translation>
</message>
<message>
<source>Rescanning...</source>
diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts
index 6abf6cd7c5..4b864f4e74 100644
--- a/src/qt/locale/bitcoin_es_CL.ts
+++ b/src/qt/locale/bitcoin_es_CL.ts
@@ -48,11 +48,11 @@ Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Elija la dirección para enviar las monedas </translation>
+ <translation>Elija la dirección para enviar las monedas</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>Elige la dirección para recibir las monedas </translation>
+ <translation>Elige la dirección para recibir las monedas</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -339,14 +339,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Cambiar la contraseña usando la encriptación de la billetera</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Ventana desarrollador</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abrir consola de diagnóstico y desarrollo</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verificar Mensaje...</translation>
</message>
@@ -407,10 +399,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Mostrar la lista de direcciones y etiquetas de recepción usadas</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abra un bitcoin: URI o solicitud de pago</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Y opciones de línea de comando</translation>
</message>
@@ -793,10 +781,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>versión</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Alrededor de %1</translation>
</message>
@@ -924,31 +908,15 @@ Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
- <translation>Desconocido. Sincronizando cabecesar (%1, %2%)...</translation>
+ <translation>Desconocido. Sincronizando cabeceras (%1, %2%)...</translation>
</message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>URI abierto</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Abrir solicitud de pago de URI o archivo</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Seleccionar archivo de solicitud de pago</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Seleccione el archivo de solicitud de pago para abrir</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1137,7 +1105,7 @@ Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
<source>&amp;Unit to show amounts in:</source>
- <translation> Unidad para mostrar montos en:</translation>
+ <translation>Unidad para mostrar montos en:</translation>
</message>
<message>
<source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
@@ -1165,7 +1133,7 @@ Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
<source>none</source>
- <translation>ninguno </translation>
+ <translation>ninguno</translation>
</message>
<message>
<source>Confirm options reset</source>
@@ -1294,10 +1262,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Manejo de URI</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>La URL de búsqueda de solicitud de pago no es válida: %1</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>Dirección de pago inválida %1</translation>
</message>
@@ -1309,66 +1273,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<source>Payment request file handling</source>
<translation>Manejo de archivos de solicitud de pago</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>¡El archivo de solicitud de pago no se puede leer! Esto puede deberse a un archivo de solicitud de pago no válido.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Solicitud de pago rechazada</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>La red de solicitud de pago no coincide con la red del cliente.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Solicitud de pago caducada.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>La solicitud de pago no está inicializada.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Las solicitudes de pago no verificadas para los scripts de pago personalizados no son compatibles.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Solicitud de pago inválida</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>El monto para la solicitud de pago de %1 es muy pequeño (considera el dust).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Reembolso de %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Solicitud de pago %1 es muy grande (Actualmente %2 bytes, máximo %3 bytes)</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Fallo al comunicar con %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>¡La solicitud de pago no se puede analizar!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Mala respuesta del servidor %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Error de solicitud de red</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Pago reconocido</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1534,10 +1438,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Información</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Ventana de depuración</translation>
- </message>
- <message>
<source>General</source>
<translation>General</translation>
</message>
@@ -1563,7 +1463,7 @@ Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
<source>Number of connections</source>
- <translation>Número de conexiones </translation>
+ <translation>Número de conexiones</translation>
</message>
<message>
<source>Block chain</source>
@@ -1703,7 +1603,7 @@ Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
<source>Totals</source>
- <translation>Totales </translation>
+ <translation>Totales</translation>
</message>
<message>
<source>In:</source>
@@ -1783,7 +1683,7 @@ Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
<source>never</source>
- <translation>nunca </translation>
+ <translation>nunca</translation>
</message>
<message>
<source>Inbound</source>
@@ -1795,7 +1695,7 @@ Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
<source>Yes</source>
- <translation>Si </translation>
+ <translation>Si</translation>
</message>
<message>
<source>No</source>
@@ -2026,10 +1926,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Advertencia: En este momento no se puede estimar la cuota.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>Colapsar ajustes de comisión.</translation>
- </message>
- <message>
<source>per kilobyte</source>
<translation>por kilobyte</translation>
</message>
@@ -2155,10 +2051,6 @@ Tarifa de copia</translation>
<translation>¡Fallo al crear la transacción!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Se ha rechazado la transacción por la siguiente razón: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Una comisión mayor que %1 se considera como una comisión absurda-mente alta.</translation>
</message>
@@ -2206,10 +2098,6 @@ Tarifa de copia</translation>
<translation>Seleccionar dirección usada anteriormente</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Este es un pago normal</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Dirección Bitcoin a enviar el pago</translation>
</message>
@@ -2257,17 +2145,6 @@ Tarifa de copia</translation>
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Introduce una etiqueta a esta dirección para añadirla a tu guía</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Si </translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2933,10 +2810,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>No es es posible re-escanear en modo prune. Debes usar -reindex el cual descargara toda la blockchain de nuevo.</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>
diff --git a/src/qt/locale/bitcoin_es_CO.ts b/src/qt/locale/bitcoin_es_CO.ts
index 41111cf0f2..5c83f25286 100644
--- a/src/qt/locale/bitcoin_es_CO.ts
+++ b/src/qt/locale/bitcoin_es_CO.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Haga clic para editar la dirección o etiqueta</translation>
+ <translation>Clic derecho para editar la dirección o etiqueta</translation>
</message>
<message>
<source>Create a new address</source>
@@ -121,7 +121,7 @@
</message>
<message>
<source>Enter passphrase</source>
- <translation>Introduce contraseña actual </translation>
+ <translation>Introduce contraseña actual</translation>
</message>
<message>
<source>New passphrase</source>
@@ -161,7 +161,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>Advertencia: Si encriptas tu billetera y pierdes tu contraseña, vas a perder&lt;b&gt;TODOS TUS BITCOINS&lt;/b&gt;!</translation>
+ <translation>Advertencia: Si encriptas tu billetera y pierdes tu contraseña, vas a ¡&lt;b&gt;PERDER TODOS TUS BITCOINS&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -334,14 +334,6 @@
<translation>Cambiar la contraseña utilizada para la codificación de la billetera</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Ventana &amp;Debug</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abre consola de depuración y diagnóstico</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>Verificar mensaje....</translation>
</message>
@@ -402,10 +394,6 @@
<translation>Mostrar la lista de direcciones de recepción y etiquetas</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abrir un identificador URI bitcoin o una petición de pago</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Opciones de linea de comando</translation>
</message>
@@ -789,10 +777,6 @@
<translation>versión</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Sobre %1</translation>
</message>
@@ -920,31 +904,15 @@
</message>
<message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
- <translation>Desconocido. Sincronizando cabecesar (%1, %2%)...</translation>
+ <translation>Desconocido. Sincronizando cabeceras (%1, %2%)...</translation>
</message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Abrir URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Abrir solicitud de pago desde URI o un archivo</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Seleccionar archivo de solicitud de pago</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Seleccionar archivo de solicitud de pago para abrir</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1198,7 +1166,7 @@
</message>
<message>
<source>The supplied proxy address is invalid.</source>
- <translation>El proxy ingresado es inválido. </translation>
+ <translation>El proxy ingresado es inválido.</translation>
</message>
</context>
<context>
@@ -1291,10 +1259,6 @@
<translation>Manejo de URI</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Lectura de URL para la solicitud de pagos es invalida: %1</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>Dirección de pago inválida %1</translation>
</message>
@@ -1306,66 +1270,6 @@
<source>Payment request file handling</source>
<translation>Manejo del archivo de solicitud de pago</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>¡El archivo de solicitud de pago no se puede leer! Esto puede deberse a un archivo de solicitud de pago no válido.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Solicitud de pago rechazada</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Red de solicitud de pagos no coincide con la red del cliente.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Solicitud de pago expirada</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>La solicitud de pago no se ha iniciado.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Las solicitudes de pago no verificadas para los scripts de pago personalizados no son compatibles.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Solicitud de pago invalida.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>El monto para la solicitud de pago de %1 es muy pequeño (considera el dust).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Reembolsar desde %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Solicitud de pago %1 es muy grande (Actualmente %2 bytes, máximo %3 bytes)</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Fallo al comunicar con %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>La solicitud de pago no puede ser analizada!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Mala respuesta desde el servidor %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Error en petición de la red</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Pago declarado</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1531,10 +1435,6 @@
<translation>&amp;Información</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Ventana Debug</translation>
- </message>
- <message>
<source>General</source>
<translation>General</translation>
</message>
@@ -1883,7 +1783,7 @@
<name>ReceiveRequestDialog</name>
<message>
<source>QR Code</source>
- <translation>Código QR </translation>
+ <translation>Código QR</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2025,10 +1925,6 @@
<translation>Advertencia: En este momento no se puede estimar la cuota.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>Colapsar ajustes de comisión.</translation>
- </message>
- <message>
<source>per kilobyte</source>
<translation>por kilobyte</translation>
</message>
@@ -2153,10 +2049,6 @@
<translation>¡Fallo al crear la transacción!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Se ha rechazado la transacción por la siguiente razón: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Una comisión mayor que %1 se considera como una comisión absurda-mente alta.</translation>
</message>
@@ -2204,10 +2096,6 @@
<translation>Seleccionar dirección usada anteriormente</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Este es un pago normal</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Dirección Bitcoin a enviar el pago</translation>
</message>
@@ -2255,17 +2143,6 @@
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Introduce una etiqueta a esta dirección para añadirla a tu guía</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Si</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2930,10 +2807,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>No es es posible re-escanear en modo prune. Debes usar -reindex el cual descargara toda la blockchain de nuevo.</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>
diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts
index 7af0050a18..af7b5189b6 100644
--- a/src/qt/locale/bitcoin_es_DO.ts
+++ b/src/qt/locale/bitcoin_es_DO.ts
@@ -173,7 +173,43 @@
<source>Wallet encrypted</source>
<translation>Monedero cifrado</translation>
</message>
- </context>
+ <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 que haya realizado previamente de su archivo de monedero debe reemplazarse con el nuevo archivo de monedero cifrado. Por razones de seguridad, las copias de seguridad previas del archivo de monedero no cifradas serán inservibles en cuanto comience a usar el nuevo monedero cifrado.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Ha fallado el cifrado del monedero</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Ha fallado el cifrado del monedero debido a un error interno. El monedero no ha sido cifrado.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Las contraseñas no coinciden.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Ha fallado el desbloqueo del monedero</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>La contraseña introducida para descifrar el monedero es incorrecta.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Ha fallado el descifrado del monedero</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Se ha cambiado correctamente la contraseña del monedero.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Aviso: ¡La tecla de bloqueo de mayúsculas está activada!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
</context>
@@ -256,14 +292,6 @@
<translation>Cambiar frase secreta usada para la encriptación de la billetera</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Ventana de &amp;depuración</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abre la consola de depuración y diágnostico</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verificar mensaje...</translation>
</message>
@@ -324,10 +352,6 @@
<translation>Muestra la lista de direcciones de recepción y etiquetas</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abrir un bitcoin: URI o petición de pago</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Opciones de línea de comandos</translation>
</message>
@@ -383,7 +407,11 @@
<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>
- </context>
+ <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>
<name>CoinControlDialog</name>
<message>
@@ -455,6 +483,30 @@
<translation>Confirmado</translation>
</message>
<message>
+ <source>Copy address</source>
+ <translation>Copiar dirección</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copiar identificador de transacción</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Bloquear lo no gastado</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Desbloquear lo no gastado</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation>Copiar cantidad</translation>
</message>
@@ -463,6 +515,10 @@
<translation>Copiar comisión</translation>
</message>
<message>
+ <source>Copy after fee</source>
+ <translation>Copiar después de aplicar donación</translation>
+ </message>
+ <message>
<source>Copy bytes</source>
<translation>Copiar bytes</translation>
</message>
@@ -471,6 +527,10 @@
<translation>Copiar cambio</translation>
</message>
<message>
+ <source>(%1 locked)</source>
+ <translation>(%1 bloqueado)</translation>
+ </message>
+ <message>
<source>yes</source>
<translation>si</translation>
</message>
@@ -482,7 +542,15 @@
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>Enviar desde %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(cambio)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
</context>
@@ -511,7 +579,31 @@
<source>&amp;Address</source>
<translation>&amp;Dirección</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Nueva dirección de envío</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Editar dirección de recepción</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Editar dirección de envío</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>La dirección introducida "%1" no es una dirección Bitcoin válida.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se pudo desbloquear el monedero.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Ha fallado la generación de la nueva clave.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
@@ -542,10 +634,6 @@
<translation>versión</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>Command-line options</source>
<translation>Opciones de línea de comandos</translation>
</message>
@@ -595,22 +683,10 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Abrir URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Abrir solicitud de pago desde URI o archivo</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Seleccionar archivo de solicitud de pago</translation>
- </message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
</context>
@@ -786,6 +862,22 @@
</context>
<context>
<name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Error en petición de pago</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>No se pudo iniciar bitcoin: manejador de pago-al-clic</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>Gestión de URI</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Dirección de pago no válida %1</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -844,6 +936,10 @@
<translation>Guardar Imagen...</translation>
</message>
<message>
+ <source>&amp;Copy Image</source>
+ <translation>Copiar imagen</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI resultante demasiado larga. Intente reducir el texto de la etiqueta / mensaje.</translation>
</message>
@@ -851,7 +947,15 @@
<source>Error encoding URI into QR Code.</source>
<translation>Error al codificar la URI en el código QR.</translation>
</message>
- </context>
+ <message>
+ <source>Save QR Code</source>
+ <translation>Guardar código QR</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>Imágenes PNG (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -867,10 +971,6 @@
<translation>Información</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Ventana de depuración</translation>
- </message>
- <message>
<source>General</source>
<translation>General</translation>
</message>
@@ -973,7 +1073,15 @@
<source>Remove</source>
<translation>Eliminar</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -993,6 +1101,18 @@
<translation>Guardar Imagen...</translation>
</message>
<message>
+ <source>Request payment to %1</source>
+ <translation>Solicitar pago a %1</translation>
+ </message>
+ <message>
+ <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>
@@ -1005,6 +1125,10 @@
<translation>Nombre</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Mensaje</translation>
+ </message>
+ <message>
<source>Wallet</source>
<translation>Billetera</translation>
</message>
@@ -1020,9 +1144,17 @@
<translation>Nombre</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Mensaje</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
+ <message>
+ <source>(no message)</source>
+ <translation>(Ningun mensaje)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -1119,10 +1251,18 @@
<translation>Copiar cantidad</translation>
</message>
<message>
+ <source>Copy amount</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
<source>Copy fee</source>
<translation>Copiar comisión</translation>
</message>
<message>
+ <source>Copy after fee</source>
+ <translation>Copiar después de aplicar donación</translation>
+ </message>
+ <message>
<source>Copy bytes</source>
<translation>Copiar bytes</translation>
</message>
@@ -1131,10 +1271,50 @@
<translation>Copiar cambio</translation>
</message>
<message>
+ <source>%1 to %2</source>
+ <translation>%1 a %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>¿Está seguro que desea enviar?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Comisión de transacción</translation>
</message>
<message>
+ <source>Confirm send coins</source>
+ <translation>Confirmar el envío de monedas</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>La cantidad por pagar tiene que ser mayor de 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>La cantidad sobrepasa su saldo.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>El total sobrepasa su saldo cuando se incluye la tasa de envío de %1</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>¡Ha fallado la creación de la transacción!</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Alerta: Dirección de Bitcoin inválida</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Alerta: Dirección de Bitcoin inválida</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
@@ -1158,10 +1338,6 @@
<translation>Escoger dirección previamente usada</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Esto es un pago ordinario.</translation>
- </message>
- <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -1193,10 +1369,7 @@
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
+</context>
<context>
<name>ShutdownWindow</name>
</context>
@@ -1270,7 +1443,59 @@
<source>Reset all verify message fields</source>
<translation>Limpiar todos los campos de la verificación de mensaje</translation>
</message>
- </context>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Haga clic en "Firmar mensaje" para generar la firma</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>La dirección introducida es inválida.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Verifique la dirección e inténtelo de nuevo.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>La dirección introducida no corresponde a una clave.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>Se ha cancelado el desbloqueo del monedero. </translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>No se dispone de la clave privada para la dirección introducida.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Ha fallado la firma del mensaje.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Mensaje firmado.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>No se puede decodificar la firma.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Compruebe la firma e inténtelo de nuevo.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>La firma no coincide con el resumen del mensaje.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>La verificación del mensaje ha fallado.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Mensaje verificado.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
<message>
@@ -1281,22 +1506,118 @@
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>Abierto hasta %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/no confirmado</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 confirmaciones</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Estado</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Fecha</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>Fuente</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Generado</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>desconocido</translation>
</message>
<message>
+ <source>To</source>
+ <translation>Para</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>dirección propia</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>etiqueta</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Crédito</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>no aceptada</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Débito</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Comisión de transacción</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>Cantidad neta</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mensaje</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Comentario</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Vendedor</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>Las monedas generadas deben madurar %1 bloques antes de que puedan ser gastadas. Una vez que generas este bloque, es propagado por la red para ser añadido a la cadena de bloques. Si falla el intento de meterse en la cadena, su estado cambiará a "no aceptado" y ya no se puede gastar. Esto puede ocurrir ocasionalmente si otro nodo genera un bloque a pocos segundos del tuyo.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Información de depuración</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transacción</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>entradas</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Monto</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>verdadero</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>falso</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
@@ -1311,17 +1632,153 @@
<translation>Fecha</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Tipo</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Nombre</translation>
</message>
<message>
+ <source>Open until %1</source>
+ <translation>Abierto hasta %1</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Confirmado (%1 confirmaciones)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Generado pero no aceptado</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Recibido con</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Recibidos de</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Enviado a</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Pago propio</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minado</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(nd)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Estado de transacción. Pasa el ratón sobre este campo para ver el número de confirmaciones.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Fecha y hora en que se recibió la transacción.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Tipo de transacción.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Cantidad retirada o añadida al saldo.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Todo</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Hoy</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Esta semana</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Este mes</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Mes pasado</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Este año</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Rango...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Recibido con</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Enviado a</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>A usted mismo</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minado</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Otra</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Cantidad mínima</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Copiar dirección</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copiar identificador de transacción</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Editar etiqueta</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Mostrar detalles de la transacción</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>Exportar historial de transacciones</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Separar los archivos con comas (*.csv)</translation>
</message>
@@ -1334,6 +1791,10 @@
<translation>Fecha</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Tipo</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Nombre</translation>
</message>
@@ -1342,10 +1803,34 @@
<translation>Direccion</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>Error al exportar</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>Ha habido un error al intentar guardar la transacción con %1.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Exportación finalizada</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>La transacción ha sido guardada en %1.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Rango:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>para</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
@@ -1354,7 +1839,11 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>No se ha cargado ningún monedero</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
@@ -1372,10 +1861,46 @@
<source>Export the data in the current tab to a file</source>
<translation>Exportar los datos en la pestaña actual a un archivo</translation>
</message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Respaldo de monedero</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>Datos de monedero (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Ha fallado el respaldo</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>Ha habido un error al intentar guardar los datos del monedero en %1.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Se ha completado con éxito la copia de respaldo</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>Los datos del monedero se han guardado con éxito en %1.</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation>Esta es una versión de pre-prueba - utilícela bajo su propio riesgo. No la utilice para usos comerciales o de minería.</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Atención: ¡Parece que la red no está totalmente de acuerdo! Algunos mineros están presentando inconvenientes.</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>Atención: ¡Parece que no estamos completamente de acuerdo con nuestros pares! Podría necesitar una actualización, u otros nodos podrían necesitarla.</translation>
+ </message>
+ <message>
<source>Corrupted block database detected</source>
<translation>Corrupción de base de datos de bloques detectada.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_ES.ts b/src/qt/locale/bitcoin_es_ES.ts
deleted file mode 100644
index 1b196cb13f..0000000000
--- a/src/qt/locale/bitcoin_es_ES.ts
+++ /dev/null
@@ -1,3185 +0,0 @@
-<TS language="es_ES" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Haz clic derecho para editar la dirección o etiqueta</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Crear una nueva dirección</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Nuevo</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Copiar la dirección seleccionada al portapapeles del sistema</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Copiar</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>C&amp;errar</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Eliminar la dirección seleccionada de la lista</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Introduzca una dirección o etiqueta que buscar</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportar los datos en la ficha actual a un archivo</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportar</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Eliminar</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Seleccione la dirección a la que enviar monedas</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Seleccione la dirección de la que recibir monedas</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>E&amp;scoger</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Enviando direcciones</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Recibiendo direcciones</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>Estas son sus direcciones Bitcoin para enviar pagos. Verifique siempre la cantidad y la dirección de recibimiento antes de enviar monedas.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Estas son sus direcciones Bitcoin para recibir pagos. Se recomienda utilizar una nueva dirección de recibimiento para cada transacción</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Copiar Dirección</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Copiar &amp;Etiqueta</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Editar</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Exportar lista de direcciones</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Archivo separado de coma (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Falló la exportación</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Había un error intentando guardar la lista de direcciones en %1. Por favor inténtelo de nuevo.</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Dirección</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sin etiqueta)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Diálogo de contraseña</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Introducir contraseña</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Nueva contraseña</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Repita la nueva contraseña</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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 frase clave del monedero. &lt;br/&gt;Por favor utilice una frase clave de &lt;b&gt;diez o más carácteres aleatorios&lt;/b&gt;, o &lt;b&gt;ocho o más palabras&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Cifrar cartera</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Esta operación necesita su frase clave de monedero para desbloquear el monedero.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Desbloquear monedero</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Esta operación necesita su frase clave de cartera para desencriptar el monedero.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Desencriptar monedero</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Cambiar frase clave</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Introduzca la vieja frase clave y la nueva flase clave para el monedero.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Confirmar encriptación del monedero</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Advertencia: Si encripta su monedero y pierde su frase clave &lt;b&gt;PERDERÁ TODOS SUS BITCOINS&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>¿Seguro que desea encriptar su monedero?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Monedero encriptado</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 se cerrará ahora para terminar el proceso de encriptación. Recuerde que encriptar su monedero no puede proteger completamente su monedero de ser robado por malware que infecte su ordenador.</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 en su archivo de monedero debería ser reemplazada con el archivo de monedero encriptado generado recientemente. Por razones de seguridad, las copias de seguridad anteriores del archivo de monedero desencriptado serán inútiles en cuanto empiece a utilizar el nuevo monedero encriptado.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Fracasó la encriptación de monedero</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Falló la encriptación del monedero debido a un error interno. Su monedero no fue encriptado.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>La frase clave introducida no coincide.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Fracasó el desbloqueo del monedero</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>La frase clave introducida para la encriptación del monedero es incorrecta.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Fracasó la encriptación del monedero</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>La frase clave del monedero se ha cambiado con éxito.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Alerta: ¡La clave de bloqueo Caps está activa!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Máscara</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Bloqueado Hasta</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Firmar &amp;mensaje...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Sincronizando con la red…</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Vista general</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Nodo</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Mostrar vista general del monedero</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transacciones</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Examinar el historial de transacciones</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>S&amp;alir</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Salir de la aplicación</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Acerca de %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Mostrar información acerca de %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Acerca de &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Mostrar información acerca de Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Opciones...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Modificar las opciones de configuración para %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Cifrar monedero…</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Guardar copia del monedero...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Cambiar la contraseña…</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>Direcciones de &amp;envío...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Direcciones de &amp;recepción...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Abrir &amp;URI...</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Haz click para desactivar la actividad de red.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Actividad de red desactivada.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Haz click para reactivar la actividad de red.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Sincronizando cabeceras (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Reindexando bloques en disco...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Enviar bitcoins a una dirección Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Copia de seguridad del monedero en otra ubicación</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Cambiar la contraseña utilizada para el cifrado del monedero</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Ventana de depuración</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abrir la consola de depuración y diagnóstico</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Verificar mensaje...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Monedero</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Enviar</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Recibir</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Mostrar / Ocultar</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Mostrar u ocultar la ventana principal</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Cifrar las claves privadas de su monedero</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Firmar mensajes con sus direcciones Bitcoin para demostrar la propiedad</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Verificar mensajes comprobando que están firmados con direcciones Bitcoin concretas</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Archivo</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Configuración</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Ayuda</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Barra de pestañas</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Solicitar pagos (generando códigos QR e identificadores URI "bitcoin:")</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Mostrar la lista de direcciones de envío y etiquetas</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Muestra la lista de direcciones de recepción y etiquetas</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abrir un identificador URI "bitcoin:" o una petición de pago</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Opciones de consola de comandos</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n conexión activa hacia la red Bitcoin</numerusform><numerusform>%n conexiones activas hacia la red Bitcoin</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Indexando bloques en disco...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Procesando bloques en disco...</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>%n bloque procesado del historial de transacciones.</numerusform><numerusform>%n bloques procesados del historial de transacciones.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 atrás</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>El último bloque recibido fue generado hace %1.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Las transacciones posteriores aún no están visibles.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Error</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Aviso</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Información</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Actualizado</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Mostrar el mensaje de ayuda %1 para obtener una lista de los posibles comandos de linea de comandos de Bitcoin</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>%1 cliente</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Conectando a pares...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Actualizando...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Fecha: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Amount: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Tipo: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Etiqueta: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Dirección: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Transacción enviada</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Transacción entrante</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>La generación de claves HD está &lt;b&gt;activada&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>La generación de claves HD está &lt;b&gt;desactivada&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>El monedero está &lt;b&gt;cifrado&lt;/b&gt; y actualmente &lt;b&gt;desbloqueado&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation>El monedero está &lt;b&gt;cifrado&lt;/b&gt; y actualmente &lt;b&gt;bloqueado&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 continuar de manera segura y se cerrará.</translation>
- </message>
-</context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Selección de la moneda</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Cantidad:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Cuantía:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Tasa:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Polvo:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Después de aplicar la comisión:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Cambio:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(des)marcar todos</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Modo árbol</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Modo lista</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantidad</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Recibido con etiqueta</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Recibido con dirección</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Fecha</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Confirmaciones</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmado</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Copiar ubicación</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copiar etiqueta</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiar cantidad</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copiar ID de transacción</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Bloquear lo no gastado</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Desbloquear lo no gastado</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copiar cantidad</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copiar cuota</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Copiar después de couta</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copiar bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copiar polvo</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copiar cambio</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 bloqueado)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>sí</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>Esta etiqueta se vuelve roja si algún destinatario recibe una cantidad inferior a la actual puerta polvorienta.</translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Puede variar +/- %1 satoshi(s) por entrada.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sin etiqueta)</translation>
- </message>
- <message>
- <source>change from %1 (%2)</source>
- <translation>cambia desde %1 (%2)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation>(cambio)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Editar Dirección</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Etiqueta</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>La etiqueta asociada con esta entrada de la lista de direcciones</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>La dirección asociada con esta entrada de la lista de direcciones. Solo puede ser modificada para direcciones de envío.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Dirección</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Nueva dirección de envío</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Editar dirección de recivimiento</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Editar dirección de envío</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>La dirección introducida "%1" no es una dirección Bitcoin válida.</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Podría no desbloquear el monedero.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Falló la generación de la nueva clave.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Se creará un nuevo directorio de datos.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>nombre</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>El directorio ya existe. Añada %1 si pretende crear aquí un directorio nuevo.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>La ruta ya existe y no es un directorio.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>No se puede crear un directorio de datos aquí.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>versión</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>Acerda de %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Opciones de la línea de órdenes</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Bienvenido</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Bienvenido a %1</translation>
- </message>
- <message>
- <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
- <translation>Al ser la primera vez que se ejecuta el programa, puede elegir donde %1 almacenara sus datos</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Utilizar el directorio de datos predeterminado</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Utilizar un directorio de datos personalizado:</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Error: no ha podido crearse el directorio de datos especificado "%1".</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Error</translation>
- </message>
- <message numerus="yes">
- <source>%n GB of free space available</source>
- <translation><numerusform>%n GB de espacio libre</numerusform><numerusform>%n GB de espacio disponible</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>(of %n GB needed)</source>
- <translation><numerusform>(de %n GB necesitados)</numerusform><numerusform>(de %n GB requeridos)</numerusform></translation>
- </message>
-</context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Formulario</translation>
- </message>
- <message>
- <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation>Las transacciones recientes podrían no ser visibles todavía, por lo que el balance de la cartera podría ser incorrecto. Esta información será correcta una vez su cartera se haya terminado de sincronizar con la red bitcoin, como se detalla más abajo.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Número de bloques restantes</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Desconocido...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Hora del último bloque</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation>Progreso</translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation>Incremento del progreso por hora</translation>
- </message>
- <message>
- <source>calculating...</source>
- <translation>calculando...</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation>Tiempo estimado restante hasta sincronización completa</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Ocultar</translation>
- </message>
- <message>
- <source>Unknown. Syncing Headers (%1)...</source>
- <translation>Desconocido. Sincronizando cabeceras (%1)...</translation>
- </message>
-</context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Abrir URI...</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Abrir solicitud de pago a partir de un identificador URI o de un archivo</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Seleccionar archivo de sulicitud de pago</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Seleccionar el archivo de solicitud de pago para abrir</translation>
- </message>
-</context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Opciones</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Principal</translation>
- </message>
- <message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation>Iniciar automaticamente %1 al encender el sistema.</translation>
- </message>
- <message>
- <source>&amp;Start %1 on system login</source>
- <translation>&amp;Iniciar %1 al iniciar el sistema</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Tamaño de cache de la &amp;base de datos</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>Número de hilos de &amp;verificación de scripts</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Dirección IP del proxy (p. ej. IPv4: 127.0.0.1 / IPv6: ::1)</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 está cerrada. Cuando se activa esta opción, la aplicación sólo se cerrará después de seleccionar Salir en el menú.</translation>
- </message>
- <message>
- <source>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>Identificadores URL de terceros (por ejemplo, un explorador de bloques) que aparecen en la pestaña de transacciones como elementos del menú contextual. El %s en la URL es reemplazado por el valor hash de la transacción. Se pueden separar URL múltiples por una barra vertical |.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Opciones activas de consola de comandos que tienen preferencia sobre las opciones anteriores:</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Restablecer todas las opciones predeterminadas del cliente.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Restablecer opciones</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Red</translation>
- </message>
- <message>
- <source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = automático, &lt;0 = dejar libres ese número de núcleos)</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>&amp;Monedero</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Experto</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Habilitar funcionalidad de &amp;coin control</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 desactiva el gasto del cambio no confirmado, no se podrá usar el cambio de una transacción hasta que se alcance al menos una confirmación. Esto afecta también a cómo se calcula su saldo.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>&amp;Gastar 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>Abrir automáticamente el puerto del cliente Bitcoin en el router. Esta opción solo funciona si el router admite UPnP y está activado.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Mapear el puerto mediante &amp;UPnP</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Conectarse a la red Bitcoin a través de un proxy SOCKS5.</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Conectarse a través de proxy SOCKS5 (proxy predeterminado):</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>Dirección &amp;IP del proxy:</translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>&amp;Puerto:</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Puerto del servidor proxy (ej. 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation>Usado para alcanzar compañeros 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>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Conectar a la red Bitcoin mediante un proxy SOCKS5 por separado para los servicios ocultos de 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>Minimizar la ventana a la bandeja de iconos del sistema.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimizar a la bandeja en vez de a la barra de tareas</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>M&amp;inimizar al cerrar</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Interfaz</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>I&amp;dioma 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>El idioma de la interfaz de usuario puede establecerse aquí. Esta configuración tendrá efecto tras reiniciar %1.</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>Mostrar las cantidades en la &amp;unidad:</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Elegir la subdivisión predeterminada para mostrar cantidades en la interfaz y cuando se envían bitcoins.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Mostrar o no funcionalidad de Coin Control</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;Aceptar</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Cancelar</translation>
- </message>
- <message>
- <source>default</source>
- <translation>predeterminado</translation>
- </message>
- <message>
- <source>none</source>
- <translation>ninguna</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Confirme el restablecimiento de las opciones</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Se necesita reiniciar el cliente para activar los cambios.</translation>
- </message>
- <message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation>El cliente se cerrará. ¿Desea continuar?</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Opciones de configuración</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Error</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Este cambio exige el reinicio del cliente.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>La dirección proxy indicada es inválida.</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Formulario</translation>
- </message>
- <message>
- <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
- <translation>La información mostrada puede estar desactualizada. Su monedero se sincroniza automáticamente con la red Bitcoin después de que se haya establecido una conexión, pero este proceso aún no se ha completado.</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>De observación:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Disponible:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Su saldo disponible actual</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Pendiente:</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 de transacciones pendientes de confirmar y que aún no contribuye al saldo disponible</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>No madurado:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>Saldo recién minado que aún no ha madurado.</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Saldos</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Total:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Su saldo actual total</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>Su saldo actual en direcciones watch-only</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Gastable:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Transacciones recientes</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Transacciones sin confirmar en direcciones watch-only</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Saldo minado en direcciones watch-only que aún no ha madurado</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>Saldo total en las direcciones watch-only</translation>
- </message>
-</context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Fallo en la solicitud de pago</translation>
- </message>
- <message>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>No se puede iniciar bitcoin: encargado click-para-pagar</translation>
- </message>
- <message>
- <source>URI handling</source>
- <translation>Manejo de URI</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>La búsqueda de solicitud de pago URL es válida: %1</translation>
- </message>
- <message>
- <source>Invalid payment address %1</source>
- <translation>Dirección de pago inválida %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 no puede ser analizado! Esto puede ser causado por una dirección Bitcoin inválida o parametros URI mal formados.</translation>
- </message>
- <message>
- <source>Payment request file handling</source>
- <translation>Manejo del archivo de solicitud de pago</translation>
- </message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>¡El archivo de solicitud de pago no puede ser leído! Esto puede ser causado por un archivo de solicitud de pago inválido.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Solicitud de pago rechazada</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>La red de solicitud de pago no cimbina la red cliente.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Solicitud de pago caducada.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>La solicitud de pago no se ha iniciado.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Solicitudes de pago sin verificar a scripts de pago habitual no se soportan.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Solicitud de pago inválida.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Cantidad de pago solicitada de %1 es demasiado pequeña (considerado polvo).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Reembolsar desde %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Solicitud de pago de %1 es demasiado grande (%2 bytes, permitidos %3 bytes).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Fallo al comunicar con %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>¡La solicitud de pago no puede ser analizada!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Mala respuesta desde el servidor %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Fallo de solicitud de red</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Pago declarado</translation>
- </message>
-</context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>User Agent</translation>
- </message>
- <message>
- <source>Node/Service</source>
- <translation>Nodo/Servicio</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>
- <message>
- <source>Received</source>
- <translation>Recibido</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Cantidad</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Introducir una dirección Bitcoin (p. ej. %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>Ninguno</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>N/D</translation>
- </message>
- <message>
- <source>%1 ms</source>
- <translation>%1 ms</translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 y %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>%1 didn't yet exit safely...</source>
- <translation>%1 aún no ha salido de manera segura...</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>desconocido</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- <message>
- <source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Error: directorio especificado "%1" no existe.</translation>
- </message>
- <message>
- <source>Error: %1</source>
- <translation>Error: %1</translation>
- </message>
-</context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Guardar imagen...</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>&amp;Copiar imagen</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>Guardar código QR</translation>
- </message>
- <message>
- <source>PNG Image (*.png)</source>
- <translation>Imagen PNG (*.png)</translation>
- </message>
-</context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>N/D</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Versión del cliente</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Información</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Ventana de depuración</translation>
- </message>
- <message>
- <source>General</source>
- <translation>General</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>Utilizando la versión de BerkeleyDB</translation>
- </message>
- <message>
- <source>Datadir</source>
- <translation>Datadir</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Hora de inicio</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Red</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Nombre</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Número de conexiones</translation>
- </message>
- <message>
- <source>Block chain</source>
- <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>Piscina de Memoria</translation>
- </message>
- <message>
- <source>Current number of transactions</source>
- <translation>Número actual de transacciones</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Uso de memoria</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Recibido</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Enviado</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Pares</translation>
- </message>
- <message>
- <source>Banned peers</source>
- <translation>Peers Bloqueados</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <translation>Seleccionar un par para ver su 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>
- <message>
- <source>Version</source>
- <translation>Versión</translation>
- </message>
- <message>
- <source>Starting Block</source>
- <translation>Importando bloques...</translation>
- </message>
- <message>
- <source>Synced Headers</source>
- <translation>Sincronizar Cabeceras</translation>
- </message>
- <message>
- <source>Synced Blocks</source>
- <translation>Bloques Sincronizados</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>User Agent</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>
- <message>
- <source>Decrease font size</source>
- <translation>Disminuir tamaño de letra</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation>Aumentar tamaño de letra</translation>
- </message>
- <message>
- <source>Services</source>
- <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>
- <message>
- <source>Last Send</source>
- <translation>Ultimo envío</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Ultima recepción</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Ping</translation>
- </message>
- <message>
- <source>The duration of a currently outstanding ping.</source>
- <translation>La duración de un ping actualmente en proceso.</translation>
- </message>
- <message>
- <source>Ping Wait</source>
- <translation>Espera de Ping</translation>
- </message>
- <message>
- <source>Min Ping</source>
- <translation>Ping mín.</translation>
- </message>
- <message>
- <source>Time Offset</source>
- <translation>Desplazamiento de tiempo</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Hora del último bloque</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Abrir</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Consola</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Tráfico de Red</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Total:</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Entrante:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Saliente:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Archivo de registro de depuración</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Borrar consola</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;hora</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;día</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;semana</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;año</translation>
- </message>
- <message>
- <source>&amp;Disconnect</source>
- <translation>&amp;Desconectar</translation>
- </message>
- <message>
- <source>Ban for</source>
- <translation>Bloqueado por</translation>
- </message>
- <message>
- <source>&amp;Unban</source>
- <translation>&amp;Desbanear</translation>
- </message>
- <message>
- <source>Welcome to the %1 RPC console.</source>
- <translation>Bienvenido a la consola RPC %1.</translation>
- </message>
- <message>
- <source>Network activity disabled</source>
- <translation>Actividad de red desactivada</translation>
- </message>
- <message>
- <source>(node id: %1)</source>
- <translation>(nodo: %1)</translation>
- </message>
- <message>
- <source>via %1</source>
- <translation>via %1</translation>
- </message>
- <message>
- <source>never</source>
- <translation>nunca</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Entrante</translation>
- </message>
- <message>
- <source>Outbound</source>
- <translation>Saliente</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>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>Cantidad</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Etiqueta:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>Mensaje:</translation>
- </message>
- <message>
- <source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
- <translation>Un mensaje opcional para adjuntar a la solicitud de pago, que se muestra cuando se abre la solicitud. Nota: El mensaje no se enviará con el pago por la red Bitcoin.</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation>Etiqueta opcional para asociar con la nueva dirección de recepción.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Utilice este formulario para solicitar pagos. Todos los campos son &lt;b&gt;opcionales&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation>Para solicitar una cantidad opcional. Deje este vacío o cero para no solicitar una cantidad específica.</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Vaciar todos los campos del formulario.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Vaciar</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>Historial de pagos solicitados</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Solicitar pago</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Muestra la petición seleccionada (También doble clic)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Mostrar</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Borrar de la lista las direcciónes actualmente seleccionadas</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Eliminar</translation>
- </message>
- <message>
- <source>Copy URI</source>
- <translation>Copiar URL</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copiar capa</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Copiar imagen</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiar cantidad</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>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Copiar &amp;Dirección</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>Guardar Imagen...</translation>
- </message>
- <message>
- <source>Request payment to %1</source>
- <translation>Solicitar pago a %1</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation>Información de 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>Monedero</translation>
- </message>
- <message>
- <source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation>URI resultante demasiado grande, trate de reducir el texto de etiqueta / mensaje.</translation>
- </message>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation>Fallo al codificar URI en código QR.</translation>
- </message>
-</context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Fecha</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mensaje</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sin etiqueta)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation>(no hay mensaje)</translation>
- </message>
- <message>
- <source>(no amount requested)</source>
- <translation>(no hay solicitud de cantidad)</translation>
- </message>
- <message>
- <source>Requested</source>
- <translation>Solicitado</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Enviar bitcoins</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Características de Coin Control</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Entradas...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>Seleccionado automáticamente</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Fondos insuficientes!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Cantidad:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Cuantía:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Tasa:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Después de tasas:</translation>
- </message>
- <message>
- <source>Change:</source>
- <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>Si se marca esta opción pero la dirección de cambio está vacía o es inválida, el cambio se enviará a una nueva dirección recién generada.</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Dirección propia</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Comisión de Transacción:</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Elija...</translation>
- </message>
- <message>
- <source>collapse fee-settings</source>
- <translation>Colapsar ajustes de cuota</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>por kilobyte</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Ocultar</translation>
- </message>
- <message>
- <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
- <translation>Pagando solamente la cuota mínima es correcto, siempre y cuando haya menos volumen de transacciones que el espacio en los bloques. Pero tenga en cuenta que esto puede terminar en una transacción nunca confirmada, una vez que haya más demanda para transacciones Bitcoin que la red pueda procesar.</translation>
- </message>
- <message>
- <source>(read the tooltip)</source>
- <translation>(leer la sugerencia)</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Recomendado:</translation>
- </message>
- <message>
- <source>Custom:</source>
- <translation>Personalizado:</translation>
- </message>
- <message>
- <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(Tarifa inteligente no inicializado aún. Esto generalmente lleva a pocos bloques...)</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Enviar a múltiples destinatarios de una vez</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>Añadir &amp;destinatario</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Vaciar todos los campos del formulario</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Polvo:</translation>
- </message>
- <message>
- <source>Confirmation time target:</source>
- <translation>Tiempo objetivo de confirmación:</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Vaciar &amp;todo</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Saldo:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Confirmar el envío</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>&amp;Enviar</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copiar cantidad</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiar cantidad</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copiar cuota</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Copiar después de couta</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copiar bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copiar polvo</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copiar cambio</translation>
- </message>
- <message>
- <source>%1 to %2</source>
- <translation>%1 a %2</translation>
- </message>
- <message>
- <source>Are you sure you want to send?</source>
- <translation>¿Seguro que quiere enviar?</translation>
- </message>
- <message>
- <source>or</source>
- <translation>o</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Comisión de transacción</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation>Confirmar enviar monedas</translation>
- </message>
- <message>
- <source>The recipient address is not valid. Please recheck.</source>
- <translation>La dirección de destinatario no es válida. Por favor revísela.</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation>La cantidad a pagar debe de ser mayor que 0.</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation>La cantidad excede su saldo.</translation>
- </message>
- <message>
- <source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>El total excede su saldo cuando la cuota de transacción de %1 es incluida.</translation>
- </message>
- <message>
- <source>Duplicate address found: addresses should only be used once each.</source>
- <translation>Dirección duplicada encontrada: la dirección sólo debería ser utilizada una vez por cada uso.</translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation>¡Falló la creación de transacción!</translation>
- </message>
- <message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Esta transacción fue rechazada por la siguiente razón: %1</translation>
- </message>
- <message>
- <source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation>Una couta mayor que %1 se considera una cuota irracionalmente alta.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Solicitud de pago caducada.</translation>
- </message>
- <message>
- <source>Pay only the required fee of %1</source>
- <translation>Pagar únicamente la cuota solicitada de %1</translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation>Alerta: dirección Bitcoin inválida</translation>
- </message>
- <message>
- <source>Warning: Unknown change address</source>
- <translation>Alerta: dirección cambiada desconocida</translation>
- </message>
- <message>
- <source>Confirm custom change address</source>
- <translation>Confirmar dirección de cambio personalizada</translation>
- </message>
- <message>
- <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
- <translation>La dirección que seleccionó para el cambio no es parte de esta cartera. Parte o la totalidad de los fondos de su cartera podrían ser enviados a esta dirección. ¿Está seguro?</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sin etiqueta)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>Ca&amp;ntidad:</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>&amp;Pagar a:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Etiqueta:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Escoger direcciones previamente usadas</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Esto es un pago ordinario.</translation>
- </message>
- <message>
- <source>The Bitcoin address to send the payment to</source>
- <translation>Dirección Bitcoin a la que enviar el pago</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Pegar dirección desde portapapeles</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Eliminar esta transacción</translation>
- </message>
- <message>
- <source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source>
- <translation>La cuota será deducida de la cantidad que sea mandada. El destinatario recibirá menos bitcoins de los que entres en el </translation>
- </message>
- <message>
- <source>S&amp;ubtract fee from amount</source>
- <translation>Restar comisiones a la cantidad</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Mensaje:</translation>
- </message>
- <message>
- <source>This is an unauthenticated payment request.</source>
- <translation>Esta es una petición de pago no autentificada.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation>Esta es una petición de pago autentificada.</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation>
- </message>
- <message>
- <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
- <translation>Un mensaje que se adjuntó a la bitcoin: URL que será almacenada con la transacción para su referencia. Nota: Este mensaje no se envía a través de la red Bitcoin.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Paga a:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Memo:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Introduzca una etiqueta para esta dirección para añadirla a su agenda</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Sí</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>%1 is shutting down...</source>
- <translation>%1 se esta cerrando...</translation>
- </message>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>No apague el equipo hasta que desaparezca esta ventana.</translation>
- </message>
-</context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Firmas - Firmar / verificar un mensaje</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Firmar mensaje</translation>
- </message>
- <message>
- <source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
- <translation>Puede firmar los mensajes con sus direcciones para demostrar que las posee. Tenga cuidado de no firmar cualquier cosa de manera vaga o aleatoria, pues los ataques de phishing pueden tratar de engañarle firmando su identidad a través de ellos. Sólo firme declaraciones totalmente detalladas con las que usted esté de acuerdo.</translation>
- </message>
- <message>
- <source>The Bitcoin address to sign the message with</source>
- <translation>Dirección Bitcoin con la que firmar el mensaje</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Escoger dirección previamente usada</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Pegar dirección desde portapapeles</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Introduzca el mensaje que desea firmar aquí</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Firma</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Copiar la firma actual al portapapeles del sistema</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Firmar el mensaje para demostrar que se posee esta dirección Bitcoin</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Firmar &amp;mensaje</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Vaciar todos los campos de la firma de mensaje</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Vaciar &amp;todo</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Verificar mensaje</translation>
- </message>
- <message>
- <source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
- <translation>Introduzca la dirección para la firma, el mensaje (asegurándose de copiar tal cual los saltos de línea, espacios, tabulaciones, etc.) y la firma a continuación para verificar el mensaje. Tenga cuidado de no asumir más información de lo que dice el propio mensaje firmado para evitar fraudes basados en ataques de tipo man-in-the-middle. </translation>
- </message>
- <message>
- <source>The Bitcoin address the message was signed with</source>
- <translation>La dirección Bitcoin con la que se firmó el mensaje</translation>
- </message>
- <message>
- <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Verificar el mensaje para comprobar que fue firmado con la dirección Bitcoin indicada</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Verificar &amp;mensaje</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Vaciar todos los campos de la verificación de mensaje</translation>
- </message>
- <message>
- <source>Click "Sign Message" to generate signature</source>
- <translation>Click en "Fírmar mensaje" para generar una firma</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation>La dirección introducida no es válida.</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Por favor revise la dirección e inténtelo de nuevo.</translation>
- </message>
- <message>
- <source>The entered address does not refer to a key.</source>
- <translation>La dirección introducida no remite a una clave.</translation>
- </message>
- <message>
- <source>Wallet unlock was cancelled.</source>
- <translation>El desbloqueo del monedero fue cancelado.</translation>
- </message>
- <message>
- <source>Private key for the entered address is not available.</source>
- <translation>La clave privada de la dirección introducida no está disponible.</translation>
- </message>
- <message>
- <source>Message signing failed.</source>
- <translation>Falló la firma del mensaje.</translation>
- </message>
- <message>
- <source>Message signed.</source>
- <translation>Mensaje firmado.</translation>
- </message>
- <message>
- <source>The signature could not be decoded.</source>
- <translation>La firma no pudo descodificarse.</translation>
- </message>
- <message>
- <source>Please check the signature and try again.</source>
- <translation>Por favor compruebe la firma y pruebe de nuevo.</translation>
- </message>
- <message>
- <source>The signature did not match the message digest.</source>
- <translation>La firma no se combinó con el mensaje.</translation>
- </message>
- <message>
- <source>Message verification failed.</source>
- <translation>Falló la verificación del mensaje.</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation>Mensaje verificado.</translation>
- </message>
-</context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KB/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Open until %1</source>
- <translation>Abierto hasta %1</translation>
- </message>
- <message>
- <source>conflicted with a transaction with %1 confirmations</source>
- <translation>Hay un conflicto con la traducción de las confirmaciones %1</translation>
- </message>
- <message>
- <source>0/unconfirmed, %1</source>
- <translation>0/no confirmado, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation>en el equipo de memoria</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation>no en el equipo de memoria</translation>
- </message>
- <message>
- <source>abandoned</source>
- <translation>abandonado</translation>
- </message>
- <message>
- <source>%1/unconfirmed</source>
- <translation>%1/no confirmado</translation>
- </message>
- <message>
- <source>%1 confirmations</source>
- <translation>confirmaciones %1</translation>
- </message>
- <message>
- <source>Status</source>
- <translation>Estado</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Fecha</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Fuente</translation>
- </message>
- <message>
- <source>Generated</source>
- <translation>Generado</translation>
- </message>
- <message>
- <source>From</source>
- <translation>Desde</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>desconocido</translation>
- </message>
- <message>
- <source>To</source>
- <translation>Para</translation>
- </message>
- <message>
- <source>own address</source>
- <translation>dirección propia</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>de observación</translation>
- </message>
- <message>
- <source>label</source>
- <translation>etiqueta</translation>
- </message>
- <message>
- <source>Credit</source>
- <translation>Credito</translation>
- </message>
- <message>
- <source>not accepted</source>
- <translation>no aceptada</translation>
- </message>
- <message>
- <source>Debit</source>
- <translation>Enviado</translation>
- </message>
- <message>
- <source>Total debit</source>
- <translation>Total enviado</translation>
- </message>
- <message>
- <source>Total credit</source>
- <translation>Total recibido</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Comisión de transacción</translation>
- </message>
- <message>
- <source>Net amount</source>
- <translation>Cantidad neta</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mensaje</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Comentario</translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation>Identificador de transacción (ID)</translation>
- </message>
- <message>
- <source>Transaction total size</source>
- <translation>Tamaño total de la transacción</translation>
- </message>
- <message>
- <source>Output index</source>
- <translation>Indice de salida</translation>
- </message>
- <message>
- <source>Merchant</source>
- <translation>Vendedor</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>Los bitcoins generados deben madurar %1 bloques antes de que puedan gastarse. Cuando generó este bloque, se transmitió a la red para que se añadiera a la cadena de bloques. Si no consigue entrar en la cadena, su estado cambiará a "no aceptado" y ya no se podrá gastar. Esto puede ocurrir ocasionalmente si otro nodo genera un bloque a pocos segundos del suyo.</translation>
- </message>
- <message>
- <source>Debug information</source>
- <translation>Información de depuración</translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation>Transacción</translation>
- </message>
- <message>
- <source>Inputs</source>
- <translation>entradas</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantidad</translation>
- </message>
- <message>
- <source>true</source>
- <translation>verdadero</translation>
- </message>
- <message>
- <source>false</source>
- <translation>falso</translation>
- </message>
-</context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Esta ventana muestra información detallada sobre la transacción</translation>
- </message>
- <message>
- <source>Details for %1</source>
- <translation>Detalles para %1</translation>
- </message>
-</context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Fecha</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tipo</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Abierto hasta %1</translation>
- </message>
- <message>
- <source>Unconfirmed</source>
- <translation>Sin confirmar</translation>
- </message>
- <message>
- <source>Abandoned</source>
- <translation>Abandonado</translation>
- </message>
- <message>
- <source>Confirming (%1 of %2 recommended confirmations)</source>
- <translation>Confirmando (%1 de %2 confirmaciones recomendadas)</translation>
- </message>
- <message>
- <source>Confirmed (%1 confirmations)</source>
- <translation>Confirmado (%1 confirmaciones)</translation>
- </message>
- <message>
- <source>Conflicted</source>
- <translation>En conflicto</translation>
- </message>
- <message>
- <source>Immature (%1 confirmations, will be available after %2)</source>
- <translation>No disponible (%1 confirmaciones. Estarán disponibles al cabo de %2)</translation>
- </message>
- <message>
- <source>Generated but not accepted</source>
- <translation>Generado pero no aceptado</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Recibido con</translation>
- </message>
- <message>
- <source>Received from</source>
- <translation>Recibidos de</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Enviado a</translation>
- </message>
- <message>
- <source>Payment to yourself</source>
- <translation>Pago proprio</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Minado</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>de observación</translation>
- </message>
- <message>
- <source>(n/a)</source>
- <translation>(nd)</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sin etiqueta)</translation>
- </message>
- <message>
- <source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>Estado de transacción. Pasa el ratón sobre este campo para ver el número de confirmaciones.</translation>
- </message>
- <message>
- <source>Date and time that the transaction was received.</source>
- <translation>Fecha y hora en que se recibió la transacción.</translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation>Tipo de transacción.</translation>
- </message>
- <message>
- <source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation>Si una dirección watch-only está involucrada en esta transacción o no.</translation>
- </message>
- <message>
- <source>User-defined intent/purpose of the transaction.</source>
- <translation>Descripción de la transacción definido por el usuario.</translation>
- </message>
- <message>
- <source>Amount removed from or added to balance.</source>
- <translation>Cantidad retirada o añadida al saldo.</translation>
- </message>
-</context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Todo</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Hoy</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>Esta semana</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>Este mes</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Mes pasado</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Este año</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Rango...</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Recibido con</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Enviado a</translation>
- </message>
- <message>
- <source>To yourself</source>
- <translation>A usted mismo</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Minado</translation>
- </message>
- <message>
- <source>Other</source>
- <translation>Otra</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation>Cantidad mínima</translation>
- </message>
- <message>
- <source>Abandon transaction</source>
- <translation>Transacción abandonada</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Copiar ubicación</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copiar capa</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiar cantidad</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copiar ID de transacción</translation>
- </message>
- <message>
- <source>Copy raw transaction</source>
- <translation>Copiar transacción raw</translation>
- </message>
- <message>
- <source>Copy full transaction details</source>
- <translation>Copiar todos los detalles de la transacción</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Editar etiqueta</translation>
- </message>
- <message>
- <source>Show transaction details</source>
- <translation>Mostrar detalles de la transacción</translation>
- </message>
- <message>
- <source>Export Transaction History</source>
- <translation>Exportar historial de transacciones</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Archivo separado de coma (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmado</translation>
- </message>
- <message>
- <source>Watch-only</source>
- <translation>De observación</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Fecha</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tipo</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Dirección</translation>
- </message>
- <message>
- <source>ID</source>
- <translation>ID</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Falló la exportación</translation>
- </message>
- <message>
- <source>There was an error trying to save the transaction history to %1.</source>
- <translation>Ha habido un error al intentar guardar la transacción con %1.</translation>
- </message>
- <message>
- <source>Exporting Successful</source>
- <translation>Exportación finalizada</translation>
- </message>
- <message>
- <source>The transaction history was successfully saved to %1.</source>
- <translation>La transacción ha sido guardada en %1.</translation>
- </message>
- <message>
- <source>Range:</source>
- <translation>Rango:</translation>
- </message>
- <message>
- <source>to</source>
- <translation>para</translation>
- </message>
-</context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- <message>
- <source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Unidad en la que se muestran las cantidades. Haga clic para seleccionar otra unidad.</translation>
- </message>
-</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>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Enviar</translation>
- </message>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportar</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportar a un archivo los datos de esta pestaña</translation>
- </message>
- <message>
- <source>Backup Wallet</source>
- <translation>Copia de seguridad del monedero</translation>
- </message>
- <message>
- <source>Wallet Data (*.dat)</source>
- <translation>Datos de monedero (*.dat)</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>La copia de seguridad ha fallado</translation>
- </message>
- <message>
- <source>There was an error trying to save the wallet data to %1.</source>
- <translation>Ha habido un error al intentar guardar los datos del monedero en %1.</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Se ha completado con éxito la copia de respaldo</translation>
- </message>
- <message>
- <source>The wallet data was successfully saved to %1.</source>
- <translation>Los datos del monedero se han guardado con éxito en %1.</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation>La Poda se ha configurado por debajo del minimo de %d MiB. Por favor utiliza un valor mas alto.</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>Poda: la ultima sincronizacion de la cartera sobrepasa los datos podados. Necesitas reindexar con -reindex (o descargar la cadena de bloques de nuevo en el caso de un nodo podado)</translation>
- </message>
- <message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Nos es posible re-escanear en modo podado.Necesitas utilizar -reindex el cual descargara la cadena de bloques al completo de nuevo.</translation>
- </message>
- <message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Un error interno fatal ocurrió, ver debug.log para detalles</translation>
- </message>
- <message>
- <source>Pruning blockstore...</source>
- <translation>Poda blockstore ...</translation>
- </message>
- <message>
- <source>Unable to start HTTP server. See debug log for details.</source>
- <translation>No se ha podido comenzar el servidor HTTP. Ver debug log para detalles.</translation>
- </message>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>The %s developers</source>
- <translation>Los %s desarrolladores</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 ya se está ejecutando.</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 leyendo %s!. Todas las claves se han leido correctamente, pero los datos de transacciones o la libreta de direcciones pueden faltar o ser incorrectos.</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, compruebe si la fecha y hora en su computadora son correctas! Si su reloj esta mal, %s no trabajara correctamente. </translation>
- </message>
- <message>
- <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <translation>Contribuya si encuentra %s de utilidad. Visite %s para mas información acerca del programa.</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 datos de bloques contiene un bloque que parece ser del futuro. Esto puede ser porque la fecha y hora de tu ordenador están mal ajustados. Reconstruye la base de datos de bloques solo si estas seguro de que la fecha y hora de tu ordenador estan ajustados correctamente.</translation>
- </message>
- <message>
- <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
- <translation>No es posible reconstruir la base de datos a un estado anterior. Debe descargar de nuevo la cadena de bloques.</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupto. Fracasó la recuperacion</translation>
- </message>
- <message>
- <source>-maxmempool must be at least %d MB</source>
- <translation>-maxmempool debe ser por lo menos de %d MB</translation>
- </message>
- <message>
- <source>Cannot resolve -%s address: '%s'</source>
- <translation>No se puede resolver -%s direccion: '%s'</translation>
- </message>
- <message>
- <source>Change index out of range</source>
- <translation>Cambio de indice fuera de rango</translation>
- </message>
- <message>
- <source>Copyright (C) %i-%i</source>
- <translation>Copyright (C) %i-%i</translation>
- </message>
- <message>
- <source>Corrupted block database detected</source>
- <translation>Corrupción de base de datos de bloques detectada.</translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>¿Quieres reconstruir la base de datos de bloques ahora?</translation>
- </message>
- <message>
- <source>Error initializing block database</source>
- <translation>Error al inicializar la base de datos de bloques</translation>
- </message>
- <message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Error al inicializar el entorno de la base de datos del monedero %s</translation>
- </message>
- <message>
- <source>Error loading %s</source>
- <translation>Error cargando %s</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet corrupted</source>
- <translation>Error cargando %s: Monedero dañado</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet requires newer version of %s</source>
- <translation>Error cargando %s: Monedero requiere un versión mas reciente de %s</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Error cargando base de datos de bloques</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Error al abrir base de datos de bloques.</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Error: ¡Espacio en disco bajo!</translation>
- </message>
- <message>
- <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>Ha fallado la escucha en todos los puertos. Use -listen=0 si desea esto.</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>Importando...</translation>
- </message>
- <message>
- <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>Incorrecto o bloque de génesis no encontrado. Datadir equivocada para la red?</translation>
- </message>
- <message>
- <source>Initialization sanity check failed. %s is shutting down.</source>
- <translation>La inicialización de la verificación de validez falló. Se está apagando %s.</translation>
- </message>
- <message>
- <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>Cantidad no valida para -%s=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>Cantidad inválida para -fallbackfee=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Loading banlist...</source>
- <translation>Cargando banlist...</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>No hay suficientes descriptores de archivo disponibles. </translation>
- </message>
- <message>
- <source>Prune cannot be configured with a negative value.</source>
- <translation>Pode no se puede configurar con un valor negativo.</translation>
- </message>
- <message>
- <source>Prune mode is incompatible with -txindex.</source>
- <translation>El modo recorte es incompatible con -txindex.</translation>
- </message>
- <message>
- <source>Rewinding blocks...</source>
- <translation>Verificando bloques...</translation>
- </message>
- <message>
- <source>The source code is available from %s.</source>
- <translation>El código fuente esta disponible desde %s.</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer. %s is probably already running.</source>
- <translation>No se ha podido conectar con %s en este equipo. %s es posible que este todavia en ejecución.</translation>
- </message>
- <message>
- <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
- <translation>El argumento -benchmark no es soportado y ha sido ignorado, utiliza -debug=bench</translation>
- </message>
- <message>
- <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
- <translation>Parámetros no compatibles -debugnet ignorados , use -debug = red.</translation>
- </message>
- <message>
- <source>Unsupported argument -tor found, use -onion.</source>
- <translation>Parámetros no compatibles -tor encontrados, use -onion .</translation>
- </message>
- <message>
- <source>User Agent comment (%s) contains unsafe characters.</source>
- <translation>El comentario del Agente de Usuario (%s) contiene caracteres inseguros.</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>Es necesario reescribir el monedero: reiniciar %s para completar</translation>
- </message>
- <message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Error: la escucha para conexiones entrantes falló (la escucha regresó el 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>Cantidad no válida para -maxtxfee=&lt;amount&gt;: '%s' (debe ser por lo menos la cuota de comisión mínima de %s para prevenir transacciones atascadas)</translation>
- </message>
- <message>
- <source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>Monto de transacción muy pequeña luego de la deducción por comisión</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>Necesitas 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>Error reading from database, shutting down.</source>
- <translation>Error al leer la base de datos, cerrando.</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Información</translation>
- </message>
- <message>
- <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation>Cantidad inválida para -paytxfee=&lt;amount&gt;: '%s' (debe ser por lo menos %s)</translation>
- </message>
- <message>
- <source>Invalid netmask specified in -whitelist: '%s'</source>
- <translation>Máscara de red inválida especificada en -whitelist: '%s'</translation>
- </message>
- <message>
- <source>Need to specify a port with -whitebind: '%s'</source>
- <translation>Necesita especificar un puerto con -whitebind: '%s'</translation>
- </message>
- <message>
- <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <translation>Reduciendo -maxconnections de %d a %d, debido a limitaciones del sistema.</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Transacción falló</translation>
- </message>
- <message>
- <source>The transaction amount is too small to pay the fee</source>
- <translation>Cantidad de la transacción demasiado pequeña para pagar la comisión</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>Este software es experimental.</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Cantidad de la transacción demasiado pequeña</translation>
- </message>
- <message>
- <source>Transaction too large for fee policy</source>
- <translation>Operación demasiado grande para la política de tasas</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Transacción demasiado grande, intenta dividirla en varias.</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation>No es posible conectar con %s en este sistema (bind ha dado el error %s)</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Aviso</translation>
- </message>
- <message>
- <source>Warning: unknown new rules activated (versionbit %i)</source>
- <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 ajuste muy elevado! Comisiones muy grandes podrían ser pagadas en una única transaccion.</translation>
- </message>
- <message>
- <source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation>Esta es la comisión que debe pagar cuando la estimación de comisión no esta disponible.</translation>
- </message>
- <message>
- <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <translation>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>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
- <translation>Error: argumento -socks encontrado. El ajuste de la versión SOCKS ya no es posible, sólo proxies SOCKS5 son compatibles.</translation>
- </message>
- <message>
- <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
- <translation>El argumento no soportado -whitelistalwaysrelay ha sido ignorado, utiliza -whitelistrelay y/o -whitelistforcerelay.</translation>
- </message>
- <message>
- <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
- <translation>Advertencia: Se están minando versiones de bloques desconocidas! Es posible que normas desconocidas estén activas</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>Aviso: fichero 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 es demasiado alto!</translation>
- </message>
- <message>
- <source>Starting network threads...</source>
- <translation>Iniciando funciones de red...</translation>
- </message>
- <message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Esta es la comisión minima que paga en cada transacción.</translation>
- </message>
- <message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Esta es la comisión que pagará si envia la transacción.</translation>
- </message>
- <message>
- <source>Transaction amounts must not be negative</source>
- <translation>Las cantidades de las transacciones no pueden ser negativas.</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>La transacción debe tener al menos un beneficiario</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>La red especificada en -onlynet '%s' es desconocida</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Fondos insuficientes</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Cargando el índice de bloques...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Cargando monedero...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>No se puede cambiar a una versión mas antigua el monedero</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Reexplorando...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Se terminó de cargar</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Error</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts
index a6dcacd3b7..acb7f0dc3d 100644
--- a/src/qt/locale/bitcoin_es_MX.ts
+++ b/src/qt/locale/bitcoin_es_MX.ts
@@ -306,10 +306,23 @@
<translation>Actividad de red deshabilitada.</translation>
</message>
<message>
+ <source>Click to enable network activity again.</source>
+ <translation> 
+Haga clic para habilitar la actividad de red nuevamente.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Sincronizar encabezados (%1%) ...</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>Reindexando bloques en el disco...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>El proxy está &lt;b&gt;habilitado&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Enviar monedas a una dirección Bitcoin</translation>
</message>
@@ -322,14 +335,6 @@
<translation>Cambiar la contraseña usada para la encriptación de la cartera</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Depurar ventana</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abrir consola de depuración y diagnostico</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verificar mensaje...</translation>
</message>
@@ -358,6 +363,10 @@
<translation>Firme mensajes con sus direcciones de Bitcoin para demostrar que los posee</translation>
</message>
<message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Verifique los mensajes para asegurarse de que se firmaron con direcciones de Bitcoin especificadas.</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Archivo</translation>
</message>
@@ -374,6 +383,12 @@
<translation>Pestañas</translation>
</message>
<message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation> 
+Solicitar pagos (genera códigos QR y bitcoin: URI)
+ </translation>
+ </message>
+ <message>
<source>&amp;Command-line options</source>
<translation>opciones de la &amp;Linea de comandos</translation>
</message>
@@ -453,10 +468,58 @@
<translation>Confirmado </translation>
</message>
<message>
+ <source>Copy address</source>
+ <translation>Copiar dirección </translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar capa </translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>copiar monto</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copiar identificación de la transacción. </translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Copiar cuota</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Copiar después de cuota</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Copiar bytes</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Copiar cambio</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>si</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>no</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>(change)</source>
+ <translation>cambio</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
</context>
@@ -477,7 +540,27 @@
<source>&amp;Address</source>
<translation>&amp;Dirección</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Nueva dirección de envío</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Editar dirección de recepción</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Editar dirección de envío</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se puede desbloquear la cartera</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>La generación de la nueva clave fallo</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
@@ -492,10 +575,6 @@
<translation>versión</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>Command-line options</source>
<translation>opciones de la Linea de comandos</translation>
</message>
@@ -572,10 +651,6 @@
</context>
<context>
<name>RPCConsole</name>
- <message>
- <source>Debug window</source>
- <translation>Depurar ventana</translation>
- </message>
</context>
<context>
<name>ReceiveCoinsDialog</name>
@@ -603,7 +678,15 @@
<source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
<translation>Monto opcional a solicitar. Dejarlo vacion o en cero no solicita un monto especifico.</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar capa </translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>copiar monto</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -623,6 +706,10 @@
<translation>Etiqueta</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Mensaje</translation>
+ </message>
+ <message>
<source>Wallet</source>
<translation>Cartera</translation>
</message>
@@ -638,6 +725,10 @@
<translation>Etiqueta</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Mensaje</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
@@ -685,6 +776,54 @@
<translation>Confirme la acción de enviar</translation>
</message>
<message>
+ <source>Copy quantity</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>copiar monto</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Copiar cuota</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Copiar después de cuota</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Copiar bytes</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Copiar cambio</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Confirme para enviar monedas</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>El monto a pagar debe ser mayor a 0</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>¡La creación de la transación falló!</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Advertencia: Dirección de Bitcoin invalida</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Advertencia: Cambio de dirección desconocido</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
@@ -704,10 +843,6 @@
<translation>&amp;Etiqueta</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Este es un pago normal</translation>
- </message>
- <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -733,9 +868,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
<message>
<source>Do not shut down the computer until this window disappears.</source>
@@ -767,14 +899,58 @@
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>Abrir hasta %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/No confirmado</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 confirmaciones</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Estado</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Fecha</translation>
</message>
<message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>desconocido</translation>
</message>
<message>
+ <source>To</source>
+ <translation>Para</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>etiqueta</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mensaje</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Comentario</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transacción</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Monto</translation>
</message>
@@ -793,17 +969,137 @@
<translation>Fecha</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Tipo</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Etiqueta</translation>
</message>
<message>
+ <source>Open until %1</source>
+ <translation>Abrir hasta %1</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Confimado (%1 confirmaciones)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Generado pero no aprovado</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Recibido con</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Enviar a</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Pagar a si mismo</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minado </translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n/a)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Fecha y hora en que la transacción fue recibida </translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Escriba una transacción</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Cantidad removida del saldo o agregada </translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Todo</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Hoy</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Esta semana </translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Este mes </translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>El mes pasado </translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Este año</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Recibido con</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Enviar a</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Para ti mismo</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minado </translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Otro</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Monto minimo </translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Copiar dirección </translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar capa </translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>copiar monto</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copiar identificación de la transacción. </translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Editar capa </translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>Exportar el historial de transacción</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Arhchivo separado por comas (*.csv)</translation>
</message>
@@ -816,6 +1112,10 @@
<translation>Fecha</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Tipo</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Etiqueta</translation>
</message>
@@ -824,10 +1124,30 @@
<translation>Dirección</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>Exportación Fallida</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>Ocurrio un error intentando guardar el historial de transaciones a %1</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Exportacion satisfactoria</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>el historial de transaciones ha sido guardado exitosamente en %1</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>Para</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
@@ -836,7 +1156,11 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>No se há cargado la cartera.</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
@@ -854,6 +1178,14 @@
<source>Export the data in the current tab to a file</source>
<translation>Exportar la información en la pestaña actual a un archivo</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>The wallet data was successfully saved to %1.</source>
+ <translation>La información de la cartera fué guardada exitosamente a %1</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_es_VE.ts b/src/qt/locale/bitcoin_es_VE.ts
index 96b55d8dda..2dd3247a5f 100644
--- a/src/qt/locale/bitcoin_es_VE.ts
+++ b/src/qt/locale/bitcoin_es_VE.ts
@@ -83,7 +83,7 @@
</message>
<message>
<source>Export Address List</source>
- <translation>Exportar la Lista de Direcciones </translation>
+ <translation>Exportar la Lista de Direcciones</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
@@ -171,7 +171,43 @@
<source>Wallet encrypted</source>
<translation>Monedero cifrado</translation>
</message>
- </context>
+ <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>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Encriptado de monedero fallido</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Encriptación de billetera fallida debido a un error interno. Tu billetera no fue encriptada.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Las frases secretas introducidas no concuerdan.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Desbloqueo de billetera fallido</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>La frase secreta introducida para la desencriptación de la billetera fué incorrecta.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Desencriptación de billetera fallida</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>La frase secreta de la billetera fué cambiada exitosamente.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Aviso: El bloqueo de mayúsculas está activado.</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
</context>
@@ -254,14 +290,6 @@
<translation>Cambiar la contraseña utilizada para el cifrado del monedero</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Ventana de &amp;depuración</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abrir la consola de depuración y diagnóstico</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verificar mensaje...</translation>
</message>
@@ -322,10 +350,6 @@
<translation>Muestra la lista de direcciones de recepción y etiquetas</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abrir un bitcoin: URI o petición de pago</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Opciones de linea de comando</translation>
</message>
@@ -358,6 +382,14 @@
<translation>Actualizado</translation>
</message>
<message>
+ <source>Close wallet</source>
+ <translation>Cerrar monedero</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation>Monederos no disponibles</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;Ventana</translation>
</message>
@@ -453,6 +485,30 @@
<translation>Confirmado</translation>
</message>
<message>
+ <source>Copy address</source>
+ <translation>Copiar dirección</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copiar ID de la transacción</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Bloqueo no gastado</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Desbloqueo no gastado</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation>Copiar cantidad</translation>
</message>
@@ -465,10 +521,18 @@
<translation>Copiar bytes</translation>
</message>
<message>
+ <source>Copy dust</source>
+ <translation>Copiar dust</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation>Copiar cambio</translation>
</message>
<message>
+ <source>(%1 locked)</source>
+ <translation>(%1 bloqueado)</translation>
+ </message>
+ <message>
<source>yes</source>
<translation>si</translation>
</message>
@@ -477,10 +541,22 @@
<translation>no</translation>
</message>
<message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Puede variar +/- %1 satoshi(s) por entrada.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>Cambio desde %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(cambio)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
</context>
@@ -509,7 +585,31 @@
<source>&amp;Address</source>
<translation>&amp;Dirección</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Nueva dirección de envío</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Editar dirección de envío</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Editar dirección de envío</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>La dirección introducida "%1" no es una dirección Bitcoin válida.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se pudo desbloquear la billetera.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Creación de la nueva llave fallida</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
@@ -540,10 +640,6 @@
<translation>versión</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>Command-line options</source>
<translation>Opciones de la línea de órdenes</translation>
</message>
@@ -593,22 +689,10 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Abrir URI...</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>El pago requiere una URI o archivo</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Seleccione archivo de sulicitud de pago</translation>
- </message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
</context>
@@ -853,10 +937,6 @@
<translation>Información</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Ventana de depuración</translation>
- </message>
- <message>
<source>General</source>
<translation>General</translation>
</message>
@@ -959,7 +1039,19 @@
<source>Remove</source>
<translation>Eliminar</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Copiar mensaje</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -1105,6 +1197,10 @@
<translation>Copiar cantidad</translation>
</message>
<message>
+ <source>Copy amount</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
<source>Copy fee</source>
<translation>Copiar comisión</translation>
</message>
@@ -1113,6 +1209,10 @@
<translation>Copiar bytes</translation>
</message>
<message>
+ <source>Copy dust</source>
+ <translation>Copiar dust</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation>Copiar cambio</translation>
</message>
@@ -1144,10 +1244,6 @@
<translation>Escoger dirección previamente usada</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Esto es un pago ordinario.</translation>
- </message>
- <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -1179,10 +1275,7 @@
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
+</context>
<context>
<name>ShutdownWindow</name>
</context>
@@ -1279,6 +1372,10 @@
<translation>Comisión de transacción</translation>
</message>
<message>
+ <source>Transaction</source>
+ <translation>Transacción</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Cantidad</translation>
</message>
@@ -1308,6 +1405,22 @@
<context>
<name>TransactionView</name>
<message>
+ <source>Copy address</source>
+ <translation>Copiar dirección</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copiar ID de la transacción</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Archivo de columnas separadas por coma (*.csv)</translation>
</message>
@@ -1337,6 +1450,10 @@
</context>
<context>
<name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation>Cerrar monedero</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
@@ -1358,10 +1475,38 @@
<source>Export the data in the current tab to a file</source>
<translation>Exportar a un archivo los datos de esta pestaña</translation>
</message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Copia de seguridad fallida</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>Hubo un error intentando guardar los datos de la billetera al %1</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Copia de seguridad completada</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>Los datos de la billetera fueron guardados exitosamente al %1</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation>Esta es una compilación de prueba pre-lanzamiento - use bajo su propio riesgo - no utilizar para aplicaciones de minería o mercantes</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Aviso: ¡La red no parece estar totalmente de acuerdo! Algunos mineros parecen estar teniendo inconvenientes.</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>Aviso: ¡No parecen estar totalmente de acuerdo con nuestros compañeros! Puede que tengas que actualizar, u otros nodos tengan que actualizarce.</translation>
+ </message>
+ <message>
<source>Corrupted block database detected</source>
<translation>Corrupción de base de datos de bloques detectada.</translation>
</message>
@@ -1395,7 +1540,7 @@
</message>
<message>
<source>Not enough file descriptors available.</source>
- <translation>No hay suficientes descriptores de archivo disponibles. </translation>
+ <translation>No hay suficientes descriptores de archivo disponibles.</translation>
</message>
<message>
<source>Verifying blocks...</source>
diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts
index c7e4ee38ac..f055141fc3 100644
--- a/src/qt/locale/bitcoin_et.ts
+++ b/src/qt/locale/bitcoin_et.ts
@@ -172,6 +172,10 @@
<translation>Rahakott krüpteeritud</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>TÄHTIS: Kõik varasemad rahakoti varundfailid tuleks üle kirjutada äsja loodud krüpteeritud rahakoti failiga. Turvakaalutlustel tühistatakse krüpteerimata rahakoti failid alates uue, krüpteeritud rahakoti, kasutusele võtust.</translation>
+ </message>
+ <message>
<source>Wallet encryption failed</source>
<translation>Rahakoti krüpteerimine ebaõnnestus</translation>
</message>
@@ -294,14 +298,6 @@
<translation>Rahakoti krüpteerimise salafraasi muutmine</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Silumise aken</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Ava debugimise ja diagnostika konsool</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Kontrolli sõnumit...</translation>
</message>
@@ -354,10 +350,6 @@
<translation>Loo maksepäring (genereerib QR koodid ja bitcoini: URId)</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Ava bitcoini: URI või maksepäring</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Käsurea valikud</translation>
</message>
@@ -463,7 +455,11 @@
<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>
- </context>
+ <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>
<name>CoinControlDialog</name>
<message>
@@ -679,21 +675,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Ava URI</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Vali maksepäringu fail</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Vali maksepäringu fail mida avada</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -859,16 +843,12 @@
<translation>Maksepäringu tõrge</translation>
</message>
<message>
- <source>Payment request rejected</source>
- <translation>Maksepäring tagasi lükatud</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Maksepäring aegunud.</translation>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Bitcoin ei käivitu: vajuta-maksa toiming</translation>
</message>
<message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Kinnitamata maksepäringud kohandatud makse scriptidele ei ole toetatud.</translation>
+ <source>URI handling</source>
+ <translation>URI käsitsemine</translation>
</message>
</context>
<context>
@@ -975,10 +955,6 @@
<translation>&amp;Informatsioon</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Debugimise aken</translation>
- </message>
- <message>
<source>General</source>
<translation>Üldine</translation>
</message>
@@ -1405,18 +1381,7 @@
<source>Pay To:</source>
<translation>Maksa :</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Aadressiraamatusse sisestamiseks märgista aadress</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Jah</translation>
- </message>
-</context>
+ </context>
<context>
<name>ShutdownWindow</name>
<message>
diff --git a/src/qt/locale/bitcoin_et_EE.ts b/src/qt/locale/bitcoin_et_EE.ts
deleted file mode 100644
index 4778e9492b..0000000000
--- a/src/qt/locale/bitcoin_et_EE.ts
+++ /dev/null
@@ -1,779 +0,0 @@
-<TS language="et_EE" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Create a new address</source>
- <translation>Loo uus aadress</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Uus</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Kopeeri</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Kustuta valitud aadress nimekirjast</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Kustuta</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Muuda</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Silt</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Aadress</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(silt puudub)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Enter passphrase</source>
- <translation>Sisesta parool</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Uus parool</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Korda uut parooli</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Krüpteeri rahakott</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Dekrüpteeri rahakott</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Muuda parooli</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Kas oled kindel, et soovid rahakoti krüpteerida?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Rahakott krüpteeritud</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Rahakoti krüpteerimine ebaõnnestus</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Rahakoti krüpteerimine ebaõnnestus sisemise vea tõttu. Sinu rahakotti ei krüpteeritud.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Sisestatud paroolid ei kattu.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Rahakoti lahtilukustamine ebaõnnestus</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Rahakoti dekrüpteerimine ebaõnnestus</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Rahakoti parooli vahetus õnnestus.</translation>
- </message>
- </context>
-<context>
- <name>BanTableModel</name>
- </context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Võrguga sünkroniseerimine...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Ülevaade</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Välju rakendusest</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Valikud...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Ava &amp;URI...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Kõvakettal olevate plokkide reindekseerimine...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Rahakott</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Saada</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Näita / Peida</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Fail</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Seaded</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Abi</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Käsurea valikud</translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 ajast maas</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Hilisemad transaktsioonid ei ole veel nähtavad.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Viga</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Hoiatus</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informatsioon</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Amount:</source>
- <translation>Kogus</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Kogus</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Kuupäev</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Kinnitused</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Kinnitatud</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Kopeeri aadress</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopeeri kogus</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Kopeeri transaktsiooni ID</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>jah</translation>
- </message>
- <message>
- <source>no</source>
- <translation>ei</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(silt puudub)</translation>
- </message>
- </context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Aadress</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Uue võtme genereerimine ebaõnnestus.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>name</source>
- <translation>nimi</translation>
- </message>
- </context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>versioon</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Käsurea valikud</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Tere tulemast</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Viga</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- </context>
-<context>
- <name>OpenURIDialog</name>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Valikud</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Võrk</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;OK</source>
- <translation>&amp;OK</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Viga</translation>
- </message>
- </context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Pending:</source>
- <translation>Ootel:</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Kokku:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Hiljutised transaktsioonid</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>Sent</source>
- <translation>Saadetud</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Vastu võetud</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Kogus</translation>
- </message>
- </context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Salvesta Pilt...</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>&amp;Kopeeri Pilt</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>Salvesta QR Kood</translation>
- </message>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Informatsioon</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Üldine</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Võrk</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Nimi</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Ühenduste arv</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Blokiahel</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Mälu kasutus</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Vastu võetud</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Saadetud</translation>
- </message>
- <message>
- <source>Direction</source>
- <translation>Suund</translation>
- </message>
- <message>
- <source>Version</source>
- <translation>Versioon</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Teenused</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Pingi Aeg</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Võrgu Liiklus</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Puhasta konsool</translation>
- </message>
- <message>
- <source>never</source>
- <translation>mitte kunagi</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Sisenev</translation>
- </message>
- <message>
- <source>Outbound</source>
- <translation>Väljuv</translation>
- </message>
- <message>
- <source>Yes</source>
- <translation>Jah</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Ei</translation>
- </message>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>&amp;Kogus:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Sõnum:</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Eemalda</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Kopeeri sõnum</translation>
- </message>
- <message>
- <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>&amp;Save Image...</source>
- <translation>&amp;Salvesta Pilt...</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Aadress</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Kogus</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Silt</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Sõnum</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Rahakott</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Kuupäev</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Silt</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Sõnum</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(silt puudub)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Amount:</source>
- <translation>Kogus</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Vali...</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopeeri kogus</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(silt puudub)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Jah</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Allkiri</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Palun kontrolli aadressi ja proovi uuesti.</translation>
- </message>
- <message>
- <source>Message signed.</source>
- <translation>Sõnum allkirjastatud.</translation>
- </message>
- <message>
- <source>The signature could not be decoded.</source>
- <translation>Allkirja ei õnnestunud dekodeerida.</translation>
- </message>
- <message>
- <source>Please check the signature and try again.</source>
- <translation>Palun kontrolli allkirja ja proovi uuesti.</translation>
- </message>
- <message>
- <source>Message verification failed.</source>
- <translation>Sõnumi verifitseerimine ebaõnnestus.</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation>Sõnum verifitseeritud.</translation>
- </message>
-</context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[test võrk]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KB/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Status</source>
- <translation>Olek</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Kuupäev</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Sõnum</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Kommentaar</translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation>Transaktsiooni ID</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Kogus</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Kuupäev</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tüüp</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Silt</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(silt puudub)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Kõik</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Täna</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>Käimasolev kuu</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Eelmine kuu</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Käimasolev aasta</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Vahemik...</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Kopeeri aadress</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopeeri summa</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Kopeeri transaktsiooni ID</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Kinnitatud</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Kuupäev</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tüüp</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Silt</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Aadress</translation>
- </message>
- <message>
- <source>ID</source>
- <translation>ID</translation>
- </message>
- <message>
- <source>Range:</source>
- <translation>Vahemik:</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>Backup Wallet</source>
- <translation>Varunda Rahakott</translation>
- </message>
- <message>
- <source>Wallet Data (*.dat)</source>
- <translation>Rahakoti Andmed (*.dat)</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>Varundamine Ebaõnnestus</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informatsioon</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Hoiatus</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Viga</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_eu.ts b/src/qt/locale/bitcoin_eu.ts
index 8d1479de7c..7aca604eeb 100644
--- a/src/qt/locale/bitcoin_eu.ts
+++ b/src/qt/locale/bitcoin_eu.ts
@@ -70,6 +70,10 @@
<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>
@@ -132,6 +136,10 @@
<translation>Pasahitz berria errepiikatu</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Pasahitza erakutsi</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Diruzorroa enkriptatu</translation>
</message>
@@ -172,6 +180,30 @@
<translation>Zorroa enkriptatuta</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>Diruzorroaren pasahitz berria sartu. &lt;br/&gt;Mesedez &lt;b&gt; hamar edo gehiago ausazko hizkiko&lt;/b&gt; pasahitza erabili, edo &lt;b&gt; gutxienez zortzi hitz&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Diruzorroaren pasahitz zahar zein berria sartu.</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>Gogoan izan diruzorroaren enkripzioak ezin dituela zure bitcoinak zure ordenagailuan izan dezakezun malware batengandik lapurtuak izatetik guztiz babestu .</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Enkriptatzeko diruzorroa</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Zure diruzorroa enkriptatzekotan dago</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Zure diruzorroa enkriptatua dago orain.</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>GARRANTZITSUA: Diruzorroaren segurtasun-kopia, wallet.dat, erabilezina bihurtuko da enkriptazioa burutu ondoren. Ondorioz, segurtasun-kopia berriekin ordezkatu beharko zenituzke zure jada eginik dituzun diruzorroaren kopiak.</translation>
</message>
@@ -199,13 +231,33 @@
<source>Wallet decryption failed</source>
<translation>Zorroaren desenkriptazioak huts egin du</translation>
</message>
- </context>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Diruzorroaren pasahitza arrakastaz aldatu da.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Abisua: Mayuskulak blokeatuak dituzu!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
- </context>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Saremaskara</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Honarte debekatua </translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
+ <source>Sign &amp;message...</source>
+ <translation>&amp;Mezua zinatu</translation>
+ </message>
+ <message>
<source>Synchronizing with network...</source>
<translation>Sarearekin sinkronizatzen...</translation>
</message>
@@ -234,6 +286,14 @@
<translation>Aplikaziotik irten</translation>
</message>
<message>
+ <source>&amp;About %1</source>
+ <translation>%1-ri buruz</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>%1-ri buruzko informazioa azaldu</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>&amp;Qt-ri buruz</translation>
</message>
@@ -246,10 +306,82 @@
<translation>&amp;Aukerak...</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>%1-ren konfiguraketa aukerak aldatu</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>Diruzorroa &amp;enkriptatu...</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>Diruzorroaren kopia bat gorde</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>Pasahitza &amp;aldatu...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>&amp;URLa zabaldu</translation>
+ </message>
+ <message>
+ <source>Create Wallet...</source>
+ <translation>Diruzorroa sortu...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Diruzorro berri bat sortu</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Diruzorroa:</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Sarea desaktibatzeko sakatu</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Sarea desaktibatua</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Sarea berriro aktibatzeko sakatu</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Burukoak sinkronizatzen (%1)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Blokeak diskoan berriro zerrendatzen...</translation>
+ </message>
+ <message>
<source>Change the passphrase used for wallet encryption</source>
<translation>Diruzorroa enkriptatzeko erabilitako pasahitza aldatu</translation>
</message>
<message>
+ <source>&amp;Verify message...</source>
+ <translation>Mezua &amp;balioztatu...</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;Bidali</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;Jaso</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Erakutsi / Izkutatu</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Lehio nagusia erakutsi edo izkutatu</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Artxiboa</translation>
</message>
@@ -266,6 +398,10 @@
<translation>Fitxen tresna-barra</translation>
</message>
<message>
+ <source>%1 behind</source>
+ <translation>%1 atzetik</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Akatsa</translation>
</message>
@@ -274,10 +410,76 @@
<translation>Eguneratua</translation>
</message>
<message>
+ <source>Open Wallet</source>
+ <translation>Diruzorroa zabaldu</translation>
+ </message>
+ <message>
+ <source>Open a wallet</source>
+ <translation>Diruzorro bat zabaldu</translation>
+ </message>
+ <message>
+ <source>Close Wallet...</source>
+ <translation>Diruzorroa itxi...</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation>Diruzorroa itxi</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;Lehioa</translation>
+ </message>
+ <message>
+ <source>Zoom</source>
+ <translation>Gerturatu</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation>Lehio nagusia</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Eguneratzen...</translation>
</message>
<message>
+ <source>Error: %1</source>
+ <translation>Akatsa: %1</translation>
+ </message>
+ <message>
+ <source>Warning: %1</source>
+ <translation>Abisua: %1</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Data: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Kopurua: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>Diruzorroa: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Etiketa: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Helbidea: %1
+</translation>
+ </message>
+ <message>
<source>Sent transaction</source>
<translation>Bidalitako transakzioa</translation>
</message>
@@ -297,10 +499,30 @@
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation>Txanpon aukeraketa</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Zenbat:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Byte kopurua:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>Kopurua:</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>Hautsa:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Bueltak:</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Kopurua</translation>
</message>
@@ -309,6 +531,14 @@
<translation>Data</translation>
</message>
<message>
+ <source>Confirmations</source>
+ <translation>Konfirmazioak</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Konfirmatuta</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>Helbidea kopiatu</translation>
</message>
@@ -317,16 +547,52 @@
<translation>Etiketa kopiatu</translation>
</message>
<message>
+ <source>yes</source>
+ <translation>bai</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>ez</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(izendapenik ez)</translation>
</message>
- </context>
+ <message>
+ <source>(change)</source>
+ <translation>(bueltak)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Diruzorroa sortzen&lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Diruzorroa sortzen hutsegitea</translation>
+ </message>
</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Diruzorroa sortu</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Diruzorroaren izena</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Diruzorroa enkriptatu</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Sortu</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -364,13 +630,33 @@
</context>
<context>
<name>FreespaceChecker</name>
+ <message>
+ <source>name</source>
+ <translation>izena</translation>
+ </message>
</context>
<context>
<name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation>bertsioa</translation>
+ </message>
</context>
<context>
<name>Intro</name>
<message>
+ <source>Welcome</source>
+ <translation>Ongietorri</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation>Ongietorri %1-ra</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Akatsa</translation>
</message>
@@ -381,12 +667,40 @@
<source>Form</source>
<translation>Inprimakia</translation>
</message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Ezezaguna...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Azken blokearen unea</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>kalkulatzen...</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Izkutatu</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
- </context>
+ <message>
+ <source>URI:</source>
+ <translation>URI: </translation>
+ </message>
+</context>
<context>
<name>OpenWalletActivity</name>
+ <message>
+ <source>Open wallet failed</source>
+ <translation>Diruzorroa irekitzen hutsegitea</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation>Diruzorroa irekitzen abisua</translation>
+ </message>
</context>
<context>
<name>OptionsDialog</name>
@@ -395,9 +709,53 @@
<translation>Aukerak</translation>
</message>
<message>
+ <source>&amp;Main</source>
+ <translation>&amp;Nagusia</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Databasearen cache tamaina</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>Tor</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;Lehioa</translation>
+ </message>
+ <message>
+ <source>&amp;Display</source>
+ <translation>&amp;Pantaila</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation>Zenbatekoa azaltzeko &amp;unitatea:</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>&amp;Ados</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>&amp;Ezeztatu</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation>Bat ere ez</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Konfiguraketa aukerak</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Akatsa</translation>
</message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>Aldaketa honek clienta berriro piztea eskatzen du</translation>
+ </message>
</context>
<context>
<name>OverviewPage</name>
@@ -405,6 +763,14 @@
<source>Form</source>
<translation>Inprimakia</translation>
</message>
+ <message>
+ <source>Pending:</source>
+ <translation>Zai:</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>Guztira:</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -419,6 +785,10 @@
<translation>Kopurua</translation>
</message>
<message>
+ <source>Error: %1</source>
+ <translation>Akatsa: %1</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>ezezaguna</translation>
</message>
@@ -428,6 +798,10 @@
</context>
<context>
<name>RPCConsole</name>
+ <message>
+ <source>Last block time</source>
+ <translation>Azken blokearen unea</translation>
+ </message>
</context>
<context>
<name>ReceiveCoinsDialog</name>
@@ -497,14 +871,34 @@
<translation>Txanponak bidali</translation>
</message>
<message>
+ <source>Quantity:</source>
+ <translation>Zenbat:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Byte kopurua:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>Kopurua:</translation>
</message>
<message>
+ <source>Change:</source>
+ <translation>Bueltak:</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Izkutatu</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>Hainbat jasotzaileri batera bidali</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>Hautsa:</translation>
+ </message>
+ <message>
<source>Balance:</source>
<translation>Saldoa:</translation>
</message>
@@ -559,13 +953,6 @@
<source>Pay To:</source>
<translation>Honi ordaindu:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Emaiozu helbide honi izenburu bat, zure helbide-liburuan horrela ager dadin</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
</context>
<context>
<name>ShutdownWindow</name>
@@ -658,7 +1045,7 @@
</message>
<message>
<source>Received with</source>
- <translation>Honekin jasoa </translation>
+ <translation>Honekin jasoa</translation>
</message>
<message>
<source>Sent to</source>
@@ -729,7 +1116,7 @@
</message>
<message>
<source>Received with</source>
- <translation>Honekin jasoa </translation>
+ <translation>Honekin jasoa</translation>
</message>
<message>
<source>Sent to</source>
@@ -764,6 +1151,10 @@
<translation>Komaz bereizitako artxiboa (*.csv)</translation>
</message>
<message>
+ <source>Confirmed</source>
+ <translation>Berretsia</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -789,6 +1180,10 @@
</context>
<context>
<name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation>Diruzorroa itxi</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts
index 4d697b5f15..b19bb00160 100644
--- a/src/qt/locale/bitcoin_fa.ts
+++ b/src/qt/locale/bitcoin_fa.ts
@@ -174,7 +174,7 @@
<message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
<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>
@@ -339,14 +339,6 @@
<translation>رمز عبور مربوط به رمزگذاریِ کیف پول را تغییر دهید</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>پنجره دیباگ</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>باز کردن کنسول دی باگ و تشخیص</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>تایید پیام</translation>
</message>
@@ -407,10 +399,6 @@
<translation>نمایش لیست آدرس‌ها و لیبل‌های دریافتی استفاده شده</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>بازکردن بیت‌کوین: آدرس یا درخواست پرداخت</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>گزینه های خط فرمان</translation>
</message>
@@ -627,7 +615,7 @@
</message>
<message>
<source>Confirmations</source>
- <translation>تاییدیه </translation>
+ <translation>تاییدیه</translation>
</message>
<message>
<source>Confirmed</source>
@@ -785,16 +773,12 @@
<translation>نسخه</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-بیت)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>حدود %1</translation>
</message>
<message>
<source>Command-line options</source>
- <translation>گزینه های خط-فرمان </translation>
+ <translation>گزینه های خط-فرمان</translation>
</message>
</context>
<context>
@@ -890,25 +874,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>باز کردن آدرس URL</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>بازکردن درخواست پرداخت از آدرس URL یا فایل</translation>
- </message>
- <message>
<source>URI:</source>
<translation>آدرس:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>انتخاب فایل درخواست وجه (Payment Request)</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>انتخاب فایل درحواست وجه برای باز کردن</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -937,7 +905,7 @@
</message>
<message>
<source>&amp;Hide tray icon</source>
- <translation> مخفی کردن ایکون
+ <translation>مخفی کردن ایکون
</translation>
</message>
<message>
@@ -1153,7 +1121,7 @@
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>موجودی شما در همین لحظه در آدرس های Watch only Addresses </translation>
+ <translation>موجودی شما در همین لحظه در آدرس های Watch only Addresses</translation>
</message>
<message>
<source>Spendable:</source>
@@ -1179,36 +1147,20 @@
<translation>درخواست پرداخت با خطا مواجه شد</translation>
</message>
<message>
- <source>Invalid payment address %1</source>
- <translation>آدرس پرداخت نامعتبر %1</translation>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>نمی‌توان بیت‌کوین را اجرا کرد: کنترل‌کنندهٔ کلیک-و-پرداخت</translation>
</message>
<message>
- <source>Payment request file handling</source>
- <translation>درحال پردازش درخواست پرداخت</translation>
+ <source>URI handling</source>
+ <translation>مدیریت URI</translation>
</message>
<message>
- <source>Payment request rejected</source>
- <translation>درخواست پرداخت رد شد</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>درخواست پرداخت منقضی شد یا تاریخ آن گذشت.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>درخواست پرداخت, با مقداردهی اولیه یکسان نبود.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>درخواست پرداخت نامعتبر بود.</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>درخواست از شبکه با خطا مواجه شد</translation>
+ <source>Invalid payment address %1</source>
+ <translation>آدرس پرداخت نامعتبر %1</translation>
</message>
<message>
- <source>Payment acknowledged</source>
- <translation>پرداخت تایید شد</translation>
+ <source>Payment request file handling</source>
+ <translation>درحال پردازش درخواست پرداخت</translation>
</message>
</context>
<context>
@@ -1371,10 +1323,6 @@
<translation>&amp;اطلاعات</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>پنجره یا صفحه دی باگ</translation>
- </message>
- <message>
<source>General</source>
<translation>عمومی</translation>
</message>
@@ -1799,10 +1747,6 @@
<translation>هشدار:تخمین کارمزد در حال حاضر امکان پذیر نیست.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>تنظیمات کاهش کارمزد</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>
@@ -1828,7 +1772,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(مقداردهی کارمزد هوشمند هنوز مشخص نشده است.این کارمزد معمولا به اندازه چند بلاک طول میکشد...) </translation>
+ <translation>(مقداردهی کارمزد هوشمند هنوز مشخص نشده است.این کارمزد معمولا به اندازه چند بلاک طول میکشد...)</translation>
</message>
<message>
<source>Send to multiple recipients at once</source>
@@ -1864,7 +1808,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Confirm the send action</source>
- <translation>تایید عملیات ارسال </translation>
+ <translation>تایید عملیات ارسال</translation>
</message>
<message>
<source>S&amp;end</source>
@@ -1959,10 +1903,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>ایجاد تراکنش با خطا مواجه شد!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>به خاطر دلیل روبرو تراکنش رد شد: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>کارمزد بیشتر از %1 است,این یعنی کارمزد خیلی زیادی در نظر گرفته شده است.</translation>
</message>
@@ -2014,10 +1954,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>انتخاب آدرس قبلا استفاده شده</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>این پرداحت,عادی هست.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>آدرس بیت کوین برای ارسال پرداحت به آن</translation>
</message>
@@ -2053,17 +1989,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Memo:</source>
<translation>یادداشت:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>یک برچسب برای این آدرس بنویسید تا به دفترچه‌ آدرس‌های شما اضافه شود</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>بله</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2084,7 +2009,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>&amp;Sign Message</source>
- <translation>&amp;ثبت پیام </translation>
+ <translation>&amp;ثبت پیام</translation>
</message>
<message>
<source>The Bitcoin address to sign the message with</source>
@@ -2168,14 +2093,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</translation>
</message>
<message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>نشانی وارد شده به هیچ کلیدی اشاره نمی‌کند.</translation>
+ </message>
+ <message>
<source>Wallet unlock was cancelled.</source>
<translation>قفل‌گشابی کیف‌پول لغو شد.</translation>
</message>
<message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>کلید خصوصی برای نشانی وارد شده در دسترس نیست.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>امضای پیام با شکست مواجه شد.</translation>
+ </message>
+ <message>
<source>Message signed.</source>
<translation>پیام ثبت شده</translation>
</message>
<message>
+ <source>The signature could not be decoded.</source>
+ <translation>امضا نمی‌تواند کدگشایی شود.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>لطفاً امضا را بررسی نموده و دوباره تلاش کنید.</translation>
+ </message>
+ <message>
<source>The signature did not match the message digest.</source>
<translation>این امضا با حرفو پیام همخوانی ندارد</translation>
</message>
@@ -2198,6 +2143,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>باز تا %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/تأیید نشده</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 تأییدیه</translation>
+ </message>
+ <message>
<source>Status</source>
<translation>وضعیت</translation>
</message>
@@ -2246,6 +2203,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>قبول نشده</translation>
</message>
<message>
+ <source>Debit</source>
+ <translation>اعتبار</translation>
+ </message>
+ <message>
<source>Total credit</source>
<translation>تمامی اعتبار</translation>
</message>
@@ -2324,10 +2285,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>برچسب</translation>
</message>
<message>
+ <source>Open until %1</source>
+ <translation>باز تا %1</translation>
+ </message>
+ <message>
<source>Unconfirmed</source>
<translation>تایید نشده</translation>
</message>
<message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>تأیید شده (%1 تأییدیه)</translation>
+ </message>
+ <message>
<source>Generated but not accepted</source>
<translation>تولید شده ولی هنوز قبول نشده است</translation>
</message>
@@ -2364,6 +2333,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>(برچسب ندارد)</translation>
</message>
<message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>وضعیت تراکنش. نشانگر را روی این فیلد نگه دارید تا تعداد تأییدیه‌ها نشان داده شود.</translation>
+ </message>
+ <message>
<source>Date and time that the transaction was received.</source>
<translation>تاریخ و زمان تراکنش دریافت شده است</translation>
</message>
@@ -2373,7 +2346,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Amount removed from or added to balance.</source>
- <translation> میزان وجه کم شده یا اضافه شده به حساب</translation>
+ <translation>میزان وجه کم شده یا اضافه شده به حساب</translation>
</message>
</context>
<context>
@@ -2578,6 +2551,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>بازیابی یا پشتیبان گیری کیف پول</translation>
</message>
<message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>دادهٔ کیف پول (*.dat)</translation>
+ </message>
+ <message>
<source>Backup Failed</source>
<translation>بازیابی یا پشتیبان گیری با خطا مواجه شد</translation>
</message>
@@ -2597,6 +2574,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%s توسعه دهندگان</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>این یک نسخه ی آزمایشی است - با مسئولیت خودتان از آن استفاده کنید - آن را در معدن و بازرگانی بکار نگیرید.</translation>
+ </message>
+ <message>
<source>Change index out of range</source>
<translation>تغییر دادن اندیس خارج از دامنه</translation>
</message>
@@ -2726,10 +2707,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>این هزینه تراکنشی است که در صورت عدم وجود هزینه تخمینی، پرداخت می کنید.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>این محصول شامل نرم افزار توسعه یافته با پروژه OpenSSL است، پروژه ای برای استفاده از جعبه ابزار OpenSSL %s و نرم افزار رمزنگاری که توسط اریک یانگ نوشته شده و همچنین نرم افزار UPnP که توسط توماس برنارد نوشته شده است.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s بسیار بزرگ انتخاب شده است.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts
index 2db4e598a9..28b455d13c 100644
--- a/src/qt/locale/bitcoin_fi.ts
+++ b/src/qt/locale/bitcoin_fi.ts
@@ -70,6 +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>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;Kopioi osoite</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Toista uusi tunnuslause</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Näytä salasanalause</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Salaa lompakko</translation>
</message>
@@ -172,6 +180,30 @@
<translation>Lompakko salattiin</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>Syötä uusi salasanalause lompakolle &lt;br/&gt;Ole hyvä ja käytä salasanalausetta, jossa on &lt;b&gt;kymmenen tai enemmän sattumanvaraisia merkkjä tai &lt;b&gt;kahdeksan tai enemmän sanoja&lt;/b&gt; .</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Syötä vanha ja uusi salasanalause lompakolle.</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>Muista, että salaamalla lompakkosi et täysin pysty suojaamaan bitcoineja varkaudelta, jotka aiheutuvat koneellasi olevista haittaohjelmista.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Lompakko tulee salata</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Lompakkosi tulee kohta salatuksi.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Lompakkosi on nyt salattu.</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>TÄRKEÄÄ: Kaikki tekemäsi vanhan lompakon varmuuskopiot pitäisi korvata uusilla suojatuilla varmuuskopioilla. Turvallisuussyistä edelliset varmuuskopiot muuttuvat turhiksi, kun aloitat uuden suojatun lompakon käytön.</translation>
</message>
@@ -294,6 +326,14 @@
<translation>Avaa &amp;URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Luo lompakko...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Luo uusi lompakko</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Lompakko:</translation>
</message>
@@ -334,14 +374,6 @@
<translation>Vaihda lompakon salaukseen käytettävä tunnuslause</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Testausikkuna</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Avaa debuggaus- ja diagnostiikkakonsoli</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>Varmista &amp;viesti...</translation>
</message>
@@ -402,10 +434,6 @@
<translation>Näytä vastaanottamiseen käytettyjen osoitteiden ja nimien lista</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Avaa bitcoin: URI tai maksupyyntö</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Komentorivin valinnat</translation>
</message>
@@ -454,6 +482,18 @@
<translation>Rahansiirtohistoria on ajan tasalla</translation>
</message>
<message>
+ <source>&amp;Sending addresses</source>
+ <translation>&amp;Lähetysosoitteet</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation>&amp;Vastaanotto-osoitteet</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <translation>Avaa lompakko</translation>
+ </message>
+ <message>
<source>Open a wallet</source>
<translation>Avaa lompakko</translation>
</message>
@@ -462,6 +502,10 @@
<translation>Sulje lompakko...</translation>
</message>
<message>
+ <source>Close wallet</source>
+ <translation>Sulje lompakko</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>
@@ -506,6 +550,10 @@
<translation>Virhe: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Varoitus: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Päivämäärä: %1
@@ -727,10 +775,50 @@
</context>
<context>
<name>CreateWalletActivity</name>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Luodaan lompakkoa &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Lompakon luonti epäonnistui</translation>
+ </message>
</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Luo lompakko</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Lompakon nimi</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>Salaa lompakko. Lompakko salataan valitsemallasa salasanalla.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Salaa lompakko</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>Poista yksityisavaimet käytöstä</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>Luo tyhjä lompakko. Tyhjissä lompakoissa ei aluksi ole yksityisavaimia tai skriptejä. Myöhemmin voidaan tuoda yksityisavaimia ja -osoitteita, tai asettaa HD-siemen.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Luo tyhjä lompakko</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Luo</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -816,10 +904,6 @@
<translation>versio</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Tietoja %1</translation>
</message>
@@ -847,6 +931,10 @@
<translation>Kun valitset OK, %1 aloittaa lataamaan ja käsittelemään koko %4 lohkoketjua (%2GB) aloittaen ensimmäisestä siirrosta %3 jolloin %4 käynnistettiin ensimmäistä kertaa.</translation>
</message>
<message>
+ <source>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>Tämän asetuksen peruuttaminen vaatii koko lohkoketjun uudelleenlataamisen. On nopeampaa ladata koko ketju ensin ja karsia se myöhemmin. Tämä myös poistaa käytöstä joitain edistyneitä toimintoja.</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>Tämä alustava synkronointi on erittäin vaativa ja saattaa tuoda esiin laiteongelmia, joita ei aikaisemmin ole havaittu. Aina kun ajat %1:n, jatketaan siitä kohdasta, mihin viimeksi jäätiin.</translation>
</message>
@@ -867,6 +955,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Hävitä lohkot varmistuksen jälkeen, poislukien viimeiset %1 GB (karsinta)</translation>
+ </message>
+ <message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation>Ainakin %1 GB tietoa varastoidaan tähän hakemistoon ja tarve kasvaa ajan myötä.</translation>
</message>
@@ -898,7 +990,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(tarvitaan %n GB)</numerusform><numerusform>(tarvitaan %n GB)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(tarvitaan %n GB koko ketjua varten)</numerusform><numerusform>(tarvitaan %n GB koko ketjua varten)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -953,29 +1049,17 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Avaa URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Avaa maksupyyntö URI:sta tai tiedostosta</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Valitse maksupyynnön tiedosto</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Valitse maksypyynnön tiedosto avattavaksi</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
<message>
+ <source>Open wallet failed</source>
+ <translation>Lompakon avaaminen epäonnistui</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>oletuslompakko</translation>
</message>
@@ -1075,6 +1159,10 @@
<translation>Tämän asetuksen muuttaminen vaatii koko lohkoketjun uudelleenlataamista.</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 = jätä näin monta ydintä vapaaksi)</translation>
</message>
@@ -1307,7 +1395,7 @@
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>Nykyinen tase seurantaosoitetteissa</translation>
+ <translation>Nykyinen tase seurattavassa osoitetteissa</translation>
</message>
<message>
<source>Spendable:</source>
@@ -1319,15 +1407,15 @@
</message>
<message>
<source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Vahvistamattomat rahansiirrot vain katseltaviin osoitteisiin</translation>
+ <translation>Vahvistamattomat rahansiirrot vain seurattaviin osoitteisiin</translation>
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Louhittu, ei vielä kypsynyt saldo vain katseltavissa osoitteissa</translation>
+ <translation>Louhittu, ei vielä kypsynyt saldo vain seurattavissa osoitteissa</translation>
</message>
<message>
<source>Current total balance in watch-only addresses</source>
- <translation>Nykyinen tase seurantaosoitetteissa</translation>
+ <translation>Nykyinen tase seurattavassa osoitetteissa</translation>
</message>
</context>
<context>
@@ -1349,16 +1437,8 @@
<translation>'bitcoin://' ei ole kelvollinen URI. Käytä 'bitcoin:' sen sijaan.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Käytät BIP70 -URL:ia, jonka tuki päättyy lähitulevaisuudessa.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Maksupyynnön haku URL on virheellinen: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Maksupyyntöä ei voida käsitellä, sillä BIP70-tukea ei ole käännetty ohjelmaan.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Tämän virheen saadessasi tulee sinun pyytää kauppiaalta BIP21 -yhteensopivaa URI-osoitetta.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1372,66 +1452,6 @@
<source>Payment request file handling</source>
<translation>Maksupyynnön tiedoston käsittely</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Maksupyyntötiedostoa ei voi lukea! Tämä saattaa johtua epäkelvosta maksupyyntötiedostosta.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Maksupyyntö hylätty</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Maksupyyntoverkko ei täsmää asiakasohjelman verkon kanssa.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Maksupyyntö vanhentui.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Maksupyyntöä ei ole alustettu.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Varmistamattomia maksupyyntöjä kustomoituun maksupalveluun ei tueta.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Virheellinen maksupyyntö.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Maksupyyntö %1 on liian pieni (kohdellaan tomuna).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Maksupalautus %1:sta</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Maksupyyntö %1 on liian suuri (%2 tavua, sallittu %3 tavua).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Virhe kommunikoidessa %1n kanssa: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Maksupyyntöä ei voida jäsentää!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Virheellinen vastaus palvelimelta %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Tietoverkon pyyntövirhe</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Rahansiirto tunnistettu</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1582,6 +1602,10 @@
<translation>Virhe käännettäessä URI:a QR-koodiksi.</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>Tukea QR-koodeille ei ole saatavilla.</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>Tallenna QR-koodi</translation>
</message>
@@ -1605,10 +1629,6 @@
<translation>T&amp;ietoa</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>&amp;Debug-ikkuna</translation>
- </message>
- <message>
<source>General</source>
<translation>Yleinen</translation>
</message>
@@ -1625,6 +1645,10 @@
<translation>Käytä '%1' -valitsinta määritelläksesi muun kuin oletuksen data-hakemistolle.</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>Käytä '%1' -valitsinta määritelläksesi muun kuin oletuksen lohkohakemistolle.</translation>
</message>
@@ -1834,7 +1858,7 @@
</message>
<message>
<source>Ban for</source>
- <translation>Estä </translation>
+ <translation>Estä</translation>
</message>
<message>
<source>&amp;Unban</source>
@@ -2141,10 +2165,6 @@
<translation>Varoitus: Kulujen arviointi ei ole juuri nyt mahdollista.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>pudota kulujen asetukset</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>
@@ -2257,6 +2277,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>%1 (%2 lohkoa)</translation>
</message>
<message>
+ <source> from wallet '%1'</source>
+ <translation> lompakosta '%1'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 to %2</translation>
</message>
@@ -2285,6 +2309,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Yhteensä</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Valitse "Näytä yksityiskohdat" nähdäksesi listan vastaanottajsta.</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Vahvista kolikoiden lähetys</translation>
</message>
@@ -2313,10 +2341,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Rahansiirron luonti epäonnistui!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Siirto hylättiin seuraavasta syystä: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>%1:tä ja korkeampaa siirtokulua pidetään mielettömän korkeana.</translation>
</message>
@@ -2330,7 +2354,7 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
- <translation>Varoitus: Virheellinen Bitcoin-osoite </translation>
+ <translation>Varoitus: Virheellinen Bitcoin-osoite</translation>
</message>
<message>
<source>Warning: Unknown change address</source>
@@ -2368,10 +2392,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Valitse aikaisemmin käytetty osoite</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Tämä on normaali maksu.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Bitcoin-osoite johon maksu lähetetään</translation>
</message>
@@ -2431,17 +2451,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<source>Memo:</source>
<translation>Muistio:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Syötä tälle osoitteelle nimi lisätäksesi sen osoitekirjaan</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Kyllä</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2672,7 +2681,7 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
</message>
<message>
<source>watch-only</source>
- <translation>vain katseltava</translation>
+ <translation>vain seurattava</translation>
</message>
<message>
<source>label</source>
@@ -2846,7 +2855,7 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
</message>
<message>
<source>watch-only</source>
- <translation>vain katseltava</translation>
+ <translation>vain seurattava</translation>
</message>
<message>
<source>(n/a)</source>
@@ -2870,7 +2879,7 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
</message>
<message>
<source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation>Onko rahansiirrossa mukana ainoastaan katseltava osoite vai ei.</translation>
+ <translation>Onko rahansiirrossa mukana ainoastaan seurattava osoite vai ei.</translation>
</message>
<message>
<source>User-defined intent/purpose of the transaction.</source>
@@ -2993,7 +3002,7 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
</message>
<message>
<source>Watch-only</source>
- <translation>Vain katseltava</translation>
+ <translation>Vain seurattava</translation>
</message>
<message>
<source>Date</source>
@@ -3050,6 +3059,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<context>
<name>WalletController</name>
<message>
+ <source>Close wallet</source>
+ <translation>Sulje lompakko</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>Lompakon sulkeminen liian pitkäksi aikaa saattaa johtaa tarpeeseen synkronoida koko ketju uudelleen, mikäli karsinta on käytössä.</translation>
</message>
@@ -3162,10 +3175,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Uudelleenskannaukset eivät ole mahdollisia karsivassa tilassa. Sinun täytyy käyttää -reindex joka lataa koko lohkoketjun uudelleen.</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>
@@ -3330,6 +3339,10 @@ 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>
@@ -3434,6 +3447,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>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Karsintatila ei ole yhteensopiva -blockfilterindex valinnan kanssa</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Vähennetään -maxconnections arvoa %d:stä %d:hen järjestelmän rajoitusten vuoksi.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fil.ts b/src/qt/locale/bitcoin_fil.ts
index 71baacf230..f7b8000439 100644
--- a/src/qt/locale/bitcoin_fil.ts
+++ b/src/qt/locale/bitcoin_fil.ts
@@ -334,14 +334,6 @@
<translation>Palitan ang passphrase na ginamit para sa pag-encrypt ng walet</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>I-debug ang window</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Buksan ang debugging at diagnostic console</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>I-verify ang mensahe...</translation>
</message>
@@ -402,10 +394,6 @@
<translation>Ipakita ang talaan ng mga gamit na address at label para sa pagtanggap</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Buksan ang bitcoin: URI o kahilingan ng bayad</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Mga opsyon ng command-line</translation>
</message>
@@ -483,7 +471,7 @@
</message>
<message>
<source>&amp;Window</source>
- <translation>Window </translation>
+ <translation>Window</translation>
</message>
<message>
<source>Minimize</source>
@@ -594,7 +582,7 @@
</message>
<message>
<source>Bytes:</source>
- <translation>Bytes: </translation>
+ <translation>Bytes:</translation>
</message>
<message>
<source>Amount:</source>
@@ -718,7 +706,7 @@
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Maaaring magbago ng +/- %1 satoshi(s) kada input. </translation>
+ <translation>Maaaring magbago ng +/- %1 satoshi(s) kada input.</translation>
</message>
<message>
<source>(no label)</source>
@@ -824,10 +812,6 @@
<translation>salin</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Tungkol sa %1</translation>
</message>
@@ -957,25 +941,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Buksan ang URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Buksan ang hiling ng bayad sa URI o file</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Piliin ang file na hiling ng bayad</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Piliin ang file na hiling ng bayad upang mabuksan</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1160,7 +1128,7 @@
</message>
<message>
<source>&amp;Window</source>
- <translation>Window </translation>
+ <translation>Window</translation>
</message>
<message>
<source>Show only a tray icon after minimizing the window.</source>
@@ -1353,18 +1321,6 @@
<translation>Ang 'bitcoin://' ay hindi wastong URI. Sa halip, gamitin ang 'bitcoin:'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Gumagamit ka ng BIP70 URL na hindi suportado sa hinaharap.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Ang fetch URL ng hiling ng bayad ay hindi wasto: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Hindi maproseso ang hiling ng bayad dahil ang suporta ng BIP70 ay hindi naipon.</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>Hindi wasto and address ng bayad %1</translation>
</message>
@@ -1376,66 +1332,6 @@
<source>Payment request file handling</source>
<translation>File handling ng hiling ng bayad</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Hindi mabasa ang file ng hiling ng bayad! Marahil ito ay dahil sa hindi wastong file ng hiling ng bayad.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Ang hiling ng bayad ay tinanggihan</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Ang network ng hiling ng bayad ay hindi tumutugma sa network ng kliyente.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Ang hiling ng bayad ay nag-expire na.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Ang hiling ng bayad ay hindi napasimulan.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Ang hindi na-verify na hiling ng bayad sa custom payment scripts ay hindi suportado.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Hindi wasto ang hiling ng bayad.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Ang hinihiling na halaga ng bayad na %1 ay masyadong maliit (ituring na dust).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>I-refund mula %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Ang hiling ng bayad %1 ay masyadong malaki (%2 bytes, ipinapahintulot ay %3 bytes).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>May kamalian makipag-usap sa %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Ang hiling ng bayad ay hindi ma-parse!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Masamang tugon mula sa server %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Kamalian sa paghiling ng network</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Nakilala ang kabayaran</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1609,10 +1505,6 @@
<translation>Impormasyon</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>I-debug ang window</translation>
- </message>
- <message>
<source>General</source>
<translation>Pangkalahatan</translation>
</message>
@@ -1945,7 +1837,7 @@
</message>
<message>
<source>Clear all fields of the form.</source>
- <translation>Burahin ang laman ng lahat ng patlang ng form. </translation>
+ <translation>Burahin ang laman ng lahat ng patlang ng form.</translation>
</message>
<message>
<source>Clear</source>
@@ -1953,7 +1845,7 @@
</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>Ang mga native segwit address (aka Bech32 o BIP-173) ay makakabawas ng iyong mga bayad sa transaksyon at nagaalok ng mas mahusay na proteksyon laban sa mga typo, ngunit ang mga lumang walet ay hindi sumusuporta nito. Kapag hindi ch-in-eck, gagawa ng mga address na katugma sa mga lumang walet sa halip. </translation>
+ <translation>Ang mga native segwit address (aka Bech32 o BIP-173) ay makakabawas ng iyong mga bayad sa transaksyon at nagaalok ng mas mahusay na proteksyon laban sa mga typo, ngunit ang mga lumang walet ay hindi sumusuporta nito. Kapag hindi ch-in-eck, gagawa ng mga address na katugma sa mga lumang walet sa halip.</translation>
</message>
<message>
<source>Generate native segwit (Bech32) address</source>
@@ -2106,7 +1998,7 @@
</message>
<message>
<source>Bytes:</source>
- <translation>Bytes: </translation>
+ <translation>Bytes:</translation>
</message>
<message>
<source>Amount:</source>
@@ -2149,10 +2041,6 @@
<translation>Babala: Kasalukuyang hindi posible ang pagtatantiya sa bayarin.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>i-collapse ang fee-settings</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>
@@ -2190,7 +2078,7 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
</message>
<message>
<source>Clear all fields of the form.</source>
- <translation>Limasin ang lahat ng mga patlang ng form. </translation>
+ <translation>Limasin ang lahat ng mga patlang ng form.</translation>
</message>
<message>
<source>Dust:</source>
@@ -2314,7 +2202,7 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>Ang kabuuan ay lumampas sa iyong balanse kapag kasama ang %1 na bayad sa transaksyon. </translation>
+ <translation>Ang kabuuan ay lumampas sa iyong balanse kapag kasama ang %1 na bayad sa transaksyon.</translation>
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
@@ -2325,10 +2213,6 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Nabigo ang paggawa ng transaksyon!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Ang transaksyon ay tinanggihan sa mga sumusunod na dahilan: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Ang bayad na mas mataas sa %1 ay itinuturing na napakataas na bayad.</translation>
</message>
@@ -2380,12 +2264,8 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Piliin ang dating ginamit na address</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Ito ay normal na pagbabayad.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
- <translation>Ang Bitcoin address kung saan ipapadala and bayad </translation>
+ <translation>Ang Bitcoin address kung saan ipapadala and bayad</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2443,17 +2323,6 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Mag-enter ng label para sa address na ito upang idagdag ito sa iyong address book.</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Oo</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2514,7 +2383,7 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Pirmahan ang mensahe upang mapatunayan na pagmamay-ari mo ang Bitcoin address na ito </translation>
+ <translation>Pirmahan ang mensahe upang mapatunayan na pagmamay-ari mo ang Bitcoin address na ito</translation>
</message>
<message>
<source>Sign &amp;Message</source>
@@ -2752,7 +2621,7 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
</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>Ang mga nabuong coins ay dapat mayroong %1 blocks sa ibabaw bago sila gastusin. Kapag nabuo mo ang block na ito, nai-broadcast ito sa network na idadagdag sa block chain. Kung nabigo itong makapasok sa chain, magbabago ang katayuan nito sa "hindi tinanggap" at hindi it magagastos. Maaaring mangyari ito paminsan-minsan kung may isang node na bumuo ng isang block sa loob ng ilang segundo sa iyo. </translation>
+ <translation>Ang mga nabuong coins ay dapat mayroong %1 blocks sa ibabaw bago sila gastusin. Kapag nabuo mo ang block na ito, nai-broadcast ito sa network na idadagdag sa block chain. Kung nabigo itong makapasok sa chain, magbabago ang katayuan nito sa "hindi tinanggap" at hindi it magagastos. Maaaring mangyari ito paminsan-minsan kung may isang node na bumuo ng isang block sa loob ng ilang segundo sa iyo.</translation>
</message>
<message>
<source>Debug information</source>
@@ -3060,7 +2929,7 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<name>UnitDisplayStatusBarControl</name>
<message>
<source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Unit na gamit upang ipakita ang mga halaga. I-klik upang pumili ng isa pang yunit. </translation>
+ <translation>Unit na gamit upang ipakita ang mga halaga. I-klik upang pumili ng isa pang yunit.</translation>
</message>
</context>
<context>
@@ -3182,10 +3051,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Ang mga rescan ay hindi posible sa mode na pruned. Kailangan mong gamitin ang -reindex na i-do-download muli ang buong blockchain.</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>
@@ -3544,10 +3409,6 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Ito ang bayad sa transaksyon na maaari mong bayaran kapag hindi magagamit ang pagtantya sa bayad.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Kasama sa produktong ito ang software na binuo ng OpenSSL Project para magamit sa OpenSSL Toolkit %s at cryptographic software na isinulat ni Eric Young at UPnP software na isinulat ni Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts
index 8b3ed89849..1cddb413ef 100644
--- a/src/qt/locale/bitcoin_fr.ts
+++ b/src/qt/locale/bitcoin_fr.ts
@@ -67,11 +67,11 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>Voici 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 nouvelle adresse de réception' dans l'onglet Recevoir pour créer de nouvelles adresses.</translation>
+ <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>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -137,7 +137,7 @@
</message>
<message>
<source>Show passphrase</source>
- <translation>Afficher phrase secrète</translation>
+ <translation>Afficher la phrase de passe</translation>
</message>
<message>
<source>Encrypt wallet</source>
@@ -181,15 +181,15 @@
</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>Saisir la nouvelle phrase secrète pour le porte-monnaie.&lt;br/&gt;Veuillez utiliser une phrase secrète de &lt;b&gt;dix caractères aléatoires ou plus&lt;/b&gt;, ou &lt;b&gt;huit mots ou plus&lt;/b&gt;.</translation>
+ <translation>Saisissez la nouvelle phrase de passe du porte-monnaie.&lt;br/&gt;Veuillez utiliser une phrase de passe composée de &lt;b&gt;dix caractères aléatoires ou plus&lt;/b&gt;, ou de &lt;b&gt;huit mots ou plus&lt;/b&gt;.</translation>
</message>
<message>
<source>Enter the old passphrase and new passphrase for the wallet.</source>
- <translation>Saisir l'ancienne phrase secrète et la nouvelle phrase secrète pour le porte-monnaie.</translation>
+ <translation>Saisir 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>
- <translation>Souvenez-vous que chiffrer votre porte-monnaie ne peut pas complètement protéger vos bitcoins contre le vol par des programmes malveillants infectant votre ordinateur.</translation>
+ <translation>N’oubliez pas que le chiffrement de votre porte-monnaie ne peut pas protéger entièrement vos bitcoins contre le vol par des programmes malveillants qui infecteraient votre ordinateur.</translation>
</message>
<message>
<source>Wallet to be encrypted</source>
@@ -197,11 +197,11 @@
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation>Votre porte-monnaie est sur le point d'être chiffré.</translation>
+ <translation>Votre porte-monnaie est sur le point d’être chiffré.</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation>Votre porte-monnaie est maintenant chiffré.</translation>
+ <translation>Votre porte-monnaie est désormais chiffré.</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>
@@ -255,7 +255,7 @@
<name>BitcoinGUI</name>
<message>
<source>Sign &amp;message...</source>
- <translation>Signer un &amp;message...</translation>
+ <translation>Signer un &amp;message…</translation>
</message>
<message>
<source>Synchronizing with network...</source>
@@ -311,23 +311,23 @@
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Chiffrer le porte-monnaie...</translation>
+ <translation>&amp;Chiffrer le porte-monnaie…</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>Sauvegarder le &amp;porte-monnaie...</translation>
+ <translation>Sauvegarder le &amp;porte-monnaie…</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
- <translation>&amp;Changer la phrase de passe...</translation>
+ <translation>&amp;Changer la phrase de passe…</translation>
</message>
<message>
<source>Open &amp;URI...</source>
- <translation>Ouvrir une &amp;URI...</translation>
+ <translation>Ouvrir une &amp;URI…</translation>
</message>
<message>
<source>Create Wallet...</source>
- <translation>Créer un porte-monnaie...</translation>
+ <translation>Créer un porte-monnaie…</translation>
</message>
<message>
<source>Create a new wallet</source>
@@ -351,11 +351,11 @@
</message>
<message>
<source>Syncing Headers (%1%)...</source>
- <translation>Synchronisation des en-têtes (%1)...</translation>
+ <translation>Synchronisation des en-têtes (%1)…</translation>
</message>
<message>
<source>Reindexing blocks on disk...</source>
- <translation>Réindexation des blocs sur le disque...</translation>
+ <translation>Réindexation des blocs sur le disque…</translation>
</message>
<message>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
@@ -374,16 +374,8 @@
<translation>Modifier la phrase de passe utilisée pour le chiffrement du porte-monnaie</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Fenêtre de &amp;débogage</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Ouvrir une console de débogage et de diagnostic</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
- <translation>&amp;Vérifier un message...</translation>
+ <translation>&amp;Vérifier un message…</translation>
</message>
<message>
<source>&amp;Send</source>
@@ -442,10 +434,6 @@
<translation>Afficher la liste d’adresses de réception et d’étiquettes utilisées</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Ouvrir une URI bitcoin: ou une demande de paiement</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Options de ligne de &amp;commande</translation>
</message>
@@ -455,11 +443,11 @@
</message>
<message>
<source>Indexing blocks on disk...</source>
- <translation>Indexation des blocs sur le disque...</translation>
+ <translation>Indexation des blocs sur le disque…</translation>
</message>
<message>
<source>Processing blocks on disk...</source>
- <translation>Traitement des blocs sur le disque...</translation>
+ <translation>Traitement des blocs sur le disque…</translation>
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
@@ -494,6 +482,14 @@
<translation>À jour</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>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>&amp;Adresses d’envoi</translation>
</message>
@@ -502,6 +498,10 @@
<translation>&amp;Adresses de réception</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Ouvrir une URI bitcoin:</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Ouvrir le porte-monnaie</translation>
</message>
@@ -551,7 +551,7 @@
</message>
<message>
<source>Connecting to peers...</source>
- <translation>Connexion aux pairs...</translation>
+ <translation>Connexion aux pairs…</translation>
</message>
<message>
<source>Catching up...</source>
@@ -559,11 +559,11 @@
</message>
<message>
<source>Error: %1</source>
- <translation>Erreur : %1</translation>
+ <translation>Erreur : %1</translation>
</message>
<message>
<source>Warning: %1</source>
- <translation>Avertissement : %1</translation>
+ <translation>Avertissement : %1</translation>
</message>
<message>
<source>Date: %1
@@ -789,11 +789,11 @@
<name>CreateWalletActivity</name>
<message>
<source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
- <translation>Création du porte-monnaie &lt;b&gt;%1&lt;/b&gt;...</translation>
+ <translation>Création du porte-monnaie &lt;b&gt;%1&lt;/b&gt;…</translation>
</message>
<message>
<source>Create wallet failed</source>
- <translation>Création du porte-monnaie échouée</translation>
+ <translation>Échec de création du porte-monnaie</translation>
</message>
<message>
<source>Create wallet warning</source>
@@ -804,7 +804,7 @@
<name>CreateWalletDialog</name>
<message>
<source>Create Wallet</source>
- <translation>Créer porte-monnaie</translation>
+ <translation>Créer un porte-monnaie</translation>
</message>
<message>
<source>Wallet Name</source>
@@ -812,7 +812,7 @@
</message>
<message>
<source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
- <translation>Chiffrer le porte-monnaie. Le porte-monnaie sera chiffré avec une phrase secrète de votre choix.</translation>
+ <translation>Chiffrer le porte-monnaie. Le porte-monnaie sera chiffré avec une phrase de passe de votre choix.</translation>
</message>
<message>
<source>Encrypt Wallet</source>
@@ -820,19 +820,19 @@
</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>Désactiver les clés privées pour ce porte-monnaie. Les portes-monnaie avec des clés privées désactivées n'auront pas de clés privées et ne peuvent pas avoir une graine HD ou des clés privées importées. Ceci est idéal pour un porte-monnaie </translation>
+ <translation>Désactiver les clés privées pour ce porte-monnaie. Les porte-monnaie pour lesquels les clés privées sont désactivées n’auront aucune clé privée et ne pourront ni avoir de graine HD ni de clés privées importées. Cela est idéal pour les porte-monnaie juste-regarder.</translation>
</message>
<message>
<source>Disable Private Keys</source>
- <translation>Désactiver Clés Privées</translation>
+ <translation>Désactiver les clés privées</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>Créer un porte-monnaie vide. Les porte-monnaie vides n'ont pas de clés privées ou scripts initialement. Des clés privées et adresses peuvent être importées ou une graine HD peut être définie ultérieurement.</translation>
+ <translation>Créer un porte-monnaie vide. Les porte-monnaie vides n’ont initialement ni clé privée ni script. Ultérieurement, des clés privées et des adresses peuvent être importées ou une graine HD peut être définie.</translation>
</message>
<message>
<source>Make Blank Wallet</source>
- <translation>Créer Porte-Monnaie Vide</translation>
+ <translation>Créer un porte-monnaie vide</translation>
</message>
<message>
<source>Create</source>
@@ -924,10 +924,6 @@
<translation>version</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>À propos de %1</translation>
</message>
@@ -956,7 +952,7 @@
</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>Revenir sur ce paramètre requiert de re-télécharger l'entier de la chaîne de blocs. Il est plus rapide de télécharger la chaîne complète et de l'élaguer plus tard. Désactive certaines fonctionnalités avancées.</translation>
+ <translation>Rétablir ce paramètre à sa valeur antérieure exige de retélécharger la chaîne de blocs dans son intégralité. Il est plus rapide de télécharger la chaîne complète dans un premier temps et de l’élaguer ultérieurement. Désactive certaines fonctions avancées.</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>
@@ -980,7 +976,7 @@
</message>
<message>
<source>Discard blocks after verification, except most recent %1 GB (prune)</source>
- <translation>Jeter les blocs après vérification, à l'exception des %1 Go les plus récents (élagage)</translation>
+ <translation>Jeter les blocs après vérification, à l’exception des %1 Go les plus récents (élagage)</translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1016,7 +1012,7 @@
</message>
<message numerus="yes">
<source>(%n GB needed for full chain)</source>
- <translation><numerusform>(%n Go nécessaire pour la chaîne complète)</numerusform><numerusform>(%n Go nécessaires pour la chaîne complète)</numerusform></translation>
+ <translation><numerusform>(%n Go nécessaire pour la chaîne complète)</numerusform><numerusform>(%n Go nécessaires pour la chaîne complète)</numerusform></translation>
</message>
</context>
<context>
@@ -1039,7 +1035,7 @@
</message>
<message>
<source>Unknown...</source>
- <translation>Inconnu...</translation>
+ <translation>Inconnu…</translation>
</message>
<message>
<source>Last block time</source>
@@ -1055,7 +1051,7 @@
</message>
<message>
<source>calculating...</source>
- <translation>calcul en cours...</translation>
+ <translation>calcul en cours…</translation>
</message>
<message>
<source>Estimated time left until synced</source>
@@ -1066,6 +1062,14 @@
<translation>Cacher</translation>
</message>
<message>
+ <source>Esc</source>
+ <translation>Échap</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 est en cours de synchronisation. Il téléchargera les en-têtes et les blocs des pairs et les validera jusqu’à ce qu’il atteigne la fin de la chaîne de blocs.</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>Inconnu. Synchronisation des en-têtes (%1, %2)…</translation>
</message>
@@ -1073,25 +1077,13 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Ouvrir une URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Ouvrir une demande de paiement à partir d’une URI ou d’un fichier</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Ouvrir une URI bitcoin</translation>
</message>
<message>
<source>URI:</source>
<translation>URI :</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Choisir le fichier de demande de paiement</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Choisir le fichier de demande de paiement à ouvrir</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1101,7 +1093,7 @@
</message>
<message>
<source>Open wallet warning</source>
- <translation>Avertissement d'ouverture du porte-monnaie</translation>
+ <translation>Avertissement d’ouverture du porte-monnaie</translation>
</message>
<message>
<source>default wallet</source>
@@ -1188,7 +1180,7 @@
</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>Désactive certaines fonctions avancées, mais tous les blocs seront quand même validés entièrement. Changer ce paramètre à sa valeur antérieure exige de retélécharger la chaîne de blocs dans son intégralité. L’espace disque utilisé pourrait être un peu plus élevé.</translation>
+ <translation>Désactive certaines fonctions avancées, mais tous les blocs seront quand même validés entièrement. Rétablir ce paramètre à sa valeur antérieure exige de retélécharger la chaîne de blocs dans son intégralité. L’espace disque utilisé pourrait être un peu plus élevé.</translation>
</message>
<message>
<source>Prune &amp;block storage to</source>
@@ -1200,7 +1192,7 @@
</message>
<message>
<source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation>Changer ce paramètre à sa valeur antérieure exige de retélécharger la chaîne de blocs dans son intégralité.</translation>
+ <translation>Rétablir ce paramètre à sa valeur antérieure exige de retélécharger la chaîne de blocs dans son intégralité.</translation>
</message>
<message>
<source>MiB</source>
@@ -1481,24 +1473,16 @@
<translation>'bitcoin://' n’est pas une URI valide. Utilisez plutôt 'bitcoin:'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Vous utilisez une URL BIP70 qui ne sera plus prise en charge à l’avenir </translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>L’URL de récupération de la demande de paiement est invalide : %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Il est impossible de traiter la demande de paiement, car la prise en charge de BIP70 n’a pas été compilée dans le logiciel.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>Il est impossible de traiter la demande de paiement, car BIP70 n’est pas pris en charge.</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>En raison de faille de sécurité généralisées dans BIP70 il est vivement recommandé que les instructions des marchands pour changer de porte-monnaie soient ignorées.</translation>
+ <translation>En raison de failles de sécurité fréquentes dans BIP70, il est vivement recommandé d’ignorer les instructions de marchands qui demanderaient de changer de porte-monnaie.</translation>
</message>
<message>
<source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
- <translation>Si vous recevez cette erreur vous devriez demander au marchand de vous fournir un URI compatible avec BIP21.</translation>
+ <translation>Si vous recevez cette erreur, vous devriez demander au marchand de vous fournir une URI compatible avec BIP21.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1512,66 +1496,6 @@
<source>Payment request file handling</source>
<translation>Gestion des fichiers de demande de paiement</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Le fichier de demande de paiement ne peut pas être lu ! Cela peut être causé par un fichier de demande de paiement invalide.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Demande de paiement rejetée</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Le réseau de la demande de paiement ne correspond pas au réseau du client.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>La demande de paiement a expiré</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>La demande de paiement n’est pas initialisée.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Les demandes de paiements non vérifiées vers des scripts de paiement personnalisés ne sont pas prises en charge.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Demande de paiement invalide.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Le paiement demandé d’un montant de %1 est trop faible (considéré comme de la poussière).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Remboursement de %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>La demande de paiement %1 est trop grande (%2 octets, %3 octets permis).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Erreur de communication avec %1 : %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>La demande de paiement ne peut pas être analysée !</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Mauvaise réponse du serveur %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Erreur de demande réseau</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Le paiement a été confirmé</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1692,11 +1616,11 @@
</message>
<message>
<source>Error: %1</source>
- <translation>Erreur : %1</translation>
+ <translation>Erreur : %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>
+ <translation>%1 ne s’est pas encore arrêté en toute sécurité…</translation>
</message>
<message>
<source>unknown</source>
@@ -1707,7 +1631,7 @@
<name>QRImageWidget</name>
<message>
<source>&amp;Save Image...</source>
- <translation>&amp;Enregistrer l’image...</translation>
+ <translation>&amp;Enregistrer l’image…</translation>
</message>
<message>
<source>&amp;Copy Image</source>
@@ -1723,7 +1647,7 @@
</message>
<message>
<source>QR code support not available.</source>
- <translation>Support du code QR non disponible.</translation>
+ <translation>La prise en charge des codes QR n’est pas proposée.</translation>
</message>
<message>
<source>Save QR Code</source>
@@ -1749,10 +1673,6 @@
<translation>&amp;Informations</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Fenêtre de débogage</translation>
- </message>
- <message>
<source>General</source>
<translation>Générales</translation>
</message>
@@ -1873,6 +1793,10 @@
<translation>Agent utilisateur</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Fenêtre des nœuds</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>
@@ -2084,8 +2008,16 @@
<translation>Un montant facultatif à demander. Ne rien saisir 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>
+ <translation>Une étiquette facultative à associer à la nouvelle adresse de réception (utilisée par vous pour identifier une facture). Elle est aussi jointe à la demande de paiement.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Un message facultatif joint à la demande de paiement et qui peut être présenté à l’expéditeur.</translation>
+ </message>
+ <message>
<source>&amp;Create new receiving address</source>
- <translation>&amp;Créer nouvelle adresse de réception</translation>
+ <translation>&amp;Créer une nouvelle adresse de réception</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
@@ -2156,7 +2088,7 @@
</message>
<message>
<source>&amp;Save Image...</source>
- <translation>&amp;Enregistrer l’image...</translation>
+ <translation>&amp;Enregistrer l’image…</translation>
</message>
<message>
<source>Request payment to %1</source>
@@ -2234,7 +2166,7 @@
</message>
<message>
<source>Inputs...</source>
- <translation>Entrants...</translation>
+ <translation>Entrants…</translation>
</message>
<message>
<source>automatically selected</source>
@@ -2282,7 +2214,7 @@
</message>
<message>
<source>Choose...</source>
- <translation>Choisir...</translation>
+ <translation>Choisir…</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>
@@ -2293,10 +2225,6 @@
<translation>Avertissement : L’estimation des frais n’est actuellement pas possible.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>réduire les paramètres des frais</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>
@@ -2322,7 +2250,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(Les frais intelligents ne sont pas encore initialisés. Cela prend habituellement quelques blocs...)</translation>
+ <translation>(Les frais intelligents ne sont pas encore initialisés. Cela prend habituellement quelques blocs…)</translation>
</message>
<message>
<source>Send to multiple recipients at once</source>
@@ -2341,6 +2269,10 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Poussière :</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Cacher les paramètres de frais de transaction</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>Quand le volume des transactions est inférieur à l’espace dans les blocs, les mineurs et les nœuds de relais peuvent imposer des frais minimaux. Il est correct de payer ces frais minimaux, mais soyez conscient que cette transaction pourrait n’être jamais confirmée si la demande en transactions de bitcoins dépassait la capacité de traitement du réseau.</translation>
</message>
@@ -2409,6 +2341,14 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>%1 (%2 blocs)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Cr&amp;éer une transaction non signée</translation>
+ </message>
+ <message>
+ <source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
+ <translation>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>
+ </message>
+ <message>
<source> from wallet '%1'</source>
<translation>du porte-monnaie '%1'</translation>
</message>
@@ -2421,10 +2361,18 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>%1 à %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Souhaitez-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>
+ </message>
+ <message>
<source>or</source>
<translation>ou</translation>
</message>
@@ -2450,13 +2398,33 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>To review recipient list click "Show Details..."</source>
- <translation>Pour passer en revue la liste des destinataires cliquer sur "Afficher détails..."</translation>
+ <translation>Pour réviser la liste des destinataires, cliquez sur « Afficher les détails de la transaction… »</translation>
</message>
<message>
<source>Confirm send coins</source>
<translation>Confirmer l’envoi de pièces</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>L’adresse du destinataire est invalide. Veuillez la revérifier.</translation>
</message>
@@ -2481,10 +2449,6 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Échec de création de la transaction !</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>La transaction a été rejetée pour la raison suivante : %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Des frais supérieurs à %1 sont considérés comme ridiculement élevés.</translation>
</message>
@@ -2536,10 +2500,6 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Choisir une adresse déjà utilisée</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Ceci est un paiement normal.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>L’adresse Bitcoin à laquelle envoyer le paiement</translation>
</message>
@@ -2560,6 +2520,10 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Retirer cette entrée</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>Le montant à envoyer dans l’unité sélectionnée</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>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>
@@ -2599,23 +2563,12 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<source>Memo:</source>
<translation>Mémo :</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Saisir une étiquette pour cette adresse afin de l’ajouter à votre carnet d’adresses</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Oui</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
<message>
<source>%1 is shutting down...</source>
- <translation>Arrêt de %1...</translation>
+ <translation>Arrêt de %1…</translation>
</message>
<message>
<source>Do not shut down the computer until this window disappears.</source>
@@ -2697,6 +2650,14 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>L’adresse Bitcoin avec laquelle le message a été signé</translation>
</message>
<message>
+ <source>The signed message to verify</source>
+ <translation>Le message signé à vérifier</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>La signature donnée quand le message a été signé</translation>
+ </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>
</message>
@@ -2729,6 +2690,10 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Le déverrouillage du porte-monnaie a été annulé.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Aucune erreur</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>La clé privée pour l’adresse saisie n’est pas disponible.</translation>
</message>
@@ -2903,6 +2868,10 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Index des sorties</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(Le certificat n’a pas été vérifié)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Marchand</translation>
</message>
@@ -3227,7 +3196,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
- <translation>Voulez-vous vraiment fermer le porte-monnaie &lt;i&gt;%1&lt;/i&gt;?</translation>
+ <translation>Voulez-vous vraiment fermer le porte-monnaie &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>
@@ -3260,6 +3229,10 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Souhaitez-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>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Frais actuels :</translation>
</message>
@@ -3276,6 +3249,14 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Confirmer l’augmentation des frais</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>Impossible de créer une ébauche de la transaction.</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>La TBPS a été copiée</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Impossible de signer la transaction.</translation>
</message>
@@ -3342,16 +3323,12 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Les réanalyses sont impossibles en mode élagué. Vous devrez utiliser -reindex, ce qui téléchargera de nouveau la chaîne de blocs en entier.</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>
</message>
<message>
<source>Pruning blockstore...</source>
- <translation>Élagage du magasin de blocs...</translation>
+ <translation>Élagage du magasin de blocs…</translation>
</message>
<message>
<source>Unable to start HTTP server. See debug log for details.</source>
@@ -3446,6 +3423,14 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Une base de données de blocs corrompue a été détectée</translation>
</message>
<message>
+ <source>Could not find asmap file %s</source>
+ <translation>Le fichier asmap %s est introuvable</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>Impossible d’analyser le fichier asmap %s</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Voulez-vous reconstruire la base de données de blocs maintenant ?</translation>
</message>
@@ -3491,7 +3476,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Importing...</source>
- <translation>Importation...</translation>
+ <translation>Importation…</translation>
</message>
<message>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
@@ -3503,7 +3488,7 @@ 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>Permission P2P invalide : '%s'</translation>
</message>
<message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
@@ -3523,11 +3508,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>Type d’adresse inconnu '%s'</translation>
</message>
<message>
<source>Unknown change type '%s'</source>
- <translation>Type de monnaie inconnu « %s »</translation>
+ <translation>Type de monnaie inconnu '%s'</translation>
</message>
<message>
<source>Upgrading txindex database</source>
@@ -3535,15 +3520,15 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Loading P2P addresses...</source>
- <translation>Chargement des adresses P2P...</translation>
+ <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>
+ <translation>Erreur : L’espace disque est trop faible !</translation>
</message>
<message>
<source>Loading banlist...</source>
- <translation>Chargement de la liste d’interdiction...</translation>
+ <translation>Chargement de la liste d’interdiction…</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -3559,11 +3544,11 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Replaying blocks...</source>
- <translation>Relecture des blocs...</translation>
+ <translation>Relecture des blocs…</translation>
</message>
<message>
<source>Rewinding blocks...</source>
- <translation>Rebobinage des blocs...</translation>
+ <translation>Rebobinage des blocs…</translation>
</message>
<message>
<source>The source code is available from %s.</source>
@@ -3595,7 +3580,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Verifying blocks...</source>
- <translation>Vérification des blocs... </translation>
+ <translation>Vérification des blocs… </translation>
</message>
<message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
@@ -3651,7 +3636,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
- <translation>Le mode élagage est incompatible avec -blockfilterindex.</translation>
+ <translation>Le mode élagage n’est pas compatible avec -blockfilterindex.</translation>
</message>
<message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
@@ -3717,7 +3702,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Verifying wallet(s)...</source>
- <translation>Vérification des porte-monnaie...</translation>
+ <translation>Vérification des porte-monnaie…</translation>
</message>
<message>
<source>Warning: unknown new rules activated (versionbit %i)</source>
@@ -3725,7 +3710,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Zapping all transactions from wallet...</source>
- <translation>Supprimer toutes les transactions du porte-monnaie...</translation>
+ <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>
@@ -3736,10 +3721,6 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Il s’agit des frais de transaction que vous pourriez payer si aucune estimation de frais n’est proposée.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Ce produit comprend des programmes développés par le Projet OpenSSL pour être utilisés dans la boîte à outils OpenSSL %s, et un programme cryptographique écrit par Eric Young, ainsi qu’un programme UPnP écrit par Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
@@ -3757,7 +3738,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Starting network threads...</source>
- <translation>Démarrage des processus réseau...</translation>
+ <translation>Démarrage des processus réseau…</translation>
</message>
<message>
<source>The wallet will avoid paying less than the minimum relay fee.</source>
diff --git a/src/qt/locale/bitcoin_fr_FR.ts b/src/qt/locale/bitcoin_fr_FR.ts
deleted file mode 100644
index 10582127c4..0000000000
--- a/src/qt/locale/bitcoin_fr_FR.ts
+++ /dev/null
@@ -1,2314 +0,0 @@
-<TS language="fr_FR" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Faîtes un clique droit afin de modifier l'adresse ou l'étiquette</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Créer une nouvelle adresse</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Nouveau</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Copier l'adresse sélectionnée dans le presse-papiers</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Copie</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>F&amp;ermer</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Supprimer l'adresse sélectionnée de la liste</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Entrez une adresse ou une étiquette à rechercher</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exporter les données de l'onglet courant vers un fichier</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exporter...</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Supprimer</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Choisissez une adresse où envoyer les bitcoins</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Choisissez une adresse où recevoir les bitcoins</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>C&amp;hoisir</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Adresses d'envoi</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Adresses de réception</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>Ceci sont vos addresses Bitcoin pour envoyer vos paiements. Il faut toujours verifier les montants et l'addresse de reception avant de valider la transaction.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Ceci sont vos addresses Bitcoin pour recevoir vos paiements. Il est recommandé d'utiliser une nouvelle adresse de recepetion pour chaque transaction</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Copie Adresse</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Copier &amp;Étiquette </translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Éditer </translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Exporter la liste d'adresses</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Valeurs séparées par des virgules (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Échec de l'export</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Une erreur s'est produite en enregistrant la list d'adresses à %1. Merci de reéssayer.</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Étiquette</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresse</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(aucune étiquette)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Dialogue mot de passe</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Entrez la phrase de passe</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Nouvelle phrase de passe</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Répétez la phrase de passe</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Montrer le mot de passe</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Entrez une nouvelle phrase de passe pour le porte-monnaie.&lt;br/&gt;Veuillez utiliser une phrase de &lt;b&gt;10 caractères aléatoire ou plus&lt;/b&gt; ou bien de &lt;b&gt;huit mots ou plus&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Chiffrer le porte-monnaie</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Cette operation nécessite la phrase clé de votre porte-monnaie pour le déverouiller</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Déverrouiller le porte-monnaie</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Cette opération nécessite la phrase clé de votre porte-monnaie pour le décrypter.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Décrypter le porte-monnaie</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Changer la phrase de passe</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Entrez l'ancien mot de passe et le nouveau mot de passe pour le portefeuille</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Confirmer le chiffrement du porte-monnaie</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Attention : Si vous chiffrez votre portefeuille et que vous perdez votre mot de passe vous &lt;b&gt; PERDREZ TOUS VOS BITCOINS&lt;/b&gt; !</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Êtes-vous sûr de de vouloir crypter votre portefeuille ? </translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Portefeuille chiffré</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 va à présent se fermer pour terminer la procédure de cryptage. N'oubliez pas que le chiffrement de votre porte-monnaie ne peut pas fournir une protection totale contre le vol par des logiciels malveillants qui infecteraient votre ordinateur.</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>IMPORTANT: Toute sauvegarde préalable de votre porte-monnais devrait être emplacée par le fichier nouvellement généré et encrypté.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Le chiffrement du porte-monnaie a échoué</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Le chiffrement du porte-monnaie a échoué en raison d'une erreur interne. Votre porte-monnaie n'a pas été chiffré.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Les phrases de passe entrées ne correspondent pas.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Le déverrouillage du porte-monnaie a échoué</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>La phrase de passe entrée pour décrypter le porte-monnaie était incorrecte.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Le décryptage du porte-monnaie a échoué</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Le changement du mot de passe du portefeuille à été effectué avec succès.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Attention : La touche majuscule est enfoncé.</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Masque de sous réseau</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Banni jusque </translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Signer un &amp;message...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Synchronisation avec le réseau...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Vue d'ensemble</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Nœud</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Affiche une vue d'ensemble du porte-monnaie</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transactions</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Permet de parcourir l'historique des transactions</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>Qui&amp;tter</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Quitter l'application</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;À propos de %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Afficher les informations sur %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>À propos de &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Afficher des informations sur Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Options...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Modifier les options de configuration pour %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Chiffrer le portefeuille </translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Sauvegarder le portefeuille</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Modifier le mot de passe</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Adresses d'envoi</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>&amp;Adresses de réception</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Ouvrir &amp;URI</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Cliquez pour désactiver l'activité du réseau.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Activité réseau désactivée</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Cliquez pour réactiver l'activité réseau</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Synchronisation des entêtes (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Réindexer les blocs sur le disque...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Envoyer des pièces à une adresse Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Sauvegarder le porte-monnaie à un autre emplacement</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Modifier la phrase de passe utilisée pour le cryptage du porte-monnaie</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Fenêtre de débogage</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Ouvrir la console de débogage et de diagnostic</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Vérification du message</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Portefeuille</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Envoyer</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Réception</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Montrer / Cacher</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Montrer ou cacher la fenêtre principale</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Crypter les clé privées qui appartiennent votre portefeuille</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Signer vos 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 soient signés avec les adresses Bitcoin spécifiées</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Fichier</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Réglages</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Aide</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Barre d'outils des onglets</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Demander des paiements (générer QR codes et bitcoin: URIs)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Montrer la liste des adresses d'envois utilisées et les étiquettes</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Afficher la liste des labels et adresses de réception utilisées</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Ouvrir un bitcoin: URI ou demande de paiement</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Options de ligne de commande</translation>
- </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>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Indexation des blocs sur le disque...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Traitement des blocs sur le disque</translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>en retard de %1</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Le dernier bloc reçu a été généré %1.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Les transactions ne seront plus visible après ceci.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erreur</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Attention</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Information</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>À jour</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Afficher le %1 message d'aide pour récupérer une liste des options de ligne de commande Bitcoin</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>%1 client</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Connexion au pairs...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Rattrapage...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Date: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Montant:%1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Type: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Étiquette: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Adresse: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Transaction envoyée</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Transaction entrante</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>Génération de clé HD &lt;b&gt;activée&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>Génération de clé HD &lt;b&gt;désactivée&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>Le porte-monnaie est &lt;b&gt;chiffré&lt;/b&gt; et est actuellement &lt;b&gt;déverrouillé&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>Le porte-monnaie est &lt;b&gt;chiffré&lt;/b&gt; et est 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 a eu lieu. Bitcoin ne peut plus continuer en toute sécurité et va s'éteindre</translation>
- </message>
-</context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Sélection de pièce </translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Quantité:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Octets:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Montant :</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Frais:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Poussière: </translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Après frais:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Change:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(dé)sélectionné tout:</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Mode arbre</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Mode list</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Montant</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Reçu avec : </translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Reçue avec l'adresse</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Date</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Confirmations</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmée</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Copier l'adresse</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copier l'étiquette</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copier le montant</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copier l'ID de transaction</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Verrouiller les non dépensés</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Déverrouiller les non dépensés</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copier la quantité</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copier les frais</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Copier après les frais</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copier les octets</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copier la poussière </translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copier changement </translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 verrouillé)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>oui</translation>
- </message>
- <message>
- <source>no</source>
- <translation>non</translation>
- </message>
- <message>
- <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Cette étiquette devient rouge si un bénéficiaire reçoit une somme plus basse que la limite actuelle de poussière.</translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Peut varier de +/- %1 satoshi(s) par entrée.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(aucune étiquette)</translation>
- </message>
- <message>
- <source>change from %1 (%2)</source>
- <translation>changement de %1 (%2)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation>(changement)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Éditer l'adresse</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Étiquette</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>L'étiquette associée à cette entrée du carnet d'adresses</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>L'adresse associée avec cette entrée du carnet d'adresses. Ne peut être modifiée que pour les adresses d'envoi.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Adresse</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Nouvelle adresse d'envoi</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Éditer l'adresse de réception</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Éditer l'adresse d'envoi</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>L'adresse entrée "%1" n'est pas une adresse Bitcoin valide.</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Impossible de déverrouiller le porte-monnaie.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Échec de la génération de la nouvelle clef.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Un nouveau répertoire de données sera créé. </translation>
- </message>
- <message>
- <source>name</source>
- <translation>nom</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>Le répertoire existe déjà. Ajouter %1 si vous voulez créer un nouveau répertoire ici.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Le chemin existe déjà et ce n'est pas un répertoire. </translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Impossible de créer un répertoire ici.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>version</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>A propos %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Options de ligne de commande</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Bienvenue </translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Bienvenue sur %1.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Utiliser le répertoire par défaut </translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Utiliser votre propre répertoire</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation>Environ %1 GB de données seront stockées dans ce répertoire, et cela augmentera au cours du temps.</translation>
- </message>
- <message>
- <source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>Environ %1 GB de données seront stockées dans ce répertoire.</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation>Le porte-monnaie sera aussi stocké dans ce répertoire.</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Erreur: Le répertoire de données "%1" n'a pas pu être créé. </translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erreur</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Formulaire</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Cacher</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Ouvrir URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Ouvrir une demande de paiement depuis une URI ou un fichier</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Sélectionner un fichier de demande de paiement</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Sélectionnez le fichier de demande de paiement à ouvrir</translation>
- </message>
-</context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Options</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Principal</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Taille du cache de la base de données.</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MO</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Adresse IP du proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Réinitialiser toutes les options du client par défaut.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Options de réinitialisation </translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Réseau</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Expert</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>Ouvrir le port du client Bitcoin automatiquement sur le routeur. Cela ne fonctionne que si votre routeur supporte l'UPnP et si la fonctionnalité est activée.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Ouvrir le port avec l'&amp;UPnP</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 du proxy (e.g. 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation>Utilisé pour contacter des pairs 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;Fenêtre</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimiser dans la barre système au lieu de la barre des tâches</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>Mi&amp;nimiser lors de la fermeture</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Afficher</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>Interface utilisateur &amp;langage:</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;OK</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Annuler </translation>
- </message>
- <message>
- <source>default</source>
- <translation>defaut</translation>
- </message>
- <message>
- <source>none</source>
- <translation>aucun</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Confirmer les options de réinitialisation </translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Redémarrage du client nécessaire pour activer les changements.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erreur</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Ce changement nécessiterait un redémarrage du client.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>L'adresse du proxy est invalide.</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Formulaire</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Regarder seulement:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Disponible: </translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>En attente:</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Immature:</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>Votre balance totale courante</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Dépensable: </translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Transactions récentes </translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Erreur lors de la requête de paiement</translation>
- </message>
- <message>
- <source>Invalid payment address %1</source>
- <translation>Adresse de paiement invalide %1</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Requête de paiement rejetée </translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Demande de paiement expirée.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>La demande de paiement n'a pas été initialisée.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Demande de paiement invalide.</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Remboursement de %1</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Mauvaise réponse du serveur %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Erreur de demande de réseau</translation>
- </message>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>Agent Utilisateur</translation>
- </message>
- <message>
- <source>Node/Service</source>
- <translation>Nœud/Service </translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Envoyé</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Reçu </translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Montant</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Entrer une adresse Bitcoin (e.g. %1)</translation>
- </message>
- <message>
- <source>%1 d</source>
- <translation>%1 j</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>Aucun</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 et %2</translation>
- </message>
- <message>
- <source>%1 B</source>
- <translation>%1 O</translation>
- </message>
- <message>
- <source>%1 KB</source>
- <translation>%1 KO</translation>
- </message>
- <message>
- <source>%1 MB</source>
- <translation>%1 MO</translation>
- </message>
- <message>
- <source>%1 GB</source>
- <translation>%1 GO</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>inconnu</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Sauvegarder image</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>&amp;Copier image</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>Sauvegarder QR code</translation>
- </message>
- <message>
- <source>PNG Image (*.png)</source>
- <translation>Image PNG (*.png)</translation>
- </message>
-</context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>N/A</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Version du client</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Information</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Fenêtre de débogage </translation>
- </message>
- <message>
- <source>General</source>
- <translation>Général</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>Version BerkeleyDButilisée </translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Le temps de démarrage</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Réseau</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Nom</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Nombre de connexions</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Chaîne de bloc </translation>
- </message>
- <message>
- <source>Current number of blocks</source>
- <translation>Nombre courant de blocs</translation>
- </message>
- <message>
- <source>Memory Pool</source>
- <translation>Mémoire du pool</translation>
- </message>
- <message>
- <source>Current number of transactions</source>
- <translation>Nombre courant de transactions</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Usage de la mémoire</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Reçu </translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Envoyé</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Pairs</translation>
- </message>
- <message>
- <source>Banned peers</source>
- <translation>Pairs bannis</translation>
- </message>
- <message>
- <source>Whitelisted</source>
- <translation>Autorisé par la liste</translation>
- </message>
- <message>
- <source>Direction</source>
- <translation>Direction</translation>
- </message>
- <message>
- <source>Version</source>
- <translation>Version</translation>
- </message>
- <message>
- <source>Starting Block</source>
- <translation>Bloc de départ</translation>
- </message>
- <message>
- <source>Synced Blocks</source>
- <translation>Blocs Synchronisés </translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>Agent Utilisateur</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Services</translation>
- </message>
- <message>
- <source>Ban Score</source>
- <translation>Score de ban</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Temps de connexion</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Dernier envoyé</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Dernier reçu</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Temps du ping</translation>
- </message>
- <message>
- <source>Ping Wait</source>
- <translation>Attente du ping</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Ouvert</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Console</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Trafic réseau</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Totaux</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Entrée:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Sortie:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Fichier du journal de débogage</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Nettoyer la console</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;heure</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;jour</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;semaine</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;an</translation>
- </message>
- <message>
- <source>via %1</source>
- <translation>via %1</translation>
- </message>
- <message>
- <source>never</source>
- <translation>jamais</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>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>Montant :</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Étiquette :</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>Message :</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Nettoyer tous les champs du formulaire.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Nettoyer</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>Historique des demandes de paiements.</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Demande de paiement</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Montrer</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Retirer</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copier l'étiquette</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Copier message</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copier le montant</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>QR Code</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Copier &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Copier &amp;Adresse</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Sauvegarder image</translation>
- </message>
- <message>
- <source>Request payment to %1</source>
- <translation>Demande de paiement à %1</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation>Informations de paiement</translation>
- </message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresse</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Montant</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Étiquette</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Message</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Portefeuille</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Date</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Étiquette</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Message</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(aucune étiquette)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation>(pas de message)</translation>
- </message>
- <message>
- <source>Requested</source>
- <translation>Demandé</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Envoyer des pièces</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Sorties...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>Automatiquement sélectionné </translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Fonds insuffisants</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Quantité:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Octets:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Montant :</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Frais:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Après frais:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Change:</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Frais de transaction</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Choisir...</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>par kilo octet</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Cacher</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Recommandé: </translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Envoyer des pièces à plusieurs destinataires à la fois</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Nettoyer tous les champs du formulaire.</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Poussière: </translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Nettoyer &amp;Tout</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Solde :</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Confirmer l'action d'envoi</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>E&amp;voyer</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copier la quantité</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copier le montant</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copier les frais</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Copier après les frais</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copier les octets</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copier la poussière </translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copier changement </translation>
- </message>
- <message>
- <source>%1 to %2</source>
- <translation>%1 à %2</translation>
- </message>
- <message>
- <source>Are you sure you want to send?</source>
- <translation>Êtes-vous sûr de vouloir envoyer ?</translation>
- </message>
- <message>
- <source>or</source>
- <translation>ou</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Frais de transaction</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation>Confirmer l'envoi des pièces</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation>Le montant à payer doit être supérieur à 0.</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation>Le montant excède votre balance. </translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation>Échec de la création de la transaction </translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Demande de paiement expirée.</translation>
- </message>
- <message>
- <source>Pay only the required fee of %1</source>
- <translation>Payer seulement les frais obligatoire de %1</translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation>Attention: Adresse Bitcoin Invalide</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(aucune étiquette)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>&amp;Montant :</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>Payer &amp;à :</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Étiquette :</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Choisir une adresse précédemment utilisée </translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>C'est un paiement normal.</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Coller une adresse depuis le presse-papiers</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Retirer cette entrée</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Message :</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Payer à :</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Memo:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Entrez une étiquette pour cette adresse afin de l'ajouter à votre carnet d'adresses</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Oui</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Signer le message</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Choisir une adresse précédemment utilisée </translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Coller une adresse depuis le presse-papiers</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Entrez ici le message que vous désirez signer</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Signature</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Copier l'adresse courante dans le presse papier</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>&amp;Signer le message</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Nettoyer &amp;Tout</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Vérifier message</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Vérifier &amp;Message</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation>L'adresse entrée est invalide. </translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Vérifiez l'adresse et réessayer. </translation>
- </message>
- <message>
- <source>Message signed.</source>
- <translation>Message signé. </translation>
- </message>
- <message>
- <source>Please check the signature and try again.</source>
- <translation>Vérifiez la signature et réessayer.</translation>
- </message>
- <message>
- <source>Message verification failed.</source>
- <translation>Vérification du message échouée.</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation>Message vérifié. </translation>
- </message>
-</context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KO/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Open until %1</source>
- <translation>Ouvert jusqu'à %1</translation>
- </message>
- <message>
- <source>abandoned</source>
- <translation>abandoné</translation>
- </message>
- <message>
- <source>%1/unconfirmed</source>
- <translation>%1/non confirmée</translation>
- </message>
- <message>
- <source>%1 confirmations</source>
- <translation>%1 confirmations</translation>
- </message>
- <message>
- <source>Status</source>
- <translation>État</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Date</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Source</translation>
- </message>
- <message>
- <source>Generated</source>
- <translation>Généré</translation>
- </message>
- <message>
- <source>From</source>
- <translation>De</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>inconnu</translation>
- </message>
- <message>
- <source>To</source>
- <translation>Á</translation>
- </message>
- <message>
- <source>own address</source>
- <translation>Votre adresse</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>Lecture uniquement</translation>
- </message>
- <message>
- <source>label</source>
- <translation>Étiquette </translation>
- </message>
- <message>
- <source>Credit</source>
- <translation>Crédit</translation>
- </message>
- <message>
- <source>not accepted</source>
- <translation>Pas accepté</translation>
- </message>
- <message>
- <source>Debit</source>
- <translation>Débit</translation>
- </message>
- <message>
- <source>Total debit</source>
- <translation>Débit total</translation>
- </message>
- <message>
- <source>Total credit</source>
- <translation>Crédit total </translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Frais de transaction</translation>
- </message>
- <message>
- <source>Net amount</source>
- <translation>Montant net</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Message</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Commentaire </translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation>ID de transaction</translation>
- </message>
- <message>
- <source>Merchant</source>
- <translation>Marchant</translation>
- </message>
- <message>
- <source>Debug information</source>
- <translation>Information de débogage </translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation>Transaction</translation>
- </message>
- <message>
- <source>Inputs</source>
- <translation>Entrées </translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Montant</translation>
- </message>
- <message>
- <source>true</source>
- <translation>vrai</translation>
- </message>
- <message>
- <source>false</source>
- <translation>faux</translation>
- </message>
-</context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Ce panneau affiche une description détaillée de la transaction</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>Étiquette</translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Ouvert jusqu'à %1</translation>
- </message>
- <message>
- <source>Unconfirmed</source>
- <translation>Non Confirmé</translation>
- </message>
- <message>
- <source>Abandoned</source>
- <translation>Abandoné</translation>
- </message>
- <message>
- <source>Confirmed (%1 confirmations)</source>
- <translation>Confirmée (%1 confirmations)</translation>
- </message>
- <message>
- <source>Generated but not accepted</source>
- <translation>Généré mais pas accepté</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Reçues avec</translation>
- </message>
- <message>
- <source>Received from</source>
- <translation>Reçue de</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Envoyées à</translation>
- </message>
- <message>
- <source>Payment to yourself</source>
- <translation>Paiement à vous-même</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Extraction</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>Lecture uniquement</translation>
- </message>
- <message>
- <source>(n/a)</source>
- <translation>(indisponible)</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(aucune étiquette)</translation>
- </message>
- <message>
- <source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>État de la transaction. Laissez le pointeur de la souris sur ce champ pour voir le nombre de confirmations.</translation>
- </message>
- <message>
- <source>Date and time that the transaction was received.</source>
- <translation>Date et heure de réception de la transaction.</translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation>Type de transaction.</translation>
- </message>
- <message>
- <source>Amount removed from or added to balance.</source>
- <translation>Montant ajouté au ou enlevé du solde.</translation>
- </message>
-</context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Toutes</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Aujourd'hui</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>Cette semaine</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>Ce mois</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Mois dernier</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Cette année</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Intervalle...</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Reçues avec</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Envoyées à</translation>
- </message>
- <message>
- <source>To yourself</source>
- <translation>À vous-même</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Extraction</translation>
- </message>
- <message>
- <source>Other</source>
- <translation>Autres</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation>Montant min</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Copier l'adresse</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copier l'étiquette</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copier le montant</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copier l'ID de transaction</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Éditer l'étiquette</translation>
- </message>
- <message>
- <source>Show transaction details</source>
- <translation>Afficher les détails de la transaction</translation>
- </message>
- <message>
- <source>Export Transaction History</source>
- <translation>Exporter l'historique des transactions</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Valeurs séparées par des virgules (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmée</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Date</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Type</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Étiquette</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresse</translation>
- </message>
- <message>
- <source>ID</source>
- <translation>ID</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Échec de l'export</translation>
- </message>
- <message>
- <source>Exporting Successful</source>
- <translation>Export réalisé avec sucés </translation>
- </message>
- <message>
- <source>Range:</source>
- <translation>Intervalle :</translation>
- </message>
- <message>
- <source>to</source>
- <translation>à</translation>
- </message>
-</context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>Aucun portefeuille a été chargé.</translation>
- </message>
-</context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Envoyer des pièces</translation>
- </message>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exporter...</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exporter les données de l'onglet courant vers un fichier</translation>
- </message>
- <message>
- <source>Backup Wallet</source>
- <translation>Sauvegarder le porte-monnaie</translation>
- </message>
- <message>
- <source>Wallet Data (*.dat)</source>
- <translation>Données de porte-monnaie (*.dat)</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>La sauvegarde a échoué</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Sauvegarde réussie</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <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>
- </message>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>
-Importation ...</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Vérifications des blocs...</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Information</translation>
- </message>
- <message>
- <source>Invalid -onion address or hostname: '%s'</source>
- <translation>Adresse ou nom d'hôte -onion invalide: '%s'</translation>
- </message>
- <message>
- <source>Invalid -proxy address or hostname: '%s'</source>
- <translation>Adresse -proxy invalide: '%s'</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Transaction signée échouée</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>C'est un logiciel expérimental.</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Montant de la transaction trop bas</translation>
- </message>
- <message>
- <source>Transaction too large for fee policy</source>
- <translation>Montant de la transaction trop élevé pour la politique de frais</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Transaction trop grande</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Attention</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Fonds insuffisants</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Chargement de l'index des blocs...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Chargement du porte-monnaie...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Vous ne pouvez pas rétrograder votre portefeuille</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Nouvelle analyse...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Chargement terminé</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erreur</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts
deleted file mode 100644
index 851b111fd6..0000000000
--- a/src/qt/locale/bitcoin_gl.ts
+++ /dev/null
@@ -1,1349 +0,0 @@
-<TS language="gl" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Create a new address</source>
- <translation>Crear un novo enderezo</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Novo</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Copiar o enderezo seleccionado ao cartafol</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Copiar</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>&amp;Pechar</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Borrar o enderezo actualmente seleccionado da listaxe</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Introduce enderezo ou etiqueta para buscar</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportar os datos da pestaña actual a un arquivo.</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportar</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Borrar</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Enviando enderezos</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Recibindo enderezos</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Copiar Enderezo</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Editar</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Exportar Lista de Enderezos</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Arquivo separado por comas (*.csv)</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Enderezo</translation>
- </message>
- </context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Diálogo de Contrasinal</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Introduce contrasinal</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Novo contrasinal</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Repite novo contrasinal</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Desbloquear moedeiro</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Desencriptar moedeiro</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Moedeiro encriptado</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Aviso: O Bloqueo de Maiúsculas está activo!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- </context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>&amp;Asinar mensaxe...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Sincronizando coa rede...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Vista xeral</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Amosar vista xeral do moedeiro</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transaccións</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Navegar historial de transaccións</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>&amp;Saír</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Saír da aplicación</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Acerca de &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Amosar información acerca de Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Opcións...</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Encriptar Moedeiro...</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>Copia de &amp;Seguridade do Moedeiro...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Cambiar contrasinal...</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>Moedeiro:</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Reindexando bloques no disco...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Enviar moedas a unha dirección Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Facer copia de seguridade do moedeiro noutra localización</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Cambiar o contrasinal empregado para a encriptación do moedeiro</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>Xanela de &amp;Depuración</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abrir consola de depuración e diagnóstico</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Verificar mensaxe...</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Enviar</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Recibir</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Amosar/Agachar</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Amosar ou agachar a xanela principal</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Encriptar as claves privadas que pertencen ao teu moedeiro</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Asina mensaxes cos teus enderezos Bitcoin para probar que che pertencen</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Verifica mensaxes para asegurar que foron asinados con enderezos Bitcoin específicos.</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Arquivo</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>Axus&amp;tes</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>A&amp;xuda</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Barra de ferramentas</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Solicitar pagamentos (xera códigos QR e bitcoin: URIs)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Amosar a listaxe de enderezos e etiquetas usadas para enviar</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Amosar a listaxe de etiquetas e enderezos usadas para recibir</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abrir un bitcoin: URI ou solicitude de pagamento</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>Opcións da liña de comandos</translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 detrás</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>O último bloque recibido foi xerado fai %1.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>As transaccións despois desta non serán aínda visibles.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erro</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Aviso</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Información</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Actualizado</translation>
- </message>
- <message>
- <source>Open Wallet</source>
- <translation>Abrir Moedeiro</translation>
- </message>
- <message>
- <source>Open a wallet</source>
- <translation>Abrir un moedeiro</translation>
- </message>
- <message>
- <source>Close Wallet...</source>
- <translation>Pechar Moedeiro...</translation>
- </message>
- <message>
- <source>Close wallet</source>
- <translation>Pechar moedeiro</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>moedeiro por defecto</translation>
- </message>
- <message>
- <source>No wallets available</source>
- <translation>Non hai moedeiros dispoñíbeis</translation>
- </message>
- <message>
- <source>&amp;Window</source>
- <translation>&amp;Xanela</translation>
- </message>
- <message>
- <source>Minimize</source>
- <translation>Minimizar</translation>
- </message>
- <message>
- <source>Zoom</source>
- <translation>Zoom</translation>
- </message>
- <message>
- <source>Main Window</source>
- <translation>Xanela Principal</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>%1 cliente</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Poñendo ao día...</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Transacción enviada</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Transacción entrante</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>O moedeiro está &lt;b&gt;encriptado&lt;/b&gt; e actualmente &lt;b&gt;desbloqueado&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation>O moedeiro está &lt;b&gt;encriptado&lt;/b&gt; e actualmente &lt;b&gt;bloqueado&lt;/b&gt;</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Quantity:</source>
- <translation>Cantidade:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Importe:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Taxa:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Cambiar:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(des)selecciona todo</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Modo árbore</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Modo lista</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantidade</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Confirmacións</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmado</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>si</translation>
- </message>
- <message>
- <source>no</source>
- <translation>non</translation>
- </message>
- </context>
-<context>
- <name>CreateWalletActivity</name>
- </context>
-<context>
- <name>CreateWalletDialog</name>
- </context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Modificar Enderezo</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Etiqueta</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>A etiqueta asociada con esta entrada da listaxe de enderezos</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>O enderezo asociado con esta entrada na listaxe de enderezos. Esta so pode ser modificada por enderezos para enviar.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Enderezo</translation>
- </message>
- </context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Crearáse un novo directorio de datos.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>nome</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>O directorio xa existe. Engade %1 se queres crear un novo directorio aquí.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>A ruta xa existe e non é un directorio.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Non se pode crear directorio de datos aquí</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>versión</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Opcións da liña de comandos</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Benvido</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Benvido a %1.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Empregar o directorio de datos por defecto</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Empregar un directorio de datos personalizado</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erro</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Formulario</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Hora do último bloque</translation>
- </message>
- <message>
- <source>calculating...</source>
- <translation>calculando...</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Abrir URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Abrir solicitude de pagamento dende URI ou ficheiro</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Seleccionar ficheiro de solicitude de pagamento</translation>
- </message>
- </context>
-<context>
- <name>OpenWalletActivity</name>
- <message>
- <source>default wallet</source>
- <translation>moedeiro por defecto</translation>
- </message>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Opcións</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Principal</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Restaurar todas as opcións de cliente ás por defecto</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>Opcións de &amp;Restaurar</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Rede</translation>
- </message>
- <message>
- <source>GB</source>
- <translation>GB</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>Moedeiro</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Experto</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>Abrir automáticamente o porto do cliente Bitcoin no router. Esto so funciona se o teu router soporta UPnP e está habilitado.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Mapear porto empregando &amp;UPnP</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>&amp;IP do Proxy:</translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>&amp;Porto:</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Porto do proxy (exemplo: 9050)</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;Xanela</translation>
- </message>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Amosar so unha icona na bandexa tras minimizar a xanela.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimizar á bandexa en lugar de á barra de tarefas.</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>M&amp;inimizar ao pechar</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Visualización</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>&amp;Linguaxe de interface de usuario:</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Unidade na que amosar as cantidades:</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Escolle a unidade de subdivisión por defecto para amosar na interface e ao enviar moedas.</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;OK</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Cancelar</translation>
- </message>
- <message>
- <source>default</source>
- <translation>por defecto</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Confirmar opcións de restaurar</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Opcións de configuración</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erro</translation>
- </message>
- <message>
- <source>The configuration file could not be opened.</source>
- <translation>O arquivo de configuración non puido ser aberto.</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Este cambio requeriría un reinicio do cliente.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>O enderezo de proxy suministrado é inválido.</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Formulario</translation>
- </message>
- <message>
- <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
- <translation>A información amosada por estar desactualizada. O teu moedeiro sincronízase automáticamente coa rede Bitcoin despois de que se estableza unha conexión, mais este proceso non está todavía rematado.</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>O teu balance actualmente dispoñible</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 de transaccións que aínda teñen que ser confirmadas, e non contan todavía dentro do balance gastable</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Inmaduro:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>O balance minado todavía non madurou</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Total:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>O teu balance actual total</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Transaccións recentes</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Erro na solicitude de pagamento</translation>
- </message>
- <message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Estás a usar unha URL BIP70 que non será soportada no futuro.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Solicitude de pagamento rexeitada</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Solicitude de pagamento expirada.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>A solicitude de pagamento non está inicializada.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Solicitude de pagamento inválida.</translation>
- </message>
- </context>
-<context>
- <name>PeerTableModel</name>
- </context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Cantidade</translation>
- </message>
- <message>
- <source>%1 h</source>
- <translation>%1 h</translation>
- </message>
- <message>
- <source>%1 m</source>
- <translation>%1 m</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>N/A</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>Erro: O directorio de datos especificado "%1" non existe.</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>descoñecido</translation>
- </message>
-</context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Gardar Imaxe...</translation>
- </message>
- <message>
- <source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation>A URI resultante é demasiado larga, tenta reducir o texto para a etiqueta / mensaxe.</translation>
- </message>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation>Erro codificando URI nun Código QR.</translation>
- </message>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>N/A</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Versión do cliente</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Información</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Xanela de Depuración</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Tempo de arranque</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Rede</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Número de conexións</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Cadea 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 do último bloque</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Abrir</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Consola</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Tráfico de Rede</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Totais</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Dentro:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Fóra:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Arquivo de log de depuración</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Limpar consola</translation>
- </message>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>&amp;Cantidade:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Etiqueta:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Mensaxe:</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Limpar tódolos campos do formulario</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Limpar</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>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Copiar &amp;Enderezo</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Gardar Imaxe...</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Enderezo</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantidade</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Moedeiro</translation>
- </message>
-</context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Moedas Enviadas</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Fondos insuficientes</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Cantidade:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Importe:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Taxa:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Cambiar:</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Tarifa de transacción:</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Enviar a múltiples receptores á vez</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>Engadir &amp;Receptor</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Limpar tódolos campos do formulario</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Limpar &amp;Todo</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Balance:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Confirmar a acción de envío</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>&amp;Enviar</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Tarifa de transacción</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Solicitude de pagamento expirada.</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>&amp;Cantidade:</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>Pagar &amp;A:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Etiqueta:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Escoller enderezo previamente usado</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Este é un pagamento normal</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Pegar enderezo dende portapapeis</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Eliminar esta entrada</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Mensaxe:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Introduce unha etiqueta para esta dirección para engadila á listaxe de direccións empregadas</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Pagar A:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Memo:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Sinaturas - Asinar / Verificar unha Mensaxe</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Asinar Mensaxe</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Escoller dirección previamente usada</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Pegar enderezo dende portapapeis</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Introduce a mensaxe que queres asinar aquí</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Sinatura</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Copiar a sinatura actual ao portapapeis do sistema</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Asina a mensaxe para probar que posúes este enderezo Bitcoin</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Asinar &amp;Mensaxe</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Restaurar todos os campos de sinatura de mensaxe</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Limpar &amp;Todo</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Verificar Mensaxe</translation>
- </message>
- <message>
- <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Verificar a mensaxe para asegurar que foi asinada coa dirección Bitcoin especificada</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Verificar &amp;Mensaxe</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Restaurar todos os campos de verificación de mensaxe</translation>
- </message>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KB/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>descoñecido</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Tarifa de transacción</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantidade</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Este panel amosa unha descripción detallada da transacción</translation>
- </message>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Arquivo separado por comas (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmado</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Enderezo</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletController</name>
- <message>
- <source>Close wallet</source>
- <translation>Pechar moedeiro</translation>
- </message>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Moedas Enviadas</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>moedeiro por defecto</translation>
- </message>
-</context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportar</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportar os datos da pestaña actual a un arquivo.</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Corrupted block database detected</source>
- <translation>Detectada base de datos de bloques corrupta.</translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Queres reconstruír a base de datos de bloques agora?</translation>
- </message>
- <message>
- <source>Error initializing block database</source>
- <translation>Erro inicializando a base de datos de bloques</translation>
- </message>
- <message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Erro inicializando entorno de base de datos de moedeiro %s!</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Erro cargando base de datos do bloque</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Erro abrindo base de datos de bloques</translation>
- </message>
- <message>
- <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>Fallou escoitar en calquera porto. Emprega -listen=0 se queres isto.</translation>
- </message>
- <message>
- <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>Bloque xénese incorrecto ou non existente. Datadir erróneo para a rede?</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>Non hai suficientes descritores de arquivo dispoñibles.</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Verificando bloques...</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Fallou a sinatura da transacción</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>A cantidade da transacción é demasiado pequena</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>A transacción é demasiado grande</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Rede descoñecida especificada en -onlynet: '%s'</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Fondos insuficientes</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Cargando índice de bloques...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Cargando moedeiro...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Non se pode desactualizar o moedeiro</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Rescaneando...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Carga completa</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts
index 0553c20607..78570e8bbf 100644
--- a/src/qt/locale/bitcoin_he.ts
+++ b/src/qt/locale/bitcoin_he.ts
@@ -70,6 +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>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;העתק כתובת</translation>
</message>
@@ -132,6 +136,10 @@
<translation>חזור על הסיסמה החדשה</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>הצג סיסמה</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>הצפנת הארנק</translation>
</message>
@@ -334,14 +342,6 @@
<translation>שנה את הסיסמא המשמשת להצפנת הארנק</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>חלון &amp;ניפוי</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>פתיחת לוח הבקרה לאבחון ולניפוי</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;אימות הודעה…</translation>
</message>
@@ -402,10 +402,6 @@
<translation>הצגת רשימת הכתובות והתוויות הנמצאות בשימוש</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>פתיחת ביטקוין: כתובת משאב או בקשת תשלום</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>אפשרויות &amp;שורת הפקודה</translation>
</message>
@@ -832,10 +828,6 @@
<translation>גרסה</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-סיביות)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>אודות %1</translation>
</message>
@@ -969,25 +961,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>פתיחת כתובת משאב</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>פתיחת בקשת תשלום מכתובת משאב או מקובץ</translation>
- </message>
- <message>
<source>URI:</source>
<translation>כתובת משאב:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>בחירת קובץ בקשת תשלום</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>בחירת קובץ בקשת תשלום לפתיחה</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1080,7 +1056,7 @@
</message>
<message>
<source>Prune &amp;block storage to</source>
- <translation> יש לגזום את &amp;מאגר הבלוקים אל</translation>
+ <translation>יש לגזום את &amp;מאגר הבלוקים אל</translation>
</message>
<message>
<source>GB</source>
@@ -1369,18 +1345,6 @@
<translation>'//:bitcoin' אינה כתובת URI תקינה. השתמשו במקום ב ':bitcoin'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>אתם משתמשים בכתובת אינטרנט BIP70 אשר לא תתמך בעתיד</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>כתובת ה URL של בקשת התשלום אינה תקינה : %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>אין אפשרות לבצע עיבוד בקשת תשלום כיון שהתמיכה ב BIP70 אינה כלולה בקוד.</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>כתובת תשלום שגויה %1</translation>
</message>
@@ -1392,66 +1356,6 @@
<source>Payment request file handling</source>
<translation>טיפול בקבצי בקשות תשלום</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>לא ניתן לקרוא את קובץ בקשת התשלום! מצב כזה יכול לקרות בעקבות קובץ בקשת תשלום פגום.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>בקשת התשלום נדחתה</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>רשת בקשת התשלום אינה תואמת לרשת הלקוח.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>בקשת התשלום פגה.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>בקשת התשלום לא הופעלה.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>בקשות תשלום לתסריטי תשלום מותאמים אישית שלא עברו וידוא אינן נתמכות.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>בקשת תשלום שגויה.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>הסכום על סך %1 הנדרש לתשלום קטן מדי (נחשב לאבק)</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>זיכוי מאת %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>בקשת התשלום %1 גדולה מדי (%2 בתים, מורשה %3 בתים).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>שגיאה בעת יצירת קשר עם %1:‏ %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>לא ניתן לפענח את בקשת התשלום!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>תגובה שגויה מהשרת %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>שגיאת בקשת רשת</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>התשלום אושר</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1625,10 +1529,6 @@
<translation>מי&amp;דע</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>חלון ניפוי</translation>
- </message>
- <message>
<source>General</source>
<translation>כללי</translation>
</message>
@@ -2165,10 +2065,6 @@
<translation>אזהרה</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>צמצום הגדרות עמלה</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>
@@ -2214,7 +2110,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>
+ <translation>כאשר יש פחות נפח עסקאות מאשר מקום בבלוק, כורים וכן צמתות מקשרות יכולות להכתיב עמלות מינימום. התשלום של עמלת מינימום הנו תקין, אך יש לקחת בחשבון שהדבר יכול לגרום לעסקה שלא תאושר ברגע שיש יותר ביקוש לעסקאות ביטקוין מאשר הרשת יכולה לעבד.</translation>
</message>
<message>
<source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
@@ -2341,10 +2237,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>יצירת ההעברה נכשלה!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>ההעברה נדחתה מהסיבות הבאות: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>עמלה מעל לסכום של %1 נחשבת לעמלה גבוהה באופן מוגזם.</translation>
</message>
@@ -2396,10 +2288,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>בחירת כתובת שהייתה בשימוש</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>זהו תשלום רגיל.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>כתובת הביטקוין של המוטב</translation>
</message>
@@ -2459,17 +2347,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Memo:</source>
<translation>תזכורת:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>נא להזין תווית לכתובת זו כדי להוסיף אותה לספר הכתובות שלך</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>כן</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -3198,10 +3075,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>גיזום: הסינכרון האחרון של הארנק עובר את היקף הנתונים שנגזמו. יש לבצע חידוש אידקסציה (נא להוריד את כל שרשרת הבלוקים שוב במקרה של צומת מקוצצת)</translation>
</message>
<message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>סריקה מחודשת אינה אפשרית בצומת מקוצצת. יש להשתמש באינדקסציה מחודשת reindex- אשר תוריד את כל שרשרת הבלוקים מחדש.</translation>
- </message>
- <message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>שגיאה: סניה קלמה קריטית פנימית קרטה, פנה ל debug.log לפרטים</translation>
</message>
@@ -3255,7 +3128,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <translation> שידור-חוזר של הבלוקים לא הצליח. תצטרכו לבצע בנייה מחדש של מאגר הנתונים באמצעות הדגל reindex-chainstate-.</translation>
+ <translation>שידור-חוזר של הבלוקים לא הצליח. תצטרכו לבצע בנייה מחדש של מאגר הנתונים באמצעות הדגל reindex-chainstate-.</translation>
</message>
<message>
<source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
@@ -3382,6 +3255,11 @@ 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>
@@ -3495,7 +3373,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Section [%s] is not recognized.</source>
- <translation> הפסקה [%s] אינה מזוהה.</translation>
+ <translation>הפסקה [%s] אינה מזוהה.</translation>
</message>
<message>
<source>Signing transaction failed</source>
@@ -3568,10 +3446,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>זוהי עמלת העסקה שתוכל לשלם כאשר אמדן גובה העמלה אינו זמין.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>מוצר זה כולל תוכנה שפותחה בפרויקט OpenSSL לטובת השימוש ב OpenSSL Toolkit %s ותוכנת קריפטוגרפיה שנכתבה ע"י Eric Young ותוכנת UPnP שנכתבה ע"יי Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation>האורך הכולל של רצף התווים של גירסת הרשת (%i) גדול מהאורך המרבי המותר (%i). יש להקטין את המספר או האורך של uacomments.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_hi.ts b/src/qt/locale/bitcoin_hi.ts
index a71fc999fa..bf67fd01f5 100644
--- a/src/qt/locale/bitcoin_hi.ts
+++ b/src/qt/locale/bitcoin_hi.ts
@@ -19,11 +19,11 @@
</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>
@@ -71,7 +71,7 @@
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>प्रतिलिप करे और चिन्हित करें </translation>
+ <translation>प्रतिलिप करे और चिन्हित करें</translation>
</message>
<message>
<source>&amp;Edit</source>
@@ -102,7 +102,7 @@
</message>
<message>
<source>Address</source>
- <translation>पता </translation>
+ <translation>पता</translation>
</message>
<message>
<source>(no label)</source>
@@ -133,7 +133,7 @@
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>इस संचालान हेतु कृपया अपने वॉलेट के सुरक्षा संवाद को दर्ज करें </translation>
+ <translation>इस संचालान हेतु कृपया अपने वॉलेट के सुरक्षा संवाद को दर्ज करें</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -141,7 +141,7 @@
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>आपके वॉलेट को गोपनीय बनाने हेतु आपके वॉलेट का सुरक्षा संवाद अनिवार्य है </translation>
+ <translation>आपके वॉलेट को गोपनीय बनाने हेतु आपके वॉलेट का सुरक्षा संवाद अनिवार्य है</translation>
</message>
<message>
<source>Decrypt wallet</source>
@@ -156,6 +156,14 @@
<translation>वॉलेट एन्क्रिप्शन की पुष्टि करें</translation>
</message>
<message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>चेतावनी: यदि आपने वॉलेट को एन्क्रिप्ट करने के बाद पदबंध खो दी तो &lt;b&gt;आप सारे बिटकॉइन खो देंगे &lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>क्या आप सुनिश्चित हैं कि आप अपने वॉलेट को एन्क्रिप्ट करना चाहते हैं ?</translation>
+ </message>
+ <message>
<source>Wallet encrypted</source>
<translation>वॉलेट को एन्क्रिप्ट किया गया है</translation>
</message>
@@ -216,7 +224,7 @@
</message>
<message>
<source>Wallet:</source>
- <translation>तिजोरी </translation>
+ <translation>तिजोरी</translation>
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
@@ -439,7 +447,7 @@
</message>
<message>
<source>Address</source>
- <translation>पता </translation>
+ <translation>पता</translation>
</message>
<message>
<source>Amount</source>
@@ -528,9 +536,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -574,7 +579,7 @@
<name>TransactionDescDialog</name>
<message>
<source>This pane shows a detailed description of the transaction</source>
- <translation> ये खिड़की आपको लेन-देन का विस्तृत विवरण देगी !</translation>
+ <translation>ये खिड़की आपको लेन-देन का विस्तृत विवरण देगी !</translation>
</message>
</context>
<context>
@@ -612,7 +617,7 @@
</message>
<message>
<source>Address</source>
- <translation>पता </translation>
+ <translation>पता</translation>
</message>
<message>
<source>Exporting Failed</source>
diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts
index 428af22fd7..0d0a2e6765 100644
--- a/src/qt/locale/bitcoin_hr.ts
+++ b/src/qt/locale/bitcoin_hr.ts
@@ -70,6 +70,10 @@
<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>
@@ -132,6 +136,10 @@
<translation>Ponovite novu lozinku</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Pokažite lozinku</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Šifrirajte novčanik</translation>
</message>
@@ -172,10 +180,30 @@
<translation>Novčanik šifriran</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>Unesite novu lozinku za novčanik. &lt;br/&gt;Molimo vas da koristite zaporku od &lt;b&gt;deset ili više slučajnih znakova&lt;/b&gt;, ili &lt;b&gt;osam ili više riječi.&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Unesite staru i novu lozinku za novčanik.</translation>
+ </message>
+ <message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
<translation>Zapamtite da šifriranje vašeg novčanika ne može u potpunosti zaštititi vaše bitcoinove od zloćudnog softvera kojim se zarazi vaše računalo.</translation>
</message>
<message>
+ <source>Wallet to be encrypted</source>
+ <translation>Novčanik koji treba šifrirati</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Vaš novčanik će biti šifriran.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Vaš novčanik je sad šifriran.</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>VAŽNO: Sve prethodne pričuve vašeg novčanika trebale bi biti zamijenjene novo stvorenom, šifriranom datotekom novčanika. Zbog sigurnosnih razloga, prethodne pričuve nešifriranog novčanika će postati beskorisne čim počnete koristiti novi, šifrirani novčanik.</translation>
</message>
@@ -298,6 +326,14 @@
<translation>Otvorite &amp;URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Stvorite novčanik...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Stvorite novi novčanik</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Novčanik:</translation>
</message>
@@ -338,14 +374,6 @@
<translation>Promijenite lozinku za šifriranje novčanika</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Konzola za dijagnostiku</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Otvorite konzolu za dijagnostiku</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Potvrdite poruku...</translation>
</message>
@@ -406,10 +434,6 @@
<translation>Prikažite popis korištenih adresa i oznaka za primanje novca</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Otvorite bitcoin: URI adresu ili zahtjev za uplatu</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Opcije &amp;naredbene linije</translation>
</message>
@@ -526,6 +550,10 @@
<translation>Greška: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Upozorenje: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Datum: %1
@@ -746,10 +774,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Stvara se novčanik &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Neuspješno stvaranje novčanika</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Upozorenje kod stvaranja novčanika</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Stvorite novčanik</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Ime novčanika</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>Šifrirajte novčanik. Novčanik bit će šifriran lozinkom po vašem izboru.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Šifrirajte novčanik</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>Isključite privatne ključeve za ovaj novčanik. Novčanici gdje su privatni ključevi isključeni neće sadržati privatne ključeve te ne mogu imati HD sjeme ili uvezene privatne ključeve. Ova postavka je idealna za novčanike koje su isključivo za promatranje.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>Isključite privatne ključeve</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>Stvorite prazni novčanik. Prazni novčanici nemaju privatnih ključeva ili skripta. Mogu se naknadno uvesti privatne ključeve i adrese ili postaviti HD sjeme.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Stvorite prazni novčanik</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Stvorite</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -835,10 +911,6 @@
<translation>verzija</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>O programu %1</translation>
</message>
@@ -866,6 +938,10 @@
<translation>Kada kliknete OK, %1 počet će preuzimati i procesirati cijeli lanac blokova (%2GB) počevši s najranijim transakcijama u %3 kad je %4 prvi put pokrenut.</translation>
</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>Vraćanje na ovu postavku zahtijeva ponovno preuzimanje cijelog lanca blokova. Brže je najprije preuzeti cijeli lanac pa ga kasnije obrezati. Isključuje napredne mogućnosti.</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>Početna sinkronizacija je vrlo zahtjevna i može otkriti hardverske probleme kod vašeg računala koji su prije prošli nezamijećeno. Svaki put kad pokrenete %1, nastavit će preuzimati odakle je stao.</translation>
</message>
@@ -886,6 +962,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Odbacite blokove nakon provjere osim one najnovije do %1 GB-a (obrezujte)</translation>
+ </message>
+ <message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation>Bit će spremljeno barem %1 GB podataka u ovoj mapi te će se povećati tijekom vremena.</translation>
</message>
@@ -917,7 +997,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(od potrebnog prostora od %n GB)</numerusform><numerusform>(od potrebnog prostora od %n GB)</numerusform><numerusform>(od potrebnog %n GB)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(potreban je %n GB za cijeli lanac)</numerusform><numerusform>(potrebna su %n GB-a za cijeli lanac)</numerusform><numerusform>(potrebno je %n GB-a za cijeli lanac)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -965,6 +1049,10 @@
<translation>Sakrijte</translation>
</message>
<message>
+ <source>Esc</source>
+ <translation>Esc</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>Nepoznato. Sinkroniziranje zaglavlja (%1, %2%)...</translation>
</message>
@@ -972,28 +1060,20 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Otvori URI adresu</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Otvori zahtjev za plaćanje iz URI adrese ili datoteke</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Izaberi datoteku zahtjeva za plaćanje</translation>
+ <source>Open wallet failed</source>
+ <translation>Neuspješno otvaranje novčanika</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Izaberi datoteku zahtjeva za plaćanje</translation>
+ <source>Open wallet warning</source>
+ <translation>Upozorenje kod otvaranja novčanika</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>uobičajeni novčanik</translation>
@@ -1372,16 +1452,12 @@
<translation>'bitcoin://' nije ispravan URI. Koristite 'bitcoin:' umjesto toga.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Koristite BIP70 URL koji će ubuduće biti nepodržan.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL za dohvatu zahtjeva za plaćanje neispravan: %1</translation>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Zbog rasprostranjenih sigurnosnih mana u BIP70-u, strogo se preporučuje da se ignoriraju bilo kakve naredbe o zamjeni novčanika sa strane trgovca.</translation>
</message>
<message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Ne može se obraditi zahtjev uplate jer podrška za BIP70 nije bila uključena tijekom prevođenja.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Ako dobivate ovu grešku, trebali biste zatražiti od trgovca BIP21 kompatibilan URI.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1395,66 +1471,6 @@
<source>Payment request file handling</source>
<translation>Rukovanje datotekom zahtjeva za plaćanje</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Nije moguće iščitati datoteku zahtjeva za plaćanje! Uzrok tomu može biti nevažeća datoteka zahtjeva za plaćanje.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Zahtjev za plaćanje odbijen</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Mreža zahtjeva za plaćanje ne poklapa se s mrežom klijenta.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Zahtjev za plaćanje istekao.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Zahtjev za plaćanje nije inicijaliziran.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Neprovjereni zahtjevi za plaćanje prilagođenim skriptima za plaćanje su nepodržani.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Nevažeći zahtjev za plaćanje.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Traženi iznos plaćanja %1 je premalen (smatra se "prašinom", sićušnim iznosom).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Povrat iz %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Zahtjev za plaćanje %1 je prevelik (%2 bajt(ov)a, dozvoljeno %3 bajt(ov)a).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Greška kod komuniciranja s %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Zahtjev za plaćanje ne može se parsirati!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Neispravan odgovor sa strane servera %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Greška kod mrežnog zahtjeva</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Plaćanje priznato</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1605,6 +1621,10 @@
<translation>Greška kod kodiranja URI adrese u QR kod.</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>Podrška za QR kodove je nedostupna.</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>Spremi QR kod</translation>
</message>
@@ -1628,10 +1648,6 @@
<translation>&amp;Informacije</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Konzola za dijagnostiku</translation>
- </message>
- <message>
<source>General</source>
<translation>Općenito</translation>
</message>
@@ -1963,6 +1979,10 @@
<translation>Opcionalan iznos koji možete zahtijevati. Ostavite ovo prazno ili unesite nulu ako ne želite zahtijevati specifičan iznos.</translation>
</message>
<message>
+ <source>&amp;Create new receiving address</source>
+ <translation>&amp;Stvorite novu primateljsku adresu</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Obriši sva polja</translation>
</message>
@@ -2168,10 +2188,6 @@
<translation>Upozorenje: Procjena naknada trenutno nije moguća.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>Sažimajte opcije naknade</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>
@@ -2284,6 +2300,14 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>%1 (%2 blokova)</translation>
</message>
<message>
+ <source> from wallet '%1'</source>
+ <translation>iz novčanika '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>od %1 do '%2'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 na %2</translation>
</message>
@@ -2316,10 +2340,18 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Ukupni iznos</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Kliknite "Prikažite detalje..." kako biste pregledali popis primatelja</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Potvrdi slanje novca</translation>
</message>
<message>
+ <source>Send</source>
+ <translation>Pošalji</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Adresa primatelja je nevažeća. Provjerite ponovno, molim vas.</translation>
</message>
@@ -2344,10 +2376,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Neuspješno stvorenje transakcije!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Transakcija je bila odbijena zbog sljedećeg razloga: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Naknada veća od %1 smatra se apsurdno visokim naknadom.</translation>
</message>
@@ -2399,10 +2427,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Odaberite prethodno korištenu adresu</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Ovo je normalna uplata.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Bitcoin adresa na koju ćete poslati uplatu</translation>
</message>
@@ -2462,17 +2486,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<source>Memo:</source>
<translation>Zapis:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Unesite oznaku za ovu adresu kako bi ju dodali u vaš adresar</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Da</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2592,6 +2605,10 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Otključavanje novčanika je otkazano.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Bez greške</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>Privatni ključ za unesenu adresu nije dostupan.</translation>
</message>
@@ -2766,6 +2783,10 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Indeks outputa</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(Certifikat nije bio ovjeren)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Trgovac</translation>
</message>
@@ -3089,6 +3110,10 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Zatvorite novčanik</translation>
</message>
<message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>Jeste li sigurni da želite zatvoriti novčanik &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>Držanje novčanik zatvorenim predugo može rezultirati ponovnom sinkronizacijom cijelog lanca ako je obrezivanje uključeno.</translation>
</message>
@@ -3201,10 +3226,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Ponovno skeniranje nije moguće u obrezanim načinu (pruned mode). Morat ćete koristiti -reindex, što će ponovno preuzeti cijeli lanac blokova.</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>
@@ -3361,6 +3382,10 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Brzinska provjera inicijalizacije neuspješna. %s se zatvara.</translation>
</message>
<message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Nevaljana dozvola za P2P: '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
<translation>Neispravan iznos za -%s=&lt;amount&gt;: '%s'</translation>
</message>
@@ -3377,6 +3402,14 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Zadana mapa blokova "%s" ne postoji.</translation>
</message>
<message>
+ <source>Unknown address type '%s'</source>
+ <translation>Nepoznat tip adrese '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation>Nepoznat tip adrese za vraćanje ostatka '%s'</translation>
+ </message>
+ <message>
<source>Upgrading txindex database</source>
<translation>Ažurira se txindex baza</translation>
</message>
@@ -3385,6 +3418,10 @@ 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>
@@ -3493,6 +3530,10 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Treba zadati port pomoću -whitebind: '%s'</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Obrezan način rada nije u skladu s parametrom -blockfilterindex.</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Smanjuje se -maxconnections sa %d na %d zbog sustavnih ograničenja.</translation>
</message>
@@ -3551,6 +3592,10 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Ne mogu se generirati početni ključevi</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>Nepoznata vrijednost parametra -blockfilterindex %s.</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>Provjerava(ju) se novčanik/(ci)...</translation>
</message>
@@ -3571,10 +3616,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Ovo je transakcijska naknada koju ćete možda platiti kada su nedostupne procjene naknada.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Ovaj proizvod sadrži softver razvijen sa strane OpenSSL Projecta za upotrebu u OpenSSL Toolkitu %s, kriptografski softver koji je napisao Eric Young te UPnP softver koji je napisao Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts
index 3301b39856..34c8b91844 100644
--- a/src/qt/locale/bitcoin_hu.ts
+++ b/src/qt/locale/bitcoin_hu.ts
@@ -70,6 +70,10 @@
<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>
</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>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;Cím másolása</translation>
</message>
@@ -121,7 +125,7 @@
</message>
<message>
<source>Enter passphrase</source>
- <translation>Add meg a jelszót</translation>
+ <translation>Írja be a jelszót</translation>
</message>
<message>
<source>New passphrase</source>
@@ -129,7 +133,11 @@
</message>
<message>
<source>Repeat new passphrase</source>
- <translation>Új jelszó újra</translation>
+ <translation>Ismét az új jelszó</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation>Jelszó mutatása</translation>
</message>
<message>
<source>Encrypt wallet</source>
@@ -137,7 +145,7 @@
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Ehhez a művelethez szükség van a tárcához tartozó kulcsmondathoz, hogy kinyithassa azt.</translation>
+ <translation>Ehhez a művelethez szükség van a tárcanyitó jelszóra.</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -145,15 +153,15 @@
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Ehhez a művelethez szükség van a tárcához tartozó kulcsmondathoz, hogy a titkosítás megszűnjön.</translation>
+ <translation>Ehhez a művelethez szükség van a tárcatitkosítást feloldó jelszóra.</translation>
</message>
<message>
<source>Decrypt wallet</source>
- <translation>Tárca dekódolása</translation>
+ <translation>Tárcatitkosítás feloldása</translation>
</message>
<message>
<source>Change passphrase</source>
- <translation>Kulcsmondat megváltoztatása</translation>
+ <translation>Jelszó megváltoztatása</translation>
</message>
<message>
<source>Confirm wallet encryption</source>
@@ -172,8 +180,28 @@
<translation>Tárca titkosítva</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>Írja be a tárca új jelszavát. &lt;br/&gt;A jelszó összetétele a következő: &lt;b&gt;tíz vagy annál több véletlenszerű karakter&lt;/b&gt;, vagy &lt;b&gt;nyolc vagy annál több szó&lt;/b&gt;. </translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Írja be a tárca régi és új jelszavát.</translation>
+ </message>
+ <message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>Ne feledd, hogy a tárca titkosítása sem nyújt teljes védelmet az adathalász programok fertőzésével szemben.</translation>
+ <translation>Ne feledd, hogy a tárca titkosítása nem nyújt teljes védelmet az adathalász programok fertőzésével szemben.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>A titkositandó tárca</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Tárcatitkosítás megkezdése.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Tárcáját titkosítottuk.</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>
@@ -181,31 +209,31 @@
</message>
<message>
<source>Wallet encryption failed</source>
- <translation>A tárca titkosítása sikertelen.</translation>
+ <translation>Nem sikerült a tárca titkosítása</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Tárca titkosítása belső hiba miatt sikertelen. A tárcád nem lett titkosítva.</translation>
+ <translation>A tárca titkosítása belső hiba miatt nem sikerült. A tárcád nem lett titkosítva.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
- <translation>A megadott jelszavak nem egyeznek.</translation>
+ <translation>A megadott jelszók nem egyeznek.</translation>
</message>
<message>
<source>Wallet unlock failed</source>
- <translation>Tárca megnyitása sikertelen</translation>
+ <translation>A tárca felnyitása nem sikerült</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>A tárca titkosításának feloldásához megadott jelszó helytelen.</translation>
+ <translation>A tárcatitkosítás feloldásához megadott jelszó helytelen.</translation>
</message>
<message>
<source>Wallet decryption failed</source>
- <translation>Tárca titkosításának feloldása sikertelen</translation>
+ <translation>A tárca titkosításának feloldása nem sikerült</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
- <translation>Tárca jelszava sikeresen megváltoztatva.</translation>
+ <translation>A tárca jelszavát sikeresen megváltoztatta.</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
@@ -239,7 +267,7 @@
</message>
<message>
<source>Show general overview of wallet</source>
- <translation>Tárca általános áttekintése</translation>
+ <translation>A tárca általános áttekintése</translation>
</message>
<message>
<source>&amp;Transactions</source>
@@ -287,7 +315,7 @@
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>&amp;Bisztonsági másolat készítése a Tárcáról</translation>
+ <translation>&amp;Biztonsági tárcamásolat készítése...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
@@ -298,6 +326,14 @@
<translation>&amp;URI azonosító megnyitása...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Tárca készítése...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Új tárca készítése</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Tárca:</translation>
</message>
@@ -323,7 +359,7 @@
</message>
<message>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>Proxy &lt;b&gt;aktív&lt;/b&gt;: %1 </translation>
+ <translation>Proxy &lt;b&gt;aktív&lt;/b&gt;: %1</translation>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
@@ -335,15 +371,7 @@
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
- <translation>Tárca-titkosító jelszó megváltoztatása</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Debug ablak</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Hibakereső és diagnosztikai konzol megnyitása</translation>
+ <translation>Tárcatitkosító jelszó megváltoztatása</translation>
</message>
<message>
<source>&amp;Verify message...</source>
@@ -406,10 +434,6 @@
<translation>A használt fogadó címek és címkék megtekintése</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>"bitcoin:" URI azonosító vagy fizetési kérelem megnyitása</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Paran&amp;cssor kapcsolók</translation>
</message>
@@ -439,7 +463,7 @@
</message>
<message>
<source>Transactions after this will not yet be visible.</source>
- <translation>Ez utáni tranzakciók még nem lesznek láthatóak. </translation>
+ <translation>Ez utáni tranzakciók még nem lesznek láthatóak.</translation>
</message>
<message>
<source>Error</source>
@@ -471,7 +495,7 @@
</message>
<message>
<source>Open a wallet</source>
- <translation>Tárca nyitása</translation>
+ <translation>Tárca megnyitása</translation>
</message>
<message>
<source>Close Wallet...</source>
@@ -540,7 +564,7 @@
<message>
<source>Wallet: %1
</source>
- <translation>Tárca: %1 </translation>
+ <translation>Tárca: %1</translation>
</message>
<message>
<source>Type: %1
@@ -582,11 +606,11 @@
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>A tárca &lt;b&gt;titkosítva&lt;/b&gt; és jelenleg &lt;b&gt;nyitva&lt;/b&gt;.</translation>
+ <translation>A tárca &lt;b&gt;titkosítva&lt;/b&gt; és jelenleg &lt;b&gt;megnyitva&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>Tárca &lt;b&gt;kódolva&lt;/b&gt; és jelenleg &lt;b&gt;zárva&lt;/b&gt;.</translation>
+ <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>
@@ -701,7 +725,7 @@
</message>
<message>
<source>Copy bytes</source>
- <translation>Byte-ok másolása </translation>
+ <translation>Byte-ok másolása</translation>
</message>
<message>
<source>Copy dust</source>
@@ -746,9 +770,49 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>&lt;b&gt;%1&lt;/b&gt; tárca készítése folyamatban...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>A tárcakészítés nem sikerült</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Tárcakészítési figyelmeztetés</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Tárca készítése</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Tárca neve</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>A tárca titkosítása. A tárcát egy Ön által megadott jelszó titkosítja.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Tárca titkosítása</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>A tárcához tartozó privát kulcsok letiltása. Azok a tárcák, melyeknél a privát kulcsok le vannak tiltva, nem tartalmaznak privát kulcsokat és nem tartalmazhatnak HD magot vagy importált privát kulcsokat. Ez azoknál a tárcáknál ideális, melyeket csak megfigyelésre használnak.</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>Üres tárca készítése. Az üres tárcák kezdetben nem tartalmaznak privát kulcsokat vagy szkripteket. Később lehetséges a privát kulcsok vagy címek importálása avagy egy HD mag beállítása.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Üres tárca készítése</translation>
+ </message>
</context>
<context>
<name>EditAddressDialog</name>
@@ -762,7 +826,7 @@
</message>
<message>
<source>The label associated with this address list entry</source>
- <translation>Ehhez a listaelemhez rendelt címke </translation>
+ <translation>Ehhez a listaelemhez rendelt címke</translation>
</message>
<message>
<source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
@@ -790,7 +854,7 @@
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation>Tárca feloldása sikertelen</translation>
+ <translation>Nem sikerült a tárca megnyitása</translation>
</message>
<message>
<source>New key generation failed.</source>
@@ -827,10 +891,6 @@
<translation>verzió</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>A %1 -ról</translation>
</message>
@@ -858,6 +918,10 @@
<translation>Ha az OK-ra kattint, %1 megkezdi a teljes %4 blokk lánc letöltését és feldolgozását (%2GB) a legkorábbi tranzakciókkal kezdve %3 -ben, amikor a %4 bevezetésre került.</translation>
</message>
<message>
+ <source>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>A beállítás visszaállításához le kell tölteni a teljes blokkláncot. A teljes lánc letöltése és későbbi nyesése ennél gyorsabb. Bizonyos haladó funkciókat letilt.</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>Az első szinkronizáció nagyon erőforrás-igényes és felszínre hozhat a számítógépében eddig rejtve maradt hardver problémákat. Minden %1 indításnál a program onnan folytatja a letöltést, ahol legutóbb abbahagyta.</translation>
</message>
@@ -878,6 +942,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Blokkok elhgyása ellenőrzés után, kivéve a legújabb %1 GB-ot (nyesés)</translation>
+ </message>
+ <message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation>Legalább %1 GB adatot fogunk ebben a könyvtárban tárolni és idővel ez egyre több lesz.</translation>
</message>
@@ -891,11 +959,11 @@
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
- <translation>Ebben a könyvtárban lesz a pénztárca is.</translation>
+ <translation>A tárcát is ebben a könyvtárban tároljuk.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Hiba: A megadott "%1" adatkönyvtár nem hozható létre. </translation>
+ <translation>Hiba: A megadott "%1" adatkönyvtár nem hozható létre.</translation>
</message>
<message>
<source>Error</source>
@@ -914,7 +982,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>A legutóbbi tranzakciók még lehet, hogy nem látszanak, ezért előfordulhat, hogy a pénztárca egyenlege nem a valós állapotot mutatja. Ha a pénztárca befejezte a szinkronizációt a bitcoin hálózattal, utána már az aktuális egyenleget fogja mutatni, amint alant részletesen látszik.</translation>
+ <translation>A legutóbbi tranzakciók még lehet, hogy nem láthatók, és így előfordulhat, hogy a tárca egyenlege helytelen. A tárca azon nyomban az aktuális egyenleget fogja mutatni, amint befejezte a bitcoin hálózattal történő szinkronizációt, amely alább van részletezve.</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
@@ -956,35 +1024,27 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>URI megnyitása</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Fizetési kérelem megnyitása URI azonosítóból vagy fájlból</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Fizetési kérelmi fájl kiválasztása</translation>
+ <source>Open wallet failed</source>
+ <translation>Nem sikerült a tárca megnyitása</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Válassza ki a megnyitni kívánt fizetési kérelem fájlt</translation>
+ <source>Open wallet warning</source>
+ <translation>Tárca-megnyitási figyelmeztetés</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>Alapértelmezett tárca</translation>
</message>
<message>
<source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
- <translation>Tárca megnyitása &lt;b&gt;%1&lt;/b&gt;... </translation>
+ <translation>&lt;b&gt;%1&lt;/b&gt; tárca megnyitása...</translation>
</message>
</context>
<context>
@@ -1022,6 +1082,10 @@
<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>
@@ -1058,10 +1122,22 @@
<translation>&amp;Hálózat</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>Bizonyos haladó funkciókat letilt, de minden blokkot teljes mértékben érvényesít. A beállítás visszaállításához le kell tölteni a teljes blokkláncot. A tényleges lemezhasználat valamennyire megnövekedhet.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Nyesi a &amp;block tárolását ide:</translation>
+ </message>
+ <message>
<source>GB</source>
<translation>GB</translation>
</message>
<message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>A beállítás visszaállításához le kell tölteni a teljes blokkláncot.</translation>
+ </message>
+ <message>
<source>MiB</source>
<translation>MB</translation>
</message>
@@ -1250,7 +1326,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>A kijelzett információ lehet, hogy elavult. A pénztárcája automatikusan szinkronizálja magát a Bitcoin hálózattal miután a kapcsolat létrejön, de ez e folyamat még nem fejeződött be.</translation>
+ <translation>A kijelzett információ lehet, hogy elavult. A kapcsolat létrehozatalát követően tárcája automatikusan szinkronba kerül a Bitcoin hálózattal, de ez a folyamat még nem fejeződött be.</translation>
</message>
<message>
<source>Watch-only:</source>
@@ -1332,6 +1408,10 @@
<translation>URI kezelés</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>Invalid payment address %1</source>
<translation>Érvénytelen fizetési cím %1</translation>
</message>
@@ -1343,62 +1423,6 @@
<source>Payment request file handling</source>
<translation>Fizetés kérelmi fájl kezelése</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Nem sikerült beolvasni a fizetési kérelmi fájlt! Ezt érvénytelen fizetési kérelmi fájl okozhatja.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>A fizetési kérelem visszautasítva</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>A fizetési kérelmi hálózat nem egyezik a kliens hálózatával.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>A fizetési kérelem lejárt.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>A fizetési kérelem nem inicializálódott</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Érvénytelen fizetési kérelem</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>A %1 fizetésre kért összege túl kevés (porszemnek minősül).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Visszatérítés a %1 -tól</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>A fizetési kérelem %1 túl nagy (%2 byte, csak %3 byte engedélyezett).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Hiba a kommuniáció során %1 -el: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Nem sikerült elemezni a fizetési kérelmet!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Rossz válasz a kiszolgálótól %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Hálózati kérelem hiba</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Fizetés elfogadva</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1511,7 +1535,7 @@
</message>
<message>
<source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Hiba: A megadott "%1" adatkönyvtár nem létezik. </translation>
+ <translation>Hiba: A megadott "%1" adatkönyvtár nem létezik.</translation>
</message>
<message>
<source>Error: Cannot parse configuration file: %1.</source>
@@ -1572,10 +1596,6 @@
<translation>&amp;Információ</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Debug ablak</translation>
- </message>
- <message>
<source>General</source>
<translation>Általános</translation>
</message>
@@ -1624,6 +1644,10 @@
<translation>Memóriahasználat</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Tárca:</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Visszaállítás</translation>
</message>
@@ -1692,6 +1716,10 @@
<translation>Szolgáltatások</translation>
</message>
<message>
+ <source>Ban Score</source>
+ <translation>Kazenske točke</translation>
+ </message>
+ <message>
<source>Connection Time</source>
<translation>Csatlakozás ideje</translation>
</message>
@@ -1812,6 +1840,14 @@
<translation>Hálózati tevékenység letiltva.</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Parancs végrehajtása tárca nélkül</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Parancs végrehajtása a "%1" tárca használatával</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(csomópont azonosító: %1)</translation>
</message>
@@ -1868,13 +1904,17 @@
</message>
<message>
<source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Használja ezt az űrlapot fizetési kérelmekhez. Minden mező &lt;b&gt;opcionális&lt;/b&gt; </translation>
+ <translation>Használja ezt az űrlapot fizetési kérelmekhez. Minden mező &lt;b&gt;opcionális&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>Egy opcionálisan kérhető összeg. Hagyja üresen, vagy írjon be nullát, ha nem kívánja használni.</translation>
</message>
<message>
+ <source>&amp;Create new receiving address</source>
+ <translation>&amp;Új fogadócím létrehozása</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Minden mező törlése</translation>
</message>
@@ -2080,10 +2120,6 @@
<translation>Figyelem: A hozzávetőleges díjszámítás jelenleg nem lehetséges.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>díj beállítások bezárása</translation>
- </message>
- <message>
<source>per kilobyte</source>
<translation>kilobájtonként</translation>
</message>
@@ -2100,6 +2136,10 @@
<translation>Egyéni:</translation>
</message>
<message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(Samodejni obračun provizije še ni pripravljen. Po navadi izračun traja nekaj blokov ...)</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>Küldés több címzettnek egyszerre</translation>
</message>
@@ -2157,7 +2197,7 @@
</message>
<message>
<source>Copy bytes</source>
- <translation>Byte-ok másolása </translation>
+ <translation>Byte-ok másolása</translation>
</message>
<message>
<source>Copy dust</source>
@@ -2168,6 +2208,18 @@
<translation>Visszajáró másolása</translation>
</message>
<message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 blokov)</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 do %2</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<translation>Biztosan el akarja küldeni?</translation>
</message>
@@ -2212,10 +2264,6 @@
<translation>Tranzakció létrehozása sikertelen!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Tranzakció visszautasítva a következő indokkal: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Magasabb díj mint %1 abszurd magas díjnak számít.</translation>
</message>
@@ -2237,7 +2285,7 @@
</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>A cím, amelyet a visszajárónak megadott, nincs ebben a tárcában. Bármennyi vagy minden összeg elküldhető a tárcájából erre a címre. Biztos benne?</translation>
+ <translation>A visszajárónak megadott cím nem szerepel ebben a tárcában. Bármilyen - vagy az egész - összeg elküldhető a tárcájából erre a címre. Biztos benne?</translation>
</message>
<message>
<source>(no label)</source>
@@ -2263,10 +2311,6 @@
<translation>Válassz egy korábban már használt címet</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Ez normál fizetés.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Erre a Bitcoin címre küldje az összeget</translation>
</message>
@@ -2287,6 +2331,10 @@
<translation>Ez a bejegyzés eltávolítása</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>
+ <message>
<source>S&amp;ubtract fee from amount</source>
<translation>&amp;Vonja le a díjat az összegből</translation>
</message>
@@ -2311,6 +2359,10 @@
<translation>Adjon egy címkét ehhez a címhez, hogy bekerüljön a használt címek közé</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>Sporočilo, ki ste ga pripeli na URI tipa bitcoin:. Shranjeno bo skupaj s podatki o transakciji. Opomba: Sporočilo ne bo poslano preko omrežja Bitcoin.</translation>
+ </message>
+ <message>
<source>Pay To:</source>
<translation>Címzett:</translation>
</message>
@@ -2318,17 +2370,6 @@
<source>Memo:</source>
<translation>Jegyzet:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Adjon egy címkét ehhez a címhez, hogy bekerüljön a címtárába</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Igen</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2352,6 +2393,10 @@
<translation>Üzenet aláírása...</translation>
</message>
<message>
+ <source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
+ <translation>S svojimi naslovi lahko podpisujete sporočila ali pogodbe in s tem dokazujete, da na teh naslovih lahko prejemate kovance. Bodite previdni in ne podpisujte ničesar nejasnega ali naključnega, ker vas zlikovci preko ribarjenja (phishing) lahko prelisičijo, da na njih prepišete svojo identiteto. Podpisujte samo podrobno opisane izjave, s katerimi se strinjate.</translation>
+ </message>
+ <message>
<source>The Bitcoin address to sign the message with</source>
<translation>Bitcoin cím, amivel alá kívánja írni az üzenetet</translation>
</message>
@@ -2385,13 +2430,17 @@
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Üzenet </translation>
+ <translation>Üzenet</translation>
</message>
<message>
<source>Sign &amp;Message</source>
<translation>Üzenet &amp;aláírása</translation>
</message>
<message>
+ <source>Reset all sign message fields</source>
+ <translation>Počisti vsa polja za vnos v oknu za podpisovanje</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Mindent &amp;töröl</translation>
</message>
@@ -2400,6 +2449,10 @@
<translation>Üzenet ellenőrzése</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>Da preverite verodostojnost sporočila, spodaj vnesite: prejemnikov naslov, prejeto sporočilo (pazljivo skopirajte vse prelome vrstic, presledke, tabulatorje ipd.,) in prejeti podpis. Da se izognete napadom tipa man-in-the-middle, vedite, da iz veljavnega podpisa ne sledi nič drugega, kot tisto, kar je navedeno v sporočilu. Podpis samo potrjuje dejstvo, da ima podpisnik v lasti prejemni naslov, ne more pa dokazati vira nobene transakcije!</translation>
+ </message>
+ <message>
<source>The Bitcoin address the message was signed with</source>
<translation>Bitcoin cím, amivel aláírta az üzenetet</translation>
</message>
@@ -2412,6 +2465,10 @@
<translation>Üzenet ellenőrzése</translation>
</message>
<message>
+ <source>Reset all verify message fields</source>
+ <translation>Počisti vsa polja za vnos v oknu za preverjanje</translation>
+ </message>
+ <message>
<source>Click "Sign Message" to generate signature</source>
<translation>Klikkeljen az "Üzenet Aláírása" -ra, hogy aláírást generáljon</translation>
</message>
@@ -2424,6 +2481,10 @@
<translation>Kérem ellenőrizze a címet és próbálja meg újra.</translation>
</message>
<message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>Vnešeni naslov se ne nanaša na ključ.</translation>
+ </message>
+ <message>
<source>Wallet unlock was cancelled.</source>
<translation>Tárca megnyitása megszakítva</translation>
</message>
@@ -2448,6 +2509,10 @@
<translation>Kérem ellenőrizze az aláírást és próbálja újra.</translation>
</message>
<message>
+ <source>The signature did not match the message digest.</source>
+ <translation>Podpis ne ustreza rezultatu (digest) preverjanja.</translation>
+ </message>
+ <message>
<source>Message verification failed.</source>
<translation>Az üzenet ellenőrzése sikertelen.</translation>
</message>
@@ -2470,6 +2535,10 @@
<translation>%1 -ig megnyitva</translation>
</message>
<message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>v sporu s transakcijo z %1 potrditvami</translation>
+ </message>
+ <message>
<source>0/unconfirmed, %1</source>
<translation>0/megerősítetlen, %1</translation>
</message>
@@ -2511,7 +2580,7 @@
</message>
<message>
<source>From</source>
- <translation>Küldő: </translation>
+ <translation>Küldő:</translation>
</message>
<message>
<source>unknown</source>
@@ -2550,6 +2619,10 @@
<translation>Teljes terhelés</translation>
</message>
<message>
+ <source>Total credit</source>
+ <translation>Skupni kredit</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Tranzakciós díj</translation>
</message>
@@ -2574,10 +2647,18 @@
<translation>Tranzakció teljes mérete</translation>
</message>
<message>
+ <source>Output index</source>
+ <translation>Indeks izhoda</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Kereskedő</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>Ustvarjeni kovanci morajo zoreti %1 blokov, preden jih lahko porabite. Ko ste ta blok ustvarili, je bil posredovan v omrežje, da bo dodan v verigo blokov. Če se bloku ni uspelo uvrstiti v verigo, se bo njegovo stanje spremenilo v "ni bilo sprejeto" in kovancev ne bo mogoče porabiti. To se včasih zgodi, če kak drug rudar v roku nekaj sekund hkrati z vami odkrije drug blok.</translation>
+ </message>
+ <message>
<source>Debug information</source>
<translation>Debug információ</translation>
</message>
@@ -2707,7 +2788,15 @@
<source>Whether or not a watch-only address is involved in this transaction.</source>
<translation>Egy csak megfigyelt cím érintett vagy nem ebben a tranzakcióban.</translation>
</message>
- </context>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>Uporabniško določen namen transakcije.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Znesek spremembe stanja sredstev.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
@@ -2759,6 +2848,10 @@
<translation>Más</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Vnesi naslov, ID transakcije, ali oznako za iskanje</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Minimális összeg</translation>
</message>
@@ -2844,27 +2937,47 @@
</message>
<message>
<source>There was an error trying to save the transaction history to %1.</source>
- <translation>Hiba történt a tranzakciós előzmények %1 helyre való mentésekor. </translation>
+ <translation>Hiba történt a tranzakciós előzmények %1 helyre való mentésekor.</translation>
</message>
<message>
<source>Exporting Successful</source>
<translation>Sikeres Exportálás</translation>
</message>
<message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>Zgodovina poteklih transakcij je bila uspešno shranjena v datoteko %1.</translation>
+ </message>
+ <message>
<source>Range:</source>
<translation>Tartomány:</translation>
</message>
- </context>
+ <message>
+ <source>to</source>
+ <translation>za</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
- </context>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation>Merska enota za prikaz zneskov. Kliknite za izbiro druge enote.</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
<translation>Tárca bezárása</translation>
</message>
- </context>
+ <message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>Biztos, hogy bezárja a "%1" tárcát?</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>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>
+</context>
<context>
<name>WalletFrame</name>
<message>
@@ -2953,10 +3066,22 @@
<translation>MIT szoftver licenc alapján terjesztve, tekintse meg a hozzátartozó fájlt %s or %s</translation>
</message>
<message>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation>Nyesés megkísérlése a minimális %d MiB alatt. Kérjük, használjon egy magasabb értéket.</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>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>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>HTTP szerver indítása sikertelen. A részleteket lásd: debug log.</translation>
</message>
@@ -2969,18 +3094,50 @@
<translation>Az %s adatkönyvtár nem zárható. A %s valószínűleg fut már.</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>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>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>
+ <message>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Az adatbázis visszatekerése az elágazás előtti állapotba nem sikerült. Ismételten le kell töltenie a blokkláncot.</translation>
+ </message>
+ <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Figyelem: A hálózat úgy tűnik nem teljesen egyezik! Néhány bányász problémákat tapasztalhat.</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>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>
<message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>Naslova -%s ni mogoče razrešiti: '%s'</translation>
+ </message>
+ <message>
+ <source>Change index out of range</source>
+ <translation>Indeks drobiža izven dovoljenega območja</translation>
+ </message>
+ <message>
<source>Copyright (C) %i-%i</source>
<translation>Szerzői jog (C) fenntartva %i-%i</translation>
</message>
@@ -3026,7 +3183,7 @@
</message>
<message>
<source>Failed to rescan the wallet during initialization</source>
- <translation>A tárca átvizsgálása közben hiba történt.</translation>
+ <translation>Inicializálás közben nem sikerült feltérképezni a tárcát</translation>
</message>
<message>
<source>Importing...</source>
@@ -3037,6 +3194,18 @@
<translation>Helytelen vagy nemlétező genézis blokk. Helytelen hálózati adatkönyvtár?</translation>
</message>
<message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>Neveljavna količina za -%s=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation>Neveljavna količina za -discardfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation>Neveljavna količina za -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
<source>Loading P2P addresses...</source>
<translation>P2P címek betöltése...</translation>
</message>
@@ -3046,7 +3215,15 @@
</message>
<message>
<source>Not enough file descriptors available.</source>
- <translation>Nincs elég fájlleíró. </translation>
+ <translation>Nincs elég fájlleíró.</translation>
+ </message>
+ <message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation>Nyesett üzemmódot nem lehet negatív értékkel kialakítani.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation>A -txindex nem használható nyesett üzemmódban.</translation>
</message>
<message>
<source>Replaying blocks...</source>
@@ -3065,6 +3242,10 @@
<translation>A tranzakciós díj és a visszajáró kiszámítása nem sikerült</translation>
</message>
<message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation>Na tem računalniku ni bilo mogoče vezati naslova %s. %s je verjetno že zagnan.</translation>
+ </message>
+ <message>
<source>Upgrading UTXO database</source>
<translation>Blokk adatbázis frissítése</translation>
</message>
@@ -3077,6 +3258,14 @@
<translation>A Tárca újraírása szükséges: Indítsa újra a %s-t.</translation>
</message>
<message>
+ <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
+ <translation>Napaka: Ni mogoče sprejemati dohodnih povezav (vrnjena napaka: %s)</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>Error reading from database, shutting down.</source>
<translation>Hiba az adatbázis olvasásakor, leállítás</translation>
</message>
@@ -3085,10 +3274,34 @@
<translation>Hiba a blokk adatbázis betöltése közben</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>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>A -blockfilterindex nem használható nyesés üzemmódban.</translation>
+ </message>
+ <message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation>Zmanjšujem maksimalno število povezav (-maxconnections) iz %d na %d, zaradi sistemskih omejitev.</translation>
+ </message>
+ <message>
<source>Signing transaction failed</source>
<translation>Tranzakció aláírása sikertelen</translation>
</message>
<message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>A megadott "%s" -walletdir nem létezik</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>A megadott "%s" -walletdir relatív elérési út</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>A megadott "%s" -walletdir nem könyvtár</translation>
+ </message>
+ <message>
<source>This is experimental software.</source>
<translation>Ez egy kísérleti szoftver.</translation>
</message>
@@ -3101,18 +3314,46 @@
<translation>Túl nagy tranzakció</translation>
</message>
<message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation>Na tem računalniku ni bilo mogoče vezati naslova %s (vrnjena napaka: %s)</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation>Ne zmorem ustvariti začetnih ključev</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>Tárcák ellenőrzése...</translation>
</message>
<message>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <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>
+ </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>
+ </message>
+ <message>
<source>%s is set very high!</source>
<translation>%s étéke nagyon magas!</translation>
</message>
<message>
+ <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
+ <translation>Hiba történt a %s tárca betöltésekor, mert duplikált tárca-fájlnevet adott meg.</translation>
+ </message>
+ <message>
<source>Starting network threads...</source>
<translation>Hálózati szálak indítása...</translation>
</message>
<message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>A tárca nem fog a minimális továbbítási díjnál kevesebbet fizetni. </translation>
+ </message>
+ <message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
<translation>Ez a minimum tranzakciós díj, amelyet tranzakciónként kifizet.</translation>
</message>
@@ -3134,7 +3375,15 @@
</message>
<message>
<source>Insufficient funds</source>
- <translation>Nincs elég bitcoinod.</translation>
+ <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>
+ </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>Loading block index...</source>
@@ -3150,7 +3399,7 @@
</message>
<message>
<source>Rescanning...</source>
- <translation>Újraszkennelés...</translation>
+ <translation>Feltérképezés megismétlése...</translation>
</message>
<message>
<source>Done loading</source>
diff --git a/src/qt/locale/bitcoin_hu_HU.ts b/src/qt/locale/bitcoin_hu_HU.ts
deleted file mode 100644
index a0bd9aa43b..0000000000
--- a/src/qt/locale/bitcoin_hu_HU.ts
+++ /dev/null
@@ -1,2685 +0,0 @@
-<TS language="hu_HU" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>A cím vagy a címke jobb gombbal szerkeszthető</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Új cím létrehozása</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Új</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>A jelenleg kiválasztott cím másolása a rendszer vágólapjára</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Másolás</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>&amp;Bezárás</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>A jelenleg kiválasztott cím eltávolítása a listából</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>A jelenlegi fülön található adat exportálása fájlba</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Export</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Törlés</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Válasszon címet a küldéshez</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Válasszon címet a fogadáshoz</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>&amp;Kiválasztás</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Küldő címek</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Fogadó 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 az Ön kifizetéseinek küldésekor használandó Bitcoin-címek. Fizetés indítása előtt mindig ellenőrizze az összeget és a fogadó címet!</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Ezek az Ön fizetéseinek fogadásakor használandó Bitcoin-címek. Célszerű minden tranzakcióhoz új fogadó címet használni.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Cím másolása</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Címke &amp;másolása</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Szerkesztés</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Címlista exportálása</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Vesszővel elválasztott adatok (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Sikertelen export</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Hiba történt a címlista %1-re történő mentése során. Kérjük, próbálja újra!</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Címke</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Cím</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nincs címke)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Jelszóhalmaz Párbeszédablak</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Adja meg jelmondatát</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Új jelmondat</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Ismételje meg jelmondatát</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Jelszó megjelenítése</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Adja meg az új jelszóhalmazt a pénztárcájához. &lt;br/&gt;Kérem a jelszóhalmaz álljon&lt;b&gt;tíz vagy több véletlenszerű karakterből&lt;/b&gt;, vagy &lt;b&gt;nyolc vagy több szóból&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Tárca kódolása</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Ehhez a művelethez szükség lesz a pénztárcájához tartozó jelszóhalmazra, hogy hozzáférjen a pénztárcához.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Tárca feloldása</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Ehhez a művelethez szükség lesz a pénztárcájához tartozó jelszóhalmazra, hogy feloldja a pénztárca titkosítását.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Tárca dekódolása</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Jelmondat megváltoztatása</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Adja meg a régi jelszóhalmazt és az új jelszóhalmazt a pénztárcájához.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Tárca titkosításának jóváhagyása</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Figyelem: Ha titkosítja a pénztárcáját, és elveszíti a jelszóhalmazt, akkor &lt;b&gt;NEM TUD TÖBBET HOZZÁFÉRNI A BITCOINJAIHOZ&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Biztosan titkosítani kívánja a tárcáját?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Tárca titkosítva</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 Most az ablak bezáródik, amíg befejeződik a titkosítási folyamat. Kérem vegye figyelembe, hogy a pénztárca titkosítása nem jelenti a bitcoinjai teljes körű védelmét, a számítógépét esetlegesen megfertőző kártékony programoktól.</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>FONTOS: A régebbi biztonsági mentéseket frissítse az új, titkosított pénztárca fájllal. Biztonsági okokból, a korábbi titkosítatlan pénztárca fájlok nem használhatóak az új titkosított pénztárcával.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Tárca titkosítása sikertelen</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>A pénztárca titkosítása programhiba miatt meghiúsult . A pénztárca nem titkosított.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>A megadott jelszóhalmazok nem egyeznek.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Tárca feloldása sikertelen</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>A jelszóhalmaz, amelyet megadott a pénztárca titkosításának a feloldásához, helytelen.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Tárca dekódolása sikertelen</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>A tárca jelmondata sikeresen megváltozott.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Figyelmeztetés: A Caps Lock billentyű benyomva!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmask</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Kitiltva a megadott időpontig</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Üzenet &amp;aláírása</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Szinkronizálás a hálózattal...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>Á&amp;ttekintés</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Csomópont</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>A pénztárca általános áttekintése</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Tranzakciók</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Tranzakció-történet böngészése</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>Ki&amp;lépés</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Alkalmazás bezárása</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Kapcsolat %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>További információ %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Kapcsolat &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>További információ Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Beállítások...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>A %1 konfigurációs beállításainak módosítása</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Tárca titkosítása</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>Tárca &amp;biztonsági másolása</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Jelszóhalmaz megváltoztatása</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Címek küldése</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Címek &amp;fogadása</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>&amp;URI... Megnyitása</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Kattintson a hálózati tevékenység felfüggesztéséhez.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Hálózati tevékenység letiltva.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Kattintson a hálózati tevékenység ismételt engedélyezéséhez.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Fejlécek szinkronizálása (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>A blokkok újraindexelése folyik a merevlemezen...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Érmék küldése egy Bitcoin címre</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Tárca biztonsági mentése más helyre</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>A tárca titkosításához használt jelszóhalmaz megváltoztatása</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Hibakereső ablak</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Hibakereső és diagnosztikai konzol megnyitása</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>Üzenet &amp;ellenőrzése</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Tárca</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>Küldé&amp;s</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Fogadás</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Mutat/Elrejt</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Fő ablak megjelenítése vagy elrejtése</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Tárcájához tartozó privát kulcsok titkosítása</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Írja alá az üzeneteit a Bitcoin címével, hogy bizonyítsa Öntől származnak</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Ellenőrizze az üzeneteket, hogy a megadott Bitcoin címekkel lettek-e aláírva</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Fájl</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Beállítások</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>Sú&amp;gó</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Ablak fülek eszköztára</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Kérjen fizetéseket (QR kódokat generál és bitcoin: URLeket)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Mutassa a használt küldő címek és cimkék listáját</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Mutassa a használt fogadó címek és cimkék listáját</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Nyisson meg egy bitcoin: URI-t vagy fizetési kérelmet</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Parancssor beállításai</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n aktív kapcsolat a Bitcoin-hálózaton</numerusform><numerusform>%n aktív kapcsolat a Bitcoin-hálózaton</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>A blokkok indexelése folyik a merevlemezen...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>A blokkok feldolgozása a merevlemezen...</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>A tranzakció-történetből %n blokk feldolgozva.</numerusform><numerusform>A tranzakció-történetből %n blokk feldolgozva.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 mögött</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Az utolsó kapott blokk %1 ideje keletkezett.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Az ez utáni tranzakciók még nem fognak látszani.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Hiba</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Figyelmeztetés</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Információ</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Naprakész</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Mutassa a %1 súgó üzenetet a lehetséges Bitcoin parancssori beállítások listájáért</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>%1 kliens</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Kapcsolatok kialakítása...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Felzárkózás...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Dátum: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Összeg: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Típus: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Címke: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Cím: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Elküldött tranzakció</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Bejövő tranzakció</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>HD kulcs generálás &lt;b&gt;engedélyezve&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>HD kulcs generálás &lt;b&gt;tiltva&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>Tárca &lt;b&gt;titkosítva&lt;/b&gt; és jelenleg &lt;b&gt;nyitva&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>Tárca &lt;b&gt;titkosítva&lt;/b&gt; és jelenleg &lt;b&gt;zárolva&lt;/b&gt;</translation>
- </message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Fatális hiba történt. A Bitcoin program nem tud tovább biztonságosan működni és be fog záródni.</translation>
- </message>
-</context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Érme választó</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Mennyiség:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bájtok:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Öszeg:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Díj:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Porszem:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Eljárási díj után:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Változás:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>minden kiválasztása(kiválasztás megszüntetése)</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Fa mód</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Lista mód</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Összeg</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Címkével fogadott</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Címmel fogadott</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Jóváhagyások</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Jóváhagyva</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Cím másolása</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Címke másolása</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Összeg másolása</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Tranzakció ID másolása</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>El nem költött zárolása</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>El nem költött nyitása</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Mennyiség másolása</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Díj másolása</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Eljárási díj utáni másolás</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Bájtok másolása</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Por másolása</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Változás másolása</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 zárolva)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>igen</translation>
- </message>
- <message>
- <source>no</source>
- <translation>nem</translation>
- </message>
- <message>
- <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Ez a címke pirosra változik, ha valamelyik fogadó fél kisebb összeget kap, mint a jelenlegi porszem határérték.</translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Változó +/- %1 satoshi(k) megadott értékenként.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nincs címke)</translation>
- </message>
- <message>
- <source>change from %1 (%2)</source>
- <translation>változtatás %1 -ről (%2)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation>(módosítás)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Cím szerkesztése</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Címke</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>Ezzel a cím bejegyzéssel társított címke</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>Ezzel a cím bejegyzéssel társított cím. Ezt csak a küldő címek esetén lehet megváltoztatni.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Cím</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Új küldési cím</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Fogadási cím szerkesztése</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Küldési cím szerkesztése</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>A megadott cím"%1" nem egy érvényes Bitcoin cím.</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>A tárca feloldása nem lehetséges</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Új kulcs létrehozása sikertelen</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Új mappa lesz létrehozva.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>név</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>A könyvtár már létezik. %1 hozzáadása, ha új könyvtárat kíván létrehozni.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Az elérési út létezik, de nem egy mappa.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Itt nem hozható létre mappa.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>verzió</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>Kapcsolat %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Parancssor beállításai</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Üdvözöljük</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Üdvözöljük itt: %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>Mivel ez a program első indulása, megváltoztathatja %1 hova mentse az adatokat.</translation>
- </message>
- <message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation>Ha az OK-ra kattint, %1 megkezdi a teljes %4 blokk lánc letöltését és feldolgozását (%2GB) a legkorábbi tranzakciókkal kezdve %3 -ben, amikor a %4 bevezetésre került.</translation>
- </message>
- <message>
- <source>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>Az első szinkronizáció nagyon erőforrás-igényes és felszínre hozhat a számítógépében eddig rejtve maradt hardver problémákat. Minden %1 indításnál a program onnan folytatja a letöltést, ahol legutóbb abbahagyta.</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>Ha a tárolt blokk lánc méretének korlátozását (megnyesését) választotta, akkor is le kell tölteni és feldolgozni az eddig keletkezett összes adatot, de utána ezek törlésre kerülnek, hogy ne foglaljunk sok helyet a merevlemezen.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Alapértelmezett adatmappa használata</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Egyéni adatmappa használata:</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation>Legalább %1 GB adatot fogunk ebben a könyvtárban tárolni és idővel ez egyre több lesz.</translation>
- </message>
- <message>
- <source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>Hozzávetőlegesen %1 GB adatot fogunk ebben a könyvtárban tárolni.</translation>
- </message>
- <message>
- <source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 le fog töltődni és a Bitcoin blokk lánc egy másolatát fogja tárolni.</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation>Ebben a könyvtárban lesz a pénztárca is.</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Hiba: A megadott könyvtárat "%1" nem sikerült létrehozni.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Hiba</translation>
- </message>
- <message numerus="yes">
- <source>%n GB of free space available</source>
- <translation><numerusform>%n GB szabad hely áll rendelkezésre</numerusform><numerusform>%n GB szabad hely áll rendelkezésre</numerusform></translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Űrlap</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>A legutóbbi tranzakciók még lehet, hogy nem látszanak, ezért előfordulhat, hogy a pénztárca egyenlege nem a valós állapotot mutatja. Ha a pénztárca befejezte a szinkronizációt a bitcoin hálózattal, utána már az aktuális egyenleget fogja mutatni, amint alant részletesen látszik.</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>A hálózat nem fogadja el azoknak a bitcoinoknak az elköltését, amelyek érintettek a még nem látszódó tranzakciókban.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Hátralévő blokkok száma</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Ismeretlen...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Utolsó blokk ideje</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation>Folyamat</translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation>A folyamat előrehaladása óránként</translation>
- </message>
- <message>
- <source>calculating...</source>
- <translation>számolás...</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation>Hozzávetőlegesen a hátralévő idő a szinkronizáció befejezéséig</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Elrejtés</translation>
- </message>
- <message>
- <source>Unknown. Syncing Headers (%1)...</source>
- <translation>Ismeretlen. Fejlécek szinkronizálása (%1)...</translation>
- </message>
-</context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>URI megnyitása</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Fizetési kérelem megnyitása URI-ból vagy fájlból</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>A fizetési kérelem fájl kiválasztása</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Válassza ki a megnyitni kívánt fizetési kérelem fájlt</translation>
- </message>
-</context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Opciók</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Fő</translation>
- </message>
- <message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation>%1 automatikus indítása a rendszerbe való belépés után.</translation>
- </message>
- <message>
- <source>&amp;Start %1 on system login</source>
- <translation>&amp;Induljon el a %1 a rendszerbe való belépéskor</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Az &amp;adatbázis cache mérete</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>A szkript &amp;igazolási szálak száma</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Proxy IP címe (pl.: 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>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>Hide the icon from the system tray.</source>
- <translation>Rejtse el az ikont a rendszer tálcáról.</translation>
- </message>
- <message>
- <source>&amp;Hide tray icon</source>
- <translation>&amp;Tálcaikon elrejtése</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>Kilépés helyett a program elrejtése az ablak bezárása után. Ha engedélyezte ezt a beállítást, akkor csak úgy tud kilépni a programból, ha a menüből a Kilépés opciót választja.</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>Harmadik féltől származó URL-ek (pl. egy blokk felfedező) amelyek a tranzakciós fülön jelennek meg mint a környezetérzékeny menü tételei. %s az URL-ben helyettesítve a tranzakciós hash-el. Több URL esetén, függőleges vonal választja el őket.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Aktív parancssori beállítások, melyek felülírják a fenti beállításokat:</translation>
- </message>
- <message>
- <source>Open the %1 configuration file from the working directory.</source>
- <translation>A %1 konfigurációs fájl megnyitása a munkakönyvtárból.</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Konfigurációs Fájl Megnyitása</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Minden kliens beállítás visszaállítása alaphelyzetbe.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Visszaállítja a Beállításokat</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Hálózat</translation>
- </message>
- <message>
- <source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = automatikus, &lt;0 = ennyi processzormagot hagyjon szabadon)</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>T&amp;árca</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Haladó</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Pénzküldés beállításainak engedélyezése</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>Ha letiltja a jóváhagyatlan visszajáró elköltését, akkor egy tranzakcióból származó visszajárót nem lehet felhasználni, amíg legalább egy jóváhagyás nem történik. Ez befolyásolja az egyenlegének a kiszámítását is.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>&amp;Költése a a jóváhagyatlan visszajárónak</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>Automatikusan nyissa meg a Bitcoin kliens által használt portot a routeren. Ez csak akkor működik, ha a router támogatja a UPnP-t, és engedélyezett ez a beállítás.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Port feltérképezése &amp;UPnP használatával</translation>
- </message>
- <message>
- <source>Accept connections from outside.</source>
- <translation>Kívülről érkező kapcsolatok fogadása.</translation>
- </message>
- <message>
- <source>Allow incomin&amp;g connections</source>
- <translation>&amp;Bejövő kapcsolatok engedélyezése</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Csatlakozás a Bitcoin hálózathoz SOCKS5 proxy használatával.</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Kapcsolódás SOCKS5 proxyn keresztül (alapértelmezett 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>Proxy portja (pl.: 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation>Párok elérésére használjuk ezen keresztül:</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>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>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Csak az ablak elrejtése után mutassa a tálca ikont.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Elrejtés a tálcára ikon formában, a tálcán látható futó program helyett</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>&amp;Elrejtés bezáráskor</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Mutatás</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>Felhasználói felület &amp;nyelve:</translation>
- </message>
- <message>
- <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation>A felhasználói felület nyelvét tudja itt beállítani. Ez a beállítás csak a %1 újraindítása után lép életbe.</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Mértékegység amelyben mutassa az összegeket:</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Válassza ki az alapértelmezett részmértékegységet, amely megjelenik a felhasználói felületen és pénzküldéskor.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Mutassa a pénzküldés beállításait vagy ne.</translation>
- </message>
- <message>
- <source>&amp;Third party transaction URLs</source>
- <translation>&amp;Harmadik féltől származó tranzakciós URL-ek</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;OK</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Mégse</translation>
- </message>
- <message>
- <source>default</source>
- <translation>alapméretezett</translation>
- </message>
- <message>
- <source>none</source>
- <translation>semmi</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Opciók visszaállításának megerősítése</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Újra kell indítani a programot a beállítások alkalmazásához.</translation>
- </message>
- <message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation>A kliens le fog állni. Szeretné folytatni?</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Beállítási lehetőségek</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>A konfigurációs fájlt a haladó felhasználók olyan beállításokra használhatják, amelyek felülírják a grafikus felület beállításait. Azonban bármely parancssori beállítás felülírja a konfigurációs fájl beállításait.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Hiba</translation>
- </message>
- <message>
- <source>The configuration file could not be opened.</source>
- <translation>Nem sikerült megnyitni a konfigurációs fájlt.</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Ehhez a változtatáshoz újra kellene indítani a klienst.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>A megadott proxy cím érvénytelen.</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Űrlap</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>Lehet, hogy a megjelenített információ elavult. A tárcája automatikusan szinkronizál a hálózattal kapcsolódás után, de a folyamat még nem ért véget.</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Megfigyelés:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Elérhető:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Felhasználható egyenlege</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Függőben:</translation>
- </message>
- <message>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>A tranzakciók száma, amelyeket még hitelesíteni kell, és amelyek még nem tartoznak az elkölthető egyenlegbe.</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Éretlen:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>Bányászott egyenleg, mely jelenleg még éretlen</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Egyenlegek</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Összesen:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Jelenlegi teljes egyenlege</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>A csak megfigyelt címeinek az egyenlege</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Elkölthető:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Legutóbbi tranzakciók</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>A csak megfigyelt címek hitelesítetlen tranzakciói</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>A csak megfigyelt címek bányászott, még éretlen egyenlege</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>A csak megfigyelt címek jelenlegi teljes egyenlege</translation>
- </message>
-</context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Hiba történt a fizetési kérelem során</translation>
- </message>
- <message>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>A bitcoin nem tud elindulni: click-to-pay kezelő</translation>
- </message>
- <message>
- <source>URI handling</source>
- <translation>URI kezelése</translation>
- </message>
- <message>
- <source>Invalid payment address %1</source>
- <translation>Érvénytelen fizetési cím %1</translation>
- </message>
- <message>
- <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>Az URI nem dolgozható fel! Ennek oka lehet egy érvénytelen Bitcoin-cím, vagy hibás URI-paraméterek.</translation>
- </message>
- <message>
- <source>Payment request file handling</source>
- <translation>Fizetésikérelem-fájl kezelése</translation>
- </message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>A fizetésikérelem-fájl nem olvasható! Lehet, hogy hibás a fájl.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Fizetési kérelem elutasítva</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>A fizetési kérelem hálózat nem egyezik a kliens hálózatával.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Fizetési kérelem lejárt</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Fizetési kérelem nincs inicializálva.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Érvénytelen fizetési kérelem</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>A %1 fizetésre kért összege túl kevés (porszemnek minősül).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Visszatérítés innen: %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>A %1 fizetési kérelem túl nagy (%2 bájt, megengedett: %3 bájt).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Hiba a kommunikáció során %1 -el: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>A fizetési kérelem nem dolgozható fel!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Rossz válasz a szervertől %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Hálózati hiba történt</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Fizetés nyugtázva</translation>
- </message>
-</context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>User Agent</translation>
- </message>
- <message>
- <source>Node/Service</source>
- <translation>Csomópont/Szolgáltatás</translation>
- </message>
- <message>
- <source>NodeId</source>
- <translation>Csomópont azonosító</translation>
- </message>
- <message>
- <source>Ping</source>
- <translation>Ping</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Elküldve</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Fogadva</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Összeg</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Adjon meg egy Bitcoin-címet (pl. %1)</translation>
- </message>
- <message>
- <source>%1 d</source>
- <translation>%1 n</translation>
- </message>
- <message>
- <source>%1 h</source>
- <translation>%1 ó</translation>
- </message>
- <message>
- <source>%1 m</source>
- <translation>%1 p</translation>
- </message>
- <message>
- <source>%1 s</source>
- <translation>%1 mp</translation>
- </message>
- <message>
- <source>None</source>
- <translation>Nincs</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 másodperc</numerusform><numerusform>%n másodperc</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n minute(s)</source>
- <translation><numerusform>%n perc</numerusform><numerusform>%n perc</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n hour(s)</source>
- <translation><numerusform>%n óra</numerusform><numerusform>%n óra</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n day(s)</source>
- <translation><numerusform>%n nap</numerusform><numerusform>%n nap</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n week(s)</source>
- <translation><numerusform>%n hét</numerusform><numerusform>%n hét</numerusform></translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 és %2</translation>
- </message>
- <message numerus="yes">
- <source>%n year(s)</source>
- <translation><numerusform>%n év</numerusform><numerusform>%n év</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>%1 didn't yet exit safely...</source>
- <translation>%1 még nem lépett ki biztonságosan...</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>ismeretlen</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- <message>
- <source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Hiba: A megadott "%1" adatkönyvtár nem létezik.</translation>
- </message>
- <message>
- <source>Error: %1</source>
- <translation>Hiba: %1</translation>
- </message>
-</context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>Kép &amp;mentése</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>Kép má&amp;solása</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>QR-kód mentése</translation>
- </message>
- <message>
- <source>PNG Image (*.png)</source>
- <translation>PNG kép (*.png)</translation>
- </message>
-</context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>N/A</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Kliens verzió</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Információ</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Hibakereső ablak</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Általános</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>BerkeleyDB verzió</translation>
- </message>
- <message>
- <source>Datadir</source>
- <translation>Adat elérési útja</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Indítás időpontja</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Hálózat</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Név</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Kapcsolatok száma</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Blokklánc</translation>
- </message>
- <message>
- <source>Current number of blocks</source>
- <translation>Blokkok aktuális száma</translation>
- </message>
- <message>
- <source>Memory Pool</source>
- <translation>Memória Halom</translation>
- </message>
- <message>
- <source>Current number of transactions</source>
- <translation>Tranzakciók pillanatnyi száma</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Memóriahasználat</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Alaphelyzet</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Fogadva</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Elküldve</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Peer-ek</translation>
- </message>
- <message>
- <source>Banned peers</source>
- <translation>Letiltott peer-ek</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <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>
- <message>
- <source>Version</source>
- <translation>Verzió</translation>
- </message>
- <message>
- <source>Starting Block</source>
- <translation>Kezdeti blokk</translation>
- </message>
- <message>
- <source>Synced Headers</source>
- <translation>Szikronizált fejlécek</translation>
- </message>
- <message>
- <source>Synced Blocks</source>
- <translation>Szinkronizált blokkok</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>User Agent</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 hibakeresési naplófájl megnyitása a jelenlegi könyvtárból. Ez néhány másodpercig eltarthat nagyobb naplófájlok esetén.</translation>
- </message>
- <message>
- <source>Decrease font size</source>
- <translation>Betűméret csökkentése</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation>Betűméret növelése</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Szolgáltatások</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Csatlakozási idő</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Utolsó küldés</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Utolsó fogadás</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Ping idő</translation>
- </message>
- <message>
- <source>The duration of a currently outstanding ping.</source>
- <translation>A jelenlegi kiváló ping időtartama.</translation>
- </message>
- <message>
- <source>Ping Wait</source>
- <translation>Várakozás ping-re</translation>
- </message>
- <message>
- <source>Min Ping</source>
- <translation>Minimum Ping</translation>
- </message>
- <message>
- <source>Time Offset</source>
- <translation>Idő Eltolódás</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Utolsó blokk ideje</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Megnyitás</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Konzol</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Hálózati forgalom</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Összesen</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Be:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Ki:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Hibakeresési napló fájl</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Konzol ürítése</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;óra</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;nap</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;hét</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;év</translation>
- </message>
- <message>
- <source>&amp;Disconnect</source>
- <translation>&amp;Szétkapcsol</translation>
- </message>
- <message>
- <source>Ban for</source>
- <translation>Tiltás oka</translation>
- </message>
- <message>
- <source>&amp;Unban</source>
- <translation>&amp;Tiltás feloldása</translation>
- </message>
- <message>
- <source>Welcome to the %1 RPC console.</source>
- <translation>Üdv az %1 RPC konzoljában.</translation>
- </message>
- <message>
- <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
- <translation>Az előzmények közötti navigálásához használd a fel és le nyilakat, és %1-t a képernyő törléséhez.</translation>
- </message>
- <message>
- <source>Type %1 for an overview of available commands.</source>
- <translation>Írja be a %1 parancsot az elérhető utasítások áttekintéséhez.</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>FIGYELEM: Csalók megpróbálnak felhasználókat rávenni, hogy parancsokat írjanak be ide, és ellopják a tárca tartalmát. Ne használja ezt a konzolt anélkül, hogy teljesen megértené egy parancs kiadásának a következményeit.</translation>
- </message>
- <message>
- <source>Network activity disabled</source>
- <translation>Hálózat aktivitása letiltva</translation>
- </message>
- <message>
- <source>(node id: %1)</source>
- <translation>(csomópont azonosító: %1)</translation>
- </message>
- <message>
- <source>via %1</source>
- <translation>%1-n keresztül</translation>
- </message>
- <message>
- <source>never</source>
- <translation>soha</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Bejövő</translation>
- </message>
- <message>
- <source>Outbound</source>
- <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>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>&amp;Összeg:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Címke:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Üzenet:</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>Opciónális üzenet csatolása a fizetési kérelemhez, ami a kérelem megnyitásakor megjelenik. Megjegyzés: Az üzenet nem lesz elküldve a fizetéssel a Bitcoin hálózaton.</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation>Opcionális címke hozzáadása az új fogadó címhez.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Használja ezt az űrlapot fizetések kérésére. Minden mező &lt;b&gt;opcionális&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>Egy opcionálisan kérhető összeg. Hagyja üresen, vagy írjon be nullát, ha nem kívánja használni.</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Az űrlap összes mezőjének törlése</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Törlés</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>A kért kifizetések előzménye</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Fizetési kérelem</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Mutassa meg a kiválasztott kérelmet (ugyanaz, mint a duplaklikk)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Megmutatás</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>A kijelölt elemek törlése a listáról</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Eltávolítás</translation>
- </message>
- <message>
- <source>Copy URI</source>
- <translation>URI másolása</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Címke másolása</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Üzenet másolása</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Összeg másolása</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>QR-kód</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>&amp;URI másolása</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Cím másolása</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>Kép &amp;mentése</translation>
- </message>
- <message>
- <source>Request payment to %1</source>
- <translation>Fizetési kérelem tőle: %1</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation>Fizetési információ</translation>
- </message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Cím</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Összeg</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Címke</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Üzenet</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Tárca</translation>
- </message>
- <message>
- <source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation>A keletkezett URI túl hosszú, próbálja meg csökkenteni a cimke / üzenet szövegének méretét.</translation>
- </message>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation>Hiba lépett fel az URI QR kóddá alakításakor.</translation>
- </message>
-</context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Címke</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Üzenet</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nincs címke)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation>(nincs üzenet)</translation>
- </message>
- <message>
- <source>(no amount requested)</source>
- <translation>(nem kért összeget)</translation>
- </message>
- <message>
- <source>Requested</source>
- <translation>Kért</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Érmék küldése</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Pénzküldés beállításai</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Bemenetek...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>automatikusan kiválasztva</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Fedezethiány!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Mennyiség:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bájtok:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Öszeg:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Díj:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Eljárási díj után:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Visszajáró:</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>Ha ezt a beállítást engedélyezi, de a visszajáró cím érvénytelen, a visszajáró egy újonnan generált címre lesz küldve.</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Egyedi visszajáró cím</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Tranzakciós díj:</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Választás...</translation>
- </message>
- <message>
- <source>Warning: Fee estimation is currently not possible.</source>
- <translation>Figyelem: A hozzávetőleges díjszámítás jelenleg nem lehetséges.</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>kilobájtonként</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Elrejtés</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Ajánlott:</translation>
- </message>
- <message>
- <source>Custom:</source>
- <translation>Egyedi:</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Küldés egyszerre több címzettnek</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Az űrlap összes mezőjének törlése</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Porszem:</translation>
- </message>
- <message>
- <source>Confirmation time target:</source>
- <translation>Megerősítési idő cél:</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>&amp;Mindent töröl</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Egyenleg:</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>&amp;Küldés</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Mennyiség másolása</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Összeg másolása</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Díj másolása</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Eljárási díj utáni másolás</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Bájtok másolása</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Por másolása</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Változás másolása</translation>
- </message>
- <message>
- <source>Are you sure you want to send?</source>
- <translation>Biztosan elküldi?</translation>
- </message>
- <message>
- <source>or</source>
- <translation>vagy</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Tranzakciós díj</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation>Az összegnek nagyobbnak kell lennie, mint 0.</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation>Az összeg túlhaladja az egyenleged.</translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation>Tranzakció készítése sikertelen!</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Fizetési kérelem lejárt</translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation>Figyelem: érvénytelen Bitcoin cím</translation>
- </message>
- <message>
- <source>Confirm custom change address</source>
- <translation>Egyedi visszajáró cím megerősítése</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nincs címke)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>&amp;Összeg:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Címke:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Válasszon a korábban használt címek közül</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Ez egy normális fizetés.</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Cím beillesztése vágólapról</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Bejegyzés eltávolítása</translation>
- </message>
- <message>
- <source>Use available balance</source>
- <translation>Elérhető egyenleg használata</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Üzenet:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Jegyzet:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Igen</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>%1 is shutting down...</source>
- <translation>%1 leáll...</translation>
- </message>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>Ne kapcsold ki a számítógépet, amíg ez az üzenet el nem tűnik.</translation>
- </message>
-</context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Aláírások - Aláír / Megerősít egy Üzenetet</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Válasszon a korábban használt címek közül</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Cím beillesztése vágólapról</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Aláírás</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>A pillanatnyi aláírás másolása a rendszer vágólapjára</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>&amp;Mindent töröl</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Üzenet megerősítése</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation>A beírt cím érvénytelen.</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Ellenőrizze a címet majd próbálja újból.</translation>
- </message>
- <message>
- <source>Wallet unlock was cancelled.</source>
- <translation>A tárca feloldása elutasítva</translation>
- </message>
- <message>
- <source>Message signing failed.</source>
- <translation>Üzenet aláírása sikertelen</translation>
- </message>
- <message>
- <source>Message signed.</source>
- <translation>Üzenet aláírva</translation>
- </message>
- <message>
- <source>Please check the signature and try again.</source>
- <translation>Ellenőrizze az aláírást majd próbálja újból</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation>Üzenet megerősítve.</translation>
- </message>
-</context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KB/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Status</source>
- <translation>Állapot</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Forrás</translation>
- </message>
- <message>
- <source>Generated</source>
- <translation>Létrehozott</translation>
- </message>
- <message>
- <source>From</source>
- <translation>Innen:</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>ismeretlen</translation>
- </message>
- <message>
- <source>To</source>
- <translation>Ide:</translation>
- </message>
- <message>
- <source>own address</source>
- <translation>saját címek</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>megfigyelés</translation>
- </message>
- <message>
- <source>label</source>
- <translation>címke</translation>
- </message>
- <message>
- <source>not accepted</source>
- <translation>nem elfogadott</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Tranzakciós díj</translation>
- </message>
- <message>
- <source>Net amount</source>
- <translation>Nettó összeg</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Üzenet</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Megjegyzés</translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation>Tranzakció azonosító</translation>
- </message>
- <message>
- <source>Transaction total size</source>
- <translation>Tranzakció teljes mérete</translation>
- </message>
- <message>
- <source>Merchant</source>
- <translation>Kereskedő</translation>
- </message>
- <message>
- <source>Debug information</source>
- <translation>Hibakeresési információk</translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation>Tranzakció</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Összeg</translation>
- </message>
- <message>
- <source>true</source>
- <translation>igaz</translation>
- </message>
- <message>
- <source>false</source>
- <translation>hamis</translation>
- </message>
-</context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Típus</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Címke</translation>
- </message>
- <message>
- <source>Unconfirmed</source>
- <translation>Nem megerősített</translation>
- </message>
- <message>
- <source>Generated but not accepted</source>
- <translation>Generált de nem elfogadott</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Küldés neki</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Bányászott</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>megfigyelés</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nincs címke)</translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation>Tranzakció típusa.</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Összes</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Ma</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>E héten</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>E hónapban</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Előző hónapban</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Ez évben</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Tartomány...</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Küldés neki</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Bányászott</translation>
- </message>
- <message>
- <source>Other</source>
- <translation>Egyéb</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation>Minimum összeg</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Cím másolása</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Címke másolása</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Összeg másolása</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Tranzakció ID másolása</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Címke szerkesztése</translation>
- </message>
- <message>
- <source>Show transaction details</source>
- <translation>Tranzakció részletei</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Vesszővel elválasztott adatok (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Jóváhagyva</translation>
- </message>
- <message>
- <source>Watch-only</source>
- <translation>Csak megtekintés</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Típus</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Címke</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Cím</translation>
- </message>
- <message>
- <source>ID</source>
- <translation>ID</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Sikertelen export</translation>
- </message>
- <message>
- <source>Exporting Successful</source>
- <translation>Sikeres exportálás</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Érmék küldése</translation>
- </message>
- <message>
- <source>Increase:</source>
- <translation>Növelés:</translation>
- </message>
- <message>
- <source>New fee:</source>
- <translation>Új díj:</translation>
- </message>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Export</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>A jelenlegi fülön található adat exportálása fájlba</translation>
- </message>
- <message>
- <source>Backup Wallet</source>
- <translation>Tárca biztonsági mentése</translation>
- </message>
- <message>
- <source>Wallet Data (*.dat)</source>
- <translation>Tárca adat (*.dat)</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>Biztonsági mentés sikertelen</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Biztonsági mentés sikeres</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Mag</translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Szeretnéd újra építeni a blokk adatbázist most?</translation>
- </message>
- <message>
- <source>Error initializing block database</source>
- <translation>Hiba a blokk adatbázis inicializálásakor</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Hiba a blokk adatbázis betöltésekor</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Hiba a blokk adatbázis megnyitásakor</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Hiba: Kicsi a lemezterület!</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>Importálás...</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Blokkok megerősítése...</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Információ</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Tranzakció aláírása sikertelen</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>Ez egy fejlesztés alatt álló szoftver.</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>A tranzakció összege túl kicsi</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>A tranzakció túl nagy</translation>
- </message>
- <message>
- <source>Verifying wallet(s)...</source>
- <translation>Tárca/Tárcák megerősítése</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Figyelmeztetés</translation>
- </message>
- <message>
- <source>%s is set very high!</source>
- <translation>%s túl magasra van állítva!</translation>
- </message>
- <message>
- <source>Starting network threads...</source>
- <translation>Hálózati szálak indítása...</translation>
- </message>
- <message>
- <source>Transaction amounts must not be negative</source>
- <translation>A tranzakciók összege nem lehet negatív</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>Legalább egy címzettnek kell lennie a tranzakcióban </translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Fedezethiány</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>A blokkindex betöltése ...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Tárca betöltése...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Nem lehet lemásolni a pénztárcát</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Újraszkennelés</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Betöltés kész</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Hiba</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_id.ts b/src/qt/locale/bitcoin_id.ts
index 1ca62902c8..e7be7825fc 100644
--- a/src/qt/locale/bitcoin_id.ts
+++ b/src/qt/locale/bitcoin_id.ts
@@ -70,6 +70,10 @@
<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>
@@ -132,6 +136,10 @@
<translation>Ulangi kata sandi baru</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Perlihatkan passphrase</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Enkripsi dompet</translation>
</message>
@@ -172,6 +180,30 @@
<translation>Dompet terenkripsi</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>Masukkan passphrase baru ke dompet.&lt;br/&gt;Harap gunakan passphrase dari &lt;b&gt;sepuluh atau lebih karakter acak&lt;/b&gt;, or &lt;b&gt;delapan atau lebih kata&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Masukan passphrase lama dan passphrase baru ke dompet</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>Mengenkripsi dompet Anda tidak dapat sepenuhnya melindungi bitcoin Anda dari pencurian oleh malware yang menginfeksi komputer Anda.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Dompet yang akan dienkripsi</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Dompet anda akan dienkripsi</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Dompet anda sudah dienkripsi</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: Backup sebelumnya yang Anda buat dari file dompet Anda harus diganti dengan file dompet terenkripsi yang baru dibuat. Demi keamanan, backup file dompet sebelumnya yang tidak dienkripsi sebelumnya akan menjadi tidak berguna begitu Anda mulai menggunakan dompet terenkripsi yang baru.</translation>
</message>
@@ -294,6 +326,14 @@
<translation>Buka &amp;URI</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Bikin dompet...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Bikin dompet baru</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Wallet:</translation>
</message>
@@ -334,14 +374,6 @@
<translation>Ubah kata kunci yang digunakan untuk enkripsi dompet</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Jendela Debug</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Buka konsol debug dan diagnosa</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verifikasi pesan...</translation>
</message>
@@ -402,10 +434,6 @@
<translation>Tampilkan daftar alamat dan label yang diterima</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Buka URI bitcoin: atau permintaan pembayaran</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;pilihan Command-line</translation>
</message>
@@ -522,6 +550,10 @@
<translation>Error: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Peringatan: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Tanggal: %1
@@ -743,10 +775,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Membuat Dompet &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Pembuatan dompet gagal</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Peringatan membuat dompet</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Bikin dompet</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Nama Dompet</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>Enkripsi dompet. Dompet akan dienkripsi dengan passphrase pilihan Anda.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Enkripsi Dompet</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>Nonaktifkan private keys dompet ini. Dompet dengan private keys nonaktif tidak akan memiliki private keys dan tidak dapat memiliki seed HD atau private keys impor. Ini sangat ideal untuk dompet watch-only.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>Nonaktifkan 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>Buat dompet kosong. Dompet kosong pada awalnya tidak memiliki private keys atau skrip pribadi. Private keys dan alamat pribadi dapat diimpor, atau seed HD dapat diatur di kemudian hari.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Buat dompet kosong</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Membuat</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -832,10 +912,6 @@
<translation>versi</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Tentang %1</translation>
</message>
@@ -863,6 +939,10 @@
<translation>Ketika Anda mengklik OK, %1 akan mulai mengunduh dan memproses %4 block chain penuh (%2GB), dimulai dari transaksi-transaksi awal di %3 saat %4 diluncurkan pertama kali.</translation>
</message>
<message>
+ <source>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>Mengembalikan pengaturan perlu mengunduh ulang seluruh blockchain. Lebih cepat mengunduh rantai penuh terlebih dahulu dan memangkasnya kemudian. Menonaktifkan beberapa fitur lanjutan.</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>Sinkronisasi awal sangat berat dan mungkin akan menunjukkan permasalahan pada perangkat keras komputer Anda yang sebelumnya tidak tampak. Setiap kali Anda menjalankan %1, aplikasi ini akan melanjutkan pengunduhan dari posisi terakhir.</translation>
</message>
@@ -883,6 +963,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Buang blok setelah verifikasi, kecuali %1 GB terbaru (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>Setidaknya %1 GB data akan disimpan di direktori ini dan akan berkembang seiring berjalannya waktu.</translation>
</message>
@@ -914,7 +998,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(dari %n GB yang dibutuhkan)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB dibutuhkan untuk rantai penuh)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -969,28 +1057,20 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Buka URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Buka permintaan pembayaran dari URI atau data</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Pilih data permintaan pembayaran</translation>
+ <source>Open wallet failed</source>
+ <translation>Gagal membuka wallet</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Pilih data permintaan pembayaran yang akan dibuka</translation>
+ <source>Open wallet warning</source>
+ <translation>Peringatan membuka wallet</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>wallet default</translation>
@@ -1088,7 +1168,7 @@
</message>
<message>
<source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation>Mengembalikan pengaturan ini membutuhkan pengunduhan seluruh blockchain lagi. </translation>
+ <translation>Mengembalikan pengaturan ini membutuhkan pengunduhan seluruh blockchain lagi.</translation>
</message>
<message>
<source>MiB</source>
@@ -1369,16 +1449,12 @@
<translation>'bitcoin://' bukanlah alamat URI yang valid. Silakan gunakan 'bitcoin:'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Anda menggunakan URL BIP70 yang akan tidak lagi didukung di masa mendatang. </translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL permintaan pembayaran tidak valid: %1</translation>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Berhubung kelemahan keamanan yang meluas di BIP70, sangat disarankan agar instruksi pedagang untuk mengganti dompet diabaikan.</translation>
</message>
<message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Tidak dapat memproses pembayaran karena dukungan BIP70 tidak disertakan didalamnya.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Jika Anda menerima kesalahan ini, Anda harus meminta pedagang memberikan URI yang kompatibel dengan BIP21.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1392,66 +1468,6 @@
<source>Payment request file handling</source>
<translation>Pengelolaan file permintaan pembayaran</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>File permintaan pembayaran tidak bisa dibaca! Hal ini bisa disebabkan karena file permintaan pembayaran tidak valid.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Permintaan pembayaran ditolak</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Jaringan permintaan pembayaran tidak sesuai dengan jaringan klien.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Permintaan pembayaran telah kadaluarsa.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Permintaan pembayaran tidak terinisialisasi</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Tidak mendukung pemprosesan pembayaran yang tidak terverifikasi pada script pembayaran khusus.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Permintaan pembayaran tidak valid.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Permintaan jumlah pembayaran %1 terlalu kecil (dianggap "dust transaction").</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Pengembalian dana dari %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Permintaan pembayaran %1 terlalu besar (%2 bita, diperbolehkan %3 bita)</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Terjadi kesalahan komunikasi dengan %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Permintaan pembayaran tidak dapat di parse!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Respon buruk dari server %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Kesalahan permintaan jaringan</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Pembayaran yang diakui</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1594,6 +1610,18 @@
<translation>&amp;Salin Gambar</translation>
</message>
<message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation>Pembuatan tautan terlalu lama, coba kurangi teks untuk label / pesan.</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>Error saat menyandikan tautan ke dalam kode QR.</translation>
+ </message>
+ <message>
+ <source>QR code support not available.</source>
+ <translation>Dukungan kode QR tidak tersedia.</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>Simpan Kode QR</translation>
</message>
@@ -1617,10 +1645,6 @@
<translation>&amp;Informasi</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Jendela debug</translation>
- </message>
- <message>
<source>General</source>
<translation>Umum</translation>
</message>
@@ -1633,10 +1657,18 @@
<translation>Datadir</translation>
</message>
<message>
+ <source>To specify a non-default location of the data directory use the '%1' option.</source>
+ <translation>Untuk menentukan lokasi direktori data yang tidak standar gunakan opsi '%1'.</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>Untuk menentukan lokasi direktori block non-default, gunakan opsi '%1'.</translation>
+ </message>
+ <message>
<source>Startup time</source>
<translation>Waktu nyala</translation>
</message>
@@ -1674,7 +1706,7 @@
</message>
<message>
<source>Wallet: </source>
- <translation>Wallet: </translation>
+ <translation>Wallet:</translation>
</message>
<message>
<source>(none)</source>
@@ -1735,6 +1767,10 @@
</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>Buka file log debug %1 dari direktori data saat ini. Dapat memakan waktu beberapa detik untuk file log besar.</translation>
+ </message>
+ <message>
<source>Decrease font size</source>
<translation>Mengurangi ukuran font</translation>
</message>
@@ -1796,7 +1832,7 @@
</message>
<message>
<source>&amp;Network Traffic</source>
- <translation>Kemacetan &amp;Jaringan </translation>
+ <translation>Kemacetan &amp;Jaringan</translation>
</message>
<message>
<source>Totals</source>
@@ -1863,6 +1899,38 @@
<translation>Untuk informasi lebih gunakan konsol ini dengan ketik %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>PERHATIAN: Para penipu sedang aktif, memberi tahu pengguna untuk mengetik perintah di sini, mencuri isi dompet mereka. Mohon tidak mengunakan konsol ini tanpa sepenuhnya memahami konsekuensi dari suatu perintah.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>Aktivitas jaringan nonaktif</translation>
+ </message>
+ <message>
+ <source>Executing command without any wallet</source>
+ <translation>Menjalankan perintah tanpa dompet apa pun</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(id simpul: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>via %1</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>tidak pernah</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>masuk</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>keluar</translation>
+ </message>
+ <message>
<source>Yes</source>
<translation>Ya</translation>
</message>
@@ -1890,6 +1958,10 @@
<translation>&amp;Pesan:</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>Pesan opsional untuk dilampirkan ke permintaan pembayaran, yang akan ditampilkan ketika permintaan dibuka. Catatan: Pesan tidak akan dikirim dengan pembayaran melalui jaringan Bitcoin.</translation>
+ </message>
+ <message>
<source>An optional label to associate with the new receiving address.</source>
<translation>Label opsional untuk mengasosiasikan dengan alamat penerima baru.</translation>
</message>
@@ -1902,6 +1974,10 @@
<translation>Nilai permintaan opsional. Biarkan ini kosong atau nol bila tidak meminta nilai tertentu.</translation>
</message>
<message>
+ <source>&amp;Create new receiving address</source>
+ <translation>&amp;Create alamat penerima baru</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Hapus informasi dari form.</translation>
</message>
@@ -1910,6 +1986,14 @@
<translation>Hapus</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>Alamat segwit asli (alias Bech32 atau BIP-173) akan mengurangi biaya transaksi anda nantinya dan menawarkan perlindungan yang lebih baik terhadap kesalahan pengetikan, tetapi dompet lama tidak mendukungnya. Ketika tidak dicentang, alamat yang kompatibel dengan dompet lama akan dibuat sebagai gantinya.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Hasilkan alamat asli segwit (Bech32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Riwayat pembayaran yang diminta Anda</translation>
</message>
@@ -1930,10 +2014,18 @@
<translation>Menghapus</translation>
</message>
<message>
+ <source>Copy URI</source>
+ <translation>Salin tautan</translation>
+ </message>
+ <message>
<source>Copy label</source>
<translation>Salin label</translation>
</message>
<message>
+ <source>Copy message</source>
+ <translation>Salin pesan</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>Salin Jumlah</translation>
</message>
@@ -1957,6 +2049,18 @@
<translation>&amp;Simpan Gambaran...</translation>
</message>
<message>
+ <source>Request payment to %1</source>
+ <translation>Minta pembayaran ke %1</translation>
+ </message>
+ <message>
+ <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>
@@ -1969,6 +2073,10 @@
<translation>Label</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Pesan</translation>
+ </message>
+ <message>
<source>Wallet</source>
<translation>Dompet</translation>
</message>
@@ -1984,10 +2092,26 @@
<translation>Label</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Pesan</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(tidak ada label)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation>(tidak ada pesan)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(tidak ada jumlah yang diminta)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>Diminta</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -2047,6 +2171,30 @@
<translation>Biaya Transaksi:</translation>
</message>
<message>
+ <source>Choose...</source>
+ <translation>Pilih...</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>Menggunakan fallbackfee dapat mengakibatkan pengiriman transaksi yang akan memakan waktu beberapa jam atau hari (atau tidak pernah) untuk dikonfirmasi. Pertimbangkan untuk memilih biaya anda secara manual atau tunggu hingga anda telah megesahkan rantai yang lengkap.</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Peringatan: Perkiraan biaya saat ini tidak memungkinkan.</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>Tentukan biaya khusus per kB (1.000 byte) dari ukuran transaksi maya.
+
+Catatan: Karena biaya dihitung berdasarkan per byte, biaya "100 satoshi per kB" untuk ukuran transaksi 500 byte (setengah dari 1 kB) pada akhirnya akan menghasilkan biaya hanya 50 satoshi.</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>per kilobyte</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation>Sembunyikan</translation>
</message>
@@ -2055,6 +2203,14 @@
<translation>Disarankan</translation>
</message>
<message>
+ <source>Custom:</source>
+ <translation>Khusus</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(Smart fee belum di-inisialisasi. Biasanya hal ini akan memerlukan beberapa block...)</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>Kirim ke beberapa penerima sekaligus</translation>
</message>
@@ -2071,6 +2227,26 @@
<translation>Dust:</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>Ketika volume transaksi lebih sedikit daripada ruang di blok, penambang serta simpul yang menyiarkanikan dapat memberlakukan biaya minimum. Anda boleh hanya membayar biaya minimum, tetapi perlu diketahui bahwa ini dapat menghasilkan transaksi yang tidak pernah dikonfirmasi setelah ada lebih banyak permintaan untuk transaksi bitcoin daripada yang dapat diproses jaringan.</translation>
+ </message>
+ <message>
+ <source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
+ <translation>Biaya yang terlalu rendah dapat menyebabkan transaksi tidak terkonfirmasi (baca tooltip)</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>Target waktu konfirmasi:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Izinkan 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>Dengan Replace-By-Fee (BIP-125) Anda dapat menambah biaya transaksi setelah dikirim. Tanpa ini, biaya yang lebih tinggi dapat direkomendasikan untuk mengkompensasi peningkatan risiko keterlambatan transaksi.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Hapus &amp;Semua</translation>
</message>
@@ -2115,13 +2291,105 @@
<translation>Salin Perubahan</translation>
</message>
<message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 block)</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation>dari dompet '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 ke '%2'</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 ke %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Apakah anda yakin ingin mengirimkan?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>atau</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Anda dapat menambah biaya kemudian (sinyal Replace-By-Fee, BIP-125).</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Mohon periksa kembali transaksi anda.</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Biaya Transaksi</translation>
</message>
<message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Tidak memberi sinyal Replace-By-Fee, BIP-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Jumlah Keseluruhan</translation>
+ </message>
+ <message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Untuk meninjau daftar penerima, klik "Tampilkan Detail ..."</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Konfirmasi pengiriman koin</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>Alamat penerima tidak sesuai. Mohon periksa kembali.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Jumlah pembayaran harus lebih besar daripada 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Jumlah melebihi saldo anda.</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>Alamat duplikat ditemukan: alamat hanya boleh digunakan sekali saja.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Pembuatan transaksi gagal!</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>Biaya yang lebih tinggi dari %1 dianggap sebagai biaya yang sangat tinggi.</translation>
+ </message>
+ <message>
<source>Payment request expired.</source>
<translation>Permintaan pembayaran telah kadaluarsa.</translation>
</message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>Diperkirakan akan memulai konfirmasi dalam %n blok.</numerusform></translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Peringatan: Alamat Bitcoin tidak valid</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Peringatan: Alamat tidak dikenal</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation>Konfirmasi perubahan alamat</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>Alamat yang anda pilih untuk diubah bukan bagian dari dompet ini. Sebagian atau semua dana di dompet anda mungkin dikirim ke alamat ini. Apakah anda yakin?</translation>
+ </message>
<message>
<source>(no label)</source>
<translation>(tidak ada label)</translation>
@@ -2146,8 +2414,8 @@
<translation>Pilih alamat yang telah digunakan sebelumnya</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Ini adalah pembayaran normal</translation>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>Alamat Bitcoin untuk mengirim pembayaran</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2166,14 +2434,38 @@
<translation>Hapus masukan ini</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>Biaya akan diambil dari jumlah yang dikirim. Penerima akan menerima bitcoin lebih sedikit daripada yang di masukkan di bidang jumlah. Jika ada beberapa penerima, biaya dibagi rata.</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>Kurangi biaya dari jumlah</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>Gunakan saldo yang tersedia</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Pesan:</translation>
</message>
<message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>Ini permintaan pembayaran yang tidak diautentikasi.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>Ini permintaan pembayaran yang diautentikasi.</translation>
+ </message>
+ <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation>Masukkan label untuk alamat ini untuk dimasukan dalam daftar alamat yang pernah digunakan</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>Pesan yang dilampirkan ke bitcoin: URI yang akan disimpan dengan transaksi untuk referensi Anda. Catatan: Pesan ini tidak akan dikirim melalui jaringan Bitcoin.</translation>
+ </message>
+ <message>
<source>Pay To:</source>
<translation>Kirim Ke:</translation>
</message>
@@ -2181,13 +2473,6 @@
<source>Memo:</source>
<translation>Catatan Peringatan:</translation>
</message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ya</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2207,6 +2492,14 @@
<translation>&amp;Tandakan Pesan</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>Anda dapat menandatangani pesan / perjanjian dengan alamat Anda untuk membuktikan bahwa Anda dapat menerima bitcoin yang dikirimkan kepada mereka. Berhati-hatilah untuk tidak menandatangani apa pun yang samar-samar atau acak, karena serangan phishing mungkin mencoba menipu Anda untuk menandatangani identitas Anda kepada mereka. Hanya tandatangani pernyataan terperinci yang Anda setujui.</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation>Alamat Bitcoin untuk menandatangani pesan</translation>
+ </message>
+ <message>
<source>Choose previously used address</source>
<translation>Pilih alamat yang telah digunakan sebelumnya</translation>
</message>
@@ -2255,6 +2548,18 @@
<translation>&amp;Verifikasi Pesan</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>Masukkan alamat penerima, pesan (pastikan Anda menyalin persis jeda baris, spasi, tab, dll) dan tanda tangan di bawah untuk memverifikasi pesan. Berhati-hatilah untuk tidak memberi informasi lebih ke tanda tangan daripada apa yang ada dalam pesan yang ditandatangani itu sendiri, untuk menghindari dikelabui oleh serangan man-in-the-middle. Perhatikan bahwa ini hanya membuktikan pihak penandatangan menerima dengan alamat, tapi tidak dapat membuktikan pengiriman dari transaksi apa pun!</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation>Alamat Bitcoin yang menandatangani pesan</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>Verifikasi pesan untuk memastikannya ditandatangani dengan alamat Bitcoin tersebut</translation>
+ </message>
+ <message>
<source>Verify &amp;Message</source>
<translation>Verifikasi &amp;Pesan</translation>
</message>
@@ -2262,7 +2567,59 @@
<source>Reset all verify message fields</source>
<translation>Hapus semua bidang verifikasi pesan</translation>
</message>
- </context>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Klik "Sign Message" untuk menghasilkan tanda tangan</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>Alamat yang dimasukkan tidak valid.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Mohon periksa alamat dan coba lagi.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>Alamat yang dimasukkan tidak merujuk pada kunci.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>Pembukaan kunci dompet dibatalkan.</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>Private key untuk alamat yang dimasukkan tidak tersedia.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Penandatanganan pesan gagal.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Pesan sudah ditandatangani.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>Tanda tangan tidak dapat disandikan.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Mohon periksa tanda tangan dan coba lagi.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>Tanda tangan tidak cocok dengan intisari pesan.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Verifikasi pesan gagal.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Pesan diverifikasi.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
<message>
@@ -2272,30 +2629,114 @@
</context>
<context>
<name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Buka untuk %n lebih blok</numerusform></translation>
+ </message>
+ <message>
+ <source>Open until %1</source>
+ <translation>Buka sampai %1</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, %1</source>
+ <translation>0/belum dikonfirmasi, %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/belum dikonfirmasi</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 konfirmasi</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Status</translation>
+ </message>
<message>
<source>Date</source>
<translation>Tanggal</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>Sumber</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>tidak diketahui</translation>
</message>
<message>
+ <source>label</source>
+ <translation>label</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Kredit</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>tidak diterima</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 kredit</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Biaya Transaksi</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Pesan</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Komentar</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID Transaksi</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Informasi debug</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transaksi</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Jumlah</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>benar</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>salah</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
<source>This pane shows a detailed description of the transaction</source>
<translation>Jendela ini menampilkan deskripsi rinci dari transaksi tersebut</translation>
</message>
- </context>
+ <message>
+ <source>Details for %1</source>
+ <translation>Detail untuk %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
@@ -2303,17 +2744,101 @@
<translation>Tanggal</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Tipe</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Label</translation>
</message>
<message>
+ <source>Open until %1</source>
+ <translation>Buka sampai %1</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>Belum dikonfirmasi</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Diterima dengan</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Diterima dari</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Dikirim ke</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(tidak ada label)</translation>
</message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Tanggal dan waktu transaksi telah diterima.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Tipe transaksi.</translation>
+ </message>
</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Semua</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Hari ini</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Minggu ini</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Bulan ini</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Bulan lalu</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Tahun ini</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Diterima dengan</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Dikirim ke</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Lainnya</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Ketik alamat, id transaksi, atau label untuk menelusuri</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Jumlah min</translation>
+ </message>
+ <message>
+ <source>Abandon transaction</source>
+ <translation>Batalkan transaksi</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>Tingkatkan biaya transaksi</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>Salin alamat</translation>
</message>
@@ -2330,6 +2855,22 @@
<translation>Salain ID Transaksi</translation>
</message>
<message>
+ <source>Copy full transaction details</source>
+ <translation>Salin detail transaksi</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Ubah label</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Lihat detail transaksi</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>Ekspor Riwayat Transaksi</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Berkas yang berformat(*.csv)</translation>
</message>
@@ -2342,6 +2883,10 @@
<translation>Tanggal</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Tipe</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Label</translation>
</message>
@@ -2350,9 +2895,17 @@
<translation>Alamat</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>Mengekspor Gagal</translation>
</message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Ekspor Berhasil</translation>
+ </message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
@@ -2374,6 +2927,26 @@
<translation>Kirim Koin</translation>
</message>
<message>
+ <source>Increasing transaction fee failed</source>
+ <translation>Gagal meningkatkan biaya transaksi</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>Apa Anda ingin meningkatkan biayanya?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>Biaya saat ini:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>Tingkatkan:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>Biaya baru:</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>wallet default</translation>
</message>
@@ -2388,12 +2961,24 @@
<source>Export the data in the current tab to a file</source>
<translation>Ekspor data dalam tab sekarang ke sebuah berkas</translation>
</message>
- </context>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Pencadangan Gagal</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Pencadangan Berhasil</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>Batal</translation>
+ </message>
+</context>
<context>
<name>bitcoin-core</name>
<message>
<source>Corrupted block database detected</source>
- <translation>Menemukan database blok yang rusak </translation>
+ <translation>Menemukan database blok yang rusak</translation>
</message>
<message>
<source>Do you want to rebuild the block database now?</source>
@@ -2424,6 +3009,10 @@
<translation>Tidak bisa cari blok pertama, atau blok pertama salah. Salah direktori untuk jaringan?</translation>
</message>
<message>
+ <source>Error: Disk space is too low!</source>
+ <translation>Eror: Kapasitas penyimpanan penuh!</translation>
+ </message>
+ <message>
<source>Not enough file descriptors available.</source>
<translation>Deskripsi berkas tidak tersedia dengan cukup.</translation>
</message>
@@ -2432,6 +3021,10 @@
<translation>Blok-blok sedang diverifikasi...</translation>
</message>
<message>
+ <source>Error: Disk space is low for %s</source>
+ <translation>Eror: Kapasitas penyimpanan penuh untuk %s</translation>
+ </message>
+ <message>
<source>Signing transaction failed</source>
<translation>Tandatangani transaksi tergagal</translation>
</message>
diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts
deleted file mode 100644
index a487936fd2..0000000000
--- a/src/qt/locale/bitcoin_id_ID.ts
+++ /dev/null
@@ -1,2137 +0,0 @@
-<TS language="id_ID" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Klik-kanan untuk mengubah alamat atau label</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Buat alamat baru</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Baru</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Salin alamat yang dipilih ke clipboard</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Menyalin</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>T&amp;utup</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Hapus alamat yang sementara dipilih dari daftar</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Masukkan alamat atau label untuk mencari</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Ekspor data dalam tab sekarang ke sebuah berkas</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Ekspor</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Hapus</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Pilih alamat untuk mengirim koin</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Piih alamat untuk menerima koin</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>&amp;Pilih</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Alamat-alamat pengirim</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Alamat-alamat penerima</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>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. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Berikut ialah alamat-alamat Bitcoin Anda yang digunakan untuk menerima pembayaran. Dianjurkan untuk menggunakan alamat penerimaan baru untuk setiap transaksi.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Salin Alamat</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Salin&amp; Label</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Ubah</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Ekspor Daftar Alamat</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Berkas CSV (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Gagal Mengekspor</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Terjadi kesalahan saat mencoba menyimpan daftar alamat ke %1. Silakan coba lagi.</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Alamat</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(tidak ada label)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Dialog Kata Sandi</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Masukkan kata sandi</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Kata sandi baru</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Ulangi kata sandi baru</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Tampilkan kata sandi</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Masukan kata sandi baru ke dompet.&lt;br/&gt;Mohon gunakan kata sandi &lt;b&gt;sepuluh karakter acak atau lebih&lt;/b&gt;, atau &lt;b&gt; delapan atau lebih beberapa kata &lt;/​​b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Enkripsi dompet</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Operasi ini memerlukan kata sandi dompet Anda untuk membuka dompet.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Buka dompet</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Operasi ini memerlukan kata sandi dompet Anda untuk mendekripsikan dompet.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Dekripsi dompet</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Ganti kata sandi</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Masukkan kata sandi lama dan kata sandi baru ke dompet.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Konfirmasi pengenkripsian dompet</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Peringatan: Jika Anda mengenkripsi dompet Anda dan lupa kata sandi Anda, Anda akan &lt;b&gt;KEHILANGAN SEMUA BITCOIN ANDA&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Apakah Anda yakin ingin enkripsi dompet Anda?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Dompet terenkripsi</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 sekarang akan ditutup untuk menyelesaikan proses enkripsi. Ingatlah bahwa mengenkripsi dompet Anda tidak dapat sepenuhnya melindungi komputer Anda dari pencurian malware yang menginfeksi komputer Anda.</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: Backup sebelumnya yang Anda buat dari file dompet Anda harus diganti dengan file dompet terenkripsi yang baru dibuat. Demi keamanan, backup file dompet sebelumnya yang tidak dienkripsi sebelumnya akan menjadi tidak berguna begitu Anda mulai menggunakan dompet terenkripsi yang baru.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Pengenkripsian dompet gagal</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Pengenkripsian dompet gagal karena kesalahan internal. Dompet Anda tidak dienkripsi.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Kata sandi yang dimasukkan tidak cocok.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Membuka dompet gagal</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Kata sandi yang dimasukkan untuk dekripsi dompet salah.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Dekripsi dompet gagal</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Kata sandi berhasil diganti.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Peringatan: Tombol Caps Lock aktif!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmask</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Di banned sampai</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Pesan &amp;penanda...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Sinkronisasi dengan jaringan...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Kilasan</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Node</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Tampilkan gambaran umum dompet Anda</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transaksi</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Lihat riwayat transaksi</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>K&amp;eluar</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Keluar dari aplikasi</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Tentang%1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Tampilkan informasi perihal %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Mengenai &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Tampilkan informasi mengenai Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Pilihan...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Pengubahan opsi konfigurasi untuk %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Enkripsi Dompet...</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Cadangkan Dompet...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Ubah Kata Kunci...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Alamat-alamat untuk mengirim...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>&amp;Alamat-alamat untuk menerima...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Buka &amp;URI</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>Wallet:</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>wallet default</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Klik untuk menonaktifkan aktivitas jaringan.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Aktivitas jaringan dinonaktifkan.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Klik untuk mengaktifkan aktivitas jaringan lagi.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Menyinkronkan Header (%1%) ...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Mengindex ulang blok di dalam disk...</translation>
- </message>
- <message>
- <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>Proxy di &lt;b&gt;aktifkan&lt;/b&gt;: %1</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Kirim koin ke alamat Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Cadangkan dompet ke lokasi lain</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Ubah kata kunci yang digunakan untuk enkripsi dompet</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Jendela Debug</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Buka konsol debug dan diagnosa</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Verifikasi pesan...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Dompet</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Kirim</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Menerima</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Tampilkan / Sembunyikan</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Tampilkan atau sembunyikan jendela utama</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Enkripsi private key yang dimiliki dompet Anda</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Tanda tangani sebuah pesan menggunakan alamat Bitcoin Anda untuk membuktikan bahwa Anda adalah pemilik alamat tersebut</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Verifikasi pesan untuk memastikan bahwa pesan tersebut ditanda tangani oleh suatu alamat Bitcoin tertentu</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Berkas</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Pengaturan</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Bantuan</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Baris tab</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Permintaan pembayaran (membuat kode QR dan bitcoin: URIs)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Tampilkan daftar alamat dan label yang terkirim</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Tampilkan daftar alamat dan label yang diterima</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Buka URI bitcoin: atau permintaan pembayaran</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;pilihan Command-line</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n koneksi aktif ke jaringan Bitcoin</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Pengindeksan blok pada disk ...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Memproses blok pada disk ...</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>%n blok dari riwayat transaksi diproses.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>kurang %1</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Blok terakhir yang diterima %1 lalu.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Transaksi setelah ini belum akan terlihat.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Terjadi sebuah kesalahan</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Peringatan</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informasi</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Terbaru</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Tampilkan %1 pesan bantuan untuk mendapatkan daftar opsi baris perintah Bitcoin yang memungkinkan</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>%1 klien</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Menghubungkan ke peer...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Menyusul...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Tanggal: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Jumlah: %1
-</translation>
- </message>
- <message>
- <source>Wallet: %1
-</source>
- <translation>Wallet: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Tipe: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Label: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Alamat: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Transaksi terkirim</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Transaksi diterima</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>Pembuatan kunci HD &lt;b&gt;diaktifkan&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>Pembuatan kunci HD &lt;b&gt;dinonaktifkan&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>Dompet saat ini &lt;b&gt;terenkripsi&lt;/b&gt; dan &lt;b&gt;terbuka&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>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>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Pemilihan Koin</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Kuantitas:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Jumlah:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Biaya:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Dust:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Dengan Biaya:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Kembalian:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(Tidak)memilih semua</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Tree mode</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Mode daftar</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Jumlah</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Diterima dengan label</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Diterima dengan alamat</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Tanggal</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Konfirmasi</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Terkonfirmasi</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Salin alamat</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Salin label</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Salin Jumlah</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Salain ID Transaksi</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Kunci Yang Tidak Digunakan</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Buka Kunci Yang Tidak Digunakan</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Salin Kuantitas</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Salin biaya</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Salin Setelah Upah</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Salin bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Salin jumlah yang lebih kecil</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Salin Perubahan</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 terkunci)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>Ya</translation>
- </message>
- <message>
- <source>no</source>
- <translation>Tidak</translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Dapat bervariasi +/- %1 satoshi per input.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(tidak ada label)</translation>
- </message>
- <message>
- <source>change from %1 (%2)</source>
- <translation>kembalian dari %1 (%2)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation>(kembalian)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Ubah 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>Label yang terkait dengan daftar alamat</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>Alamat yang terkait dengan daftar alamat. Hanya dapat diubah untuk alamat pengirim.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Alamat</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Alamat pengirim baru</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Ubah alamat penerima</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Ubah alamat pengirim</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>Alamat yang dimasukkan "%1" bukanlah alamat Bitcoin yang valid.</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>Alamat "%1" sudah ada sebagai alamat penerimaan dengan label "%2" sehingga tidak bisa ditambah sebagai alamat pengiriman.</translation>
- </message>
- <message>
- <source>The entered address "%1" is already in the address book with label "%2".</source>
- <translation>Alamat "%1" yang dimasukkan sudah ada di dalam buku alamat dengan label "%2".</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Tidak dapat membuka dompet.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Pembuatan kunci baru gagal.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Sebuah data direktori baru telah dibuat.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>nama</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>Direktori masih ada. Tambahlah %1 apabila Anda ingin membuat direktori baru disini.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Sudah ada path, dan itu bukan direktori.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Tidak bisa membuat direktori data disini.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>versi</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>Tentang %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Pilihan Command-line</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Selamat Datang</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Selamat Datang di %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>Karena ini adalah pertama kalinya program dijalankan, Anda dapat memilih lokasi %1 akan menyimpan data.</translation>
- </message>
- <message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation>Ketika Anda mengklik OK, %1 akan mulai mengunduh dan memproses %4 block chain penuh (%2GB), dimulai dari transaksi-transaksi awal di %3 saat %4 diluncurkan pertama kali.</translation>
- </message>
- <message>
- <source>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>Sinkronisasi awal sangat berat dan mungkin akan menunjukkan permasalahan pada perangkat keras komputer Anda yang sebelumnya tidak tampak. Setiap kali Anda menjalankan %1, aplikasi ini akan melanjutkan pengunduhan dari posisi terakhir.</translation>
- </message>
- <message>
- <source>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>Apabila Anda memilih untuk membatasi penyimpanan block chain (pruning), data historis tetap akan diunduh dan diproses. Namun, data akan dihapus setelahnya untuk menjaga pemakaian disk agar tetap sedikit.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Gunakan direktori data default.</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Gunakan direktori pilihan Anda:</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation>Setidaknya %1 GB data akan disimpan di direktori ini dan akan berkembang seiring berjalannya waktu.</translation>
- </message>
- <message>
- <source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>%1 GB data akan disimpan di direktori ini.</translation>
- </message>
- <message>
- <source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 akan mengunduh dan menyimpan salinan Bitcoin block chain.</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation>Dompet juga akan disimpan di direktori ini.</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Kesalahan: Direktori data "%1" tidak dapat dibuat.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Kesalahan</translation>
- </message>
- <message numerus="yes">
- <source>%n GB of free space available</source>
- <translation><numerusform>%n GB ruang kosong tersedia.</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>(of %n GB needed)</source>
- <translation><numerusform>(dari %n GB yang dibutuhkan)</numerusform></translation>
- </message>
-</context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Formulir</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>Transaksi-transaksi terkini mungkin belum terlihat dan oleh karenanya, saldo dompet Anda mungkin tidak tepat. Informasi ini akan akurat ketika dompet Anda tersinkronisasi dengan jaringan Bitcoin, seperti rincian berikut.</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>Usaha untuk menggunakan bitcoin yang dipengaruhi oleh transaksi yang belum terlihat tidak akan diterima oleh jaringan.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Jumlah blok tersisa</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Tidak diketahui...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Waktu blok terakhir</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation>Perkembangan</translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation>Peningkatan perkembangan per jam</translation>
- </message>
- <message>
- <source>calculating...</source>
- <translation>menghitung...</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation>Estimasi waktu tersisa sampai tersinkronisasi</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Sembunyikan</translation>
- </message>
- <message>
- <source>Unknown. Syncing Headers (%1)...</source>
- <translation>Tidak diketahui. Menyinkronisasikan Headers (%1)...</translation>
- </message>
-</context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Buka URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Buka permintaan pembayaran dari URI atau data</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Pilih data permintaan pembayaran</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Pilih data permintaan pembayaran yang akan dibuka</translation>
- </message>
-</context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Pilihan</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Utama</translation>
- </message>
- <message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation>Mulai %1 secara otomatis setelah masuk ke dalam sistem.</translation>
- </message>
- <message>
- <source>&amp;Start %1 on system login</source>
- <translation>Mulai %1 ketika masuk ke &amp;sistem</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Ukuran cache &amp;database</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>Jumlah script &amp;verification threads</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Alamat IP proxy (cth. 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>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>
- <message>
- <source>&amp;Hide tray icon</source>
- <translation>&amp;Sembunyikan ikon tray</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>Minimalisasi aplikasi ketika jendela ditutup. Ketika pilihan ini dipilih, aplikasi akan menutup seluruhnya jika anda memilih Keluar di menu yang tersedia.</translation>
- </message>
- <message>
- <source>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>URL pihak ketika (misalnya sebuah block explorer) yang mumcul dalam tab transaksi sebagai konteks menu. %s dalam URL diganti dengan kode transaksi. URL dipisahkan dengan tanda vertikal |.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Pilihan command-line yang aktif menimpa diatas opsi: </translation>
- </message>
- <message>
- <source>Open the %1 configuration file from the working directory.</source>
- <translation>Buka file konfigurasi %1 dari direktori kerja.</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Buka Berkas Konfigurasi</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Kembalikan semua pengaturan ke awal.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Reset Pilihan</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Jaringan</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>Menonaktifkan beberapa fitur canggih akan tetapi semua block akan tetap divalidasi seutuhnya. Mengembalikan pengaturan ini memerlukan untuk mengunduh seluruh blockchain. Penggunaan disk mungkin akan lebih tinggi.</translation>
- </message>
- <message>
- <source>GB</source>
- <translation>GB</translation>
- </message>
- <message>
- <source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation>Mengembalikan pengaturan ini membutuhkan pengunduhan seluruh blockchain lagi. </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>D&amp;ompet</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Ahli</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Perbolehkan fitur &amp;pengaturan koin</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>Jika Anda menonaktifkan perubahan saldo untuk transaksi yang belum dikonfirmasi, perubahan dari transaksi tidak dapat dilakukan sampai transaksi memiliki setidaknya satu konfirmasi. Hal ini juga mempengaruhi bagaimana saldo Anda dihitung.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>&amp;Perubahan saldo untuk transaksi yang belum dikonfirmasi</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>Otomatis membuka port client Bitcoin di router. Hanya berjalan apabila router anda mendukung UPnP dan di-enable.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Petakan port dengan &amp;UPnP</translation>
- </message>
- <message>
- <source>Accept connections from outside.</source>
- <translation>Terima koneksi-koneksi dari luar.</translation>
- </message>
- <message>
- <source>Allow incomin&amp;g connections</source>
- <translation>Terima koneksi-koneksi masuk</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Hubungkan ke jaringan Bitcoin melalui SOCKS5 proxy.</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Hubungkan melalui proxy SOCKS5 (proxy default):</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>IP Proxy:</translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>&amp;Port:</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Port proxy (cth. 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation>Digunakan untuk berhubungan dengan peers melalui:</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>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>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Hanya tampilkan ikon tray setelah meminilisasi jendela</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Meminilisasi ke tray daripada taskbar</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>M&amp;eminilisasi saat tutup</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Tampilan</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>&amp;Bahasa Antarmuka Pengguna:</translation>
- </message>
- <message>
- <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation>Bahasa tampilan dapat diatur di sini. Pengaturan ini akan berpengaruh setelah memulai ulang %1.</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Unit untuk menunjukkan nilai:</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Pilihan standar unit yang ingin ditampilkan pada layar aplikasi dan saat mengirim koin.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Ingin menunjukkan cara pengaturan koin atau tidak.</translation>
- </message>
- <message>
- <source>&amp;Third party transaction URLs</source>
- <translation>&amp;URL transaksi pihak ketiga</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;YA</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Batal</translation>
- </message>
- <message>
- <source>default</source>
- <translation>standar</translation>
- </message>
- <message>
- <source>none</source>
- <translation>tidak satupun</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Memastikan reset pilihan</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Restart klien diperlukan untuk mengaktifkan perubahan.</translation>
- </message>
- <message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation>Klien akan dimatikan, apakah anda hendak melanjutkan?</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Konfigurasi pengaturan</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>File konfigurasi digunakan untuk menspesifikkan pilihan khusus pengguna yang akan menimpa pengaturan GUI. Sebagai tambahan, pengaturan command-line apapun akan menimpa file konfigurasi itu.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Terjadi sebuah kesalahan</translation>
- </message>
- <message>
- <source>The configuration file could not be opened.</source>
- <translation>Berkas konfigurasi tidak dapat dibuka.</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Perubahan ini akan memerlukan restart klien</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Alamat proxy yang diisi tidak valid.</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Formulir</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>Informasi terlampir mungkin sudah kedaluwarsa. Dompet Anda secara otomatis mensinkronisasi dengan jaringan Bitcoin ketika sebuah hubungan terbentuk, namun proses ini belum selesai.</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Hanya lihat:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Tersedia:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Jumlah yang Anda bisa keluarkan sekarang</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Ditunda</translation>
- </message>
- <message>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Jumlah keseluruhan transaksi yang belum dikonfirmasi, dan belum saatnya dihitung sebagai pengeluaran saldo yang telah dibelanjakan.</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Terlalu Muda:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>Saldo ditambang yang masih terlalu muda</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Saldo:</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Jumlah:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Jumlah saldo Anda sekarang</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>Saldomu di alamat hanya lihat</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Bisa digunakan:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Transaksi-transaksi terkini</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Transaksi yang belum terkonfirmasi ke alamat hanya lihat</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Saldo hasil mining di alamat hanya lihat yang belum bisa digunakan</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>Jumlah saldo di alamat hanya lihat</translation>
- </message>
-</context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Terjadi kesalahan pada permintaan pembayaran</translation>
- </message>
- <message>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>Tidak bisa memulai bitcoin: handler click-to-pay</translation>
- </message>
- <message>
- <source>URI handling</source>
- <translation>Pengelolaan URI</translation>
- </message>
- <message>
- <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
- <translation>'bitcoin://' bukanlah alamat URI yang valid. Silakan gunakan 'bitcoin:'.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL permintaan pembayaran tidak valid: %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 tidak bisa dimengerti! Hal ini bisa disebabkan karena alamat Bitcoin yang tidak sah atau parameter URI yang tidak tepat.</translation>
- </message>
- <message>
- <source>Payment request file handling</source>
- <translation>Pengelolaan file permintaan pembayaran</translation>
- </message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>File permintaan pembayaran tidak bisa dibaca! Hal ini bisa disebabkan karena file permintaan pembayaran tidak valid.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Permintaan pembayaran ditolak</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Jaringan permintaan pembayaran tidak sesuai dengan jaringan klien.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Permintaan pembayaran telah kadaluarsa.</translation>
- </message>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>Agen Pengguna</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Terkirim</translation>
- </message>
- </context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Nilai</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Masukkan alamat Bitcoin (contoh %1)</translation>
- </message>
- <message>
- <source>%1 h</source>
- <translation>%1 Jam</translation>
- </message>
- <message>
- <source>%1 m</source>
- <translation>%1 menit</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>T/S</translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 dan %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>unknown</source>
- <translation>tidak diketahui</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>T/S</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Versi Klien</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Informasi</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Jendela debug</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Umum</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Waktu nyala</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Jaringan</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Nama</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Jumlah hubungan</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Rantai blok</translation>
- </message>
- <message>
- <source>Current number of blocks</source>
- <translation>Jumlah blok terkini</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Terkirim</translation>
- </message>
- <message>
- <source>Version</source>
- <translation>Versi</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>Agen Pengguna
-
-</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Layanan</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Waktu blok terakhir</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Buka</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Konsol</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>Kemacetan &amp;Jaringan </translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Total</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Masuk:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Keluar:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Berkas catatan debug</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Bersihkan konsol</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;jam</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;hari</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;minggu</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;tahun</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>wallet default</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>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>&amp;Nilai:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Label:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Pesan:</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation>Label opsional untuk mengasosiasikan dengan alamat penerima baru.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Gunakan form ini untuk meminta pembayaran. Semua bidang adalah &lt;b&gt;opsional&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>Nilai permintaan opsional. Biarkan ini kosong atau nol bila tidak meminta nilai tertentu.</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Hapus informasi dari form.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Hapus</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>Riwayat pembayaran yang diminta Anda</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Minta pembayaran</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Menunjukkan permintaan yang dipilih (sama dengan tekan pilihan dua kali)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Menunjukkan</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Menghapus informasi terpilih dari daftar</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Menghapus</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Salin label</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Salin Jumlah</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>Kode QR</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Salin &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Salin &amp;Alamat</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Simpan Gambaran...</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>Wallet</source>
- <translation>Dompet</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(tidak ada label)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Kirim Koin</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Cara Pengaturan Koin</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Masukan...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>Pemilihan otomatis</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Saldo tidak mencukupi!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Kuantitas:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Nilai:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Biaya:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Dengan Biaya:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Uang Kembali:</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>Jiki ini dipilih, tetapi alamat pengembalian uang kosong atau salah, uang kembali akan dikirim ke alamat yang baru dibuat.</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Alamat uang kembali yang kustom</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Biaya Transaksi:</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Sembunyikan</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Disarankan</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Kirim ke beberapa penerima sekaligus</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>Tambahlah &amp;Penerima</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Hapus informasi dari form.</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Dust:</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Hapus &amp;Semua</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Saldo:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Konfirmasi aksi pengiriman</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>K&amp;irim</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Salin Kuantitas</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Salin Jumlah</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Salin biaya</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Salin Setelah Upah</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Salin bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Salin dust</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Salin Perubahan</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Biaya Transaksi</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Permintaan pembayaran telah kadaluarsa.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(tidak ada label)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>J&amp;umlah:</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>Kirim &amp;Ke:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Label:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Pilih alamat yang telah digunakan sebelumnya</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Ini adalah pembayaran normal</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+J</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Tempel alamat dari salinan</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+B</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Hapus masukan ini</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Pesan:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Masukkan label untuk alamat ini untuk dimasukan dalam daftar alamat yang pernah digunakan</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Kirim Ke:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Catatan Peringatan:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>Kamu tidak dapat mematikan komputer sebelum jendela ini tertutup sendiri.</translation>
- </message>
-</context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Tanda Tangan / Verifikasi sebuah Pesan</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Tandakan Pesan</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Pilih alamat yang telah digunakan sebelumnya</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Tempel alamat dari salinan</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+B</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Masukan pesan yang ingin ditandai disini</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Tanda Tangan</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Salin tanda tangan terpilih ke sistem klipboard</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Tandai pesan untuk menyetujui kamu pemiliki alamat Bitcoin ini</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Tandakan &amp;Pesan</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Hapus semua bidang penanda pesan</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Hapus &amp;Semua</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Verifikasi Pesan</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Verifikasi &amp;Pesan</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Hapus semua bidang verifikasi pesan</translation>
- </message>
- </context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KB/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Amount</source>
- <translation>Jumlah</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Jendela ini menampilkan deskripsi rinci dari transaksi tersebut</translation>
- </message>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(tidak ada label)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Copy address</source>
- <translation>Salin alamat</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Salin label</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Salin Jumlah</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Salain ID Transaksi</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Berkas yang berformat(*.csv)</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Alamat</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Mengekspor Gagal</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>Corrupted block database detected</source>
- <translation>Menemukan database blok yang rusak </translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Apakah Anda ingin coba membangun kembali database blok sekarang?</translation>
- </message>
- <message>
- <source>Error initializing block database</source>
- <translation>Kesalahan menginisialisasi database blok</translation>
- </message>
- <message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Kesalahan menginisialisasi dompet pada database%s!</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Gagal memuat database blok</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Menemukan masalah membukakan database blok</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Gagal: Hard disk hampir terisi!</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>mengimpor...</translation>
- </message>
- <message>
- <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>Tidak bisa cari blok pertama, atau blok pertama salah. Salah direktori untuk jaringan?</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>Deskripsi berkas tidak tersedia dengan cukup.</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Blok-blok sedang diverifikasi...</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informasi</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Tandatangani transaksi tergagal</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Nilai transaksi terlalu kecil</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Transaksi terlalu besar</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Peringatan</translation>
- </message>
- <message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Setiap transaksi dalam dompet sedang di-'Zap'...</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Jaringan tidak diketahui yang ditentukan dalam -onlynet: '%s'</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Saldo tidak mencukupi</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Memuat indeks blok...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Memuat dompet...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Tidak dapat menurunkan versi dompet</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Memindai ulang...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Memuat selesai</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Gagal</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_is.ts b/src/qt/locale/bitcoin_is.ts
index 2bc8bf222b..6eb5c10107 100644
--- a/src/qt/locale/bitcoin_is.ts
+++ b/src/qt/locale/bitcoin_is.ts
@@ -322,14 +322,6 @@
<translation>Breyta lykilsetningunni sem gildir um dulkóðun veskis</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Kembunargluggi</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Opna kembunar- og greiningarstjórnborð</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Yfirfara skilaboð...</translation>
</message>
@@ -390,10 +382,6 @@
<translation>Sýna færslugildi sem notuð hafa verið til að taka við mynt og merkingar þeirra</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Opna bitcoin: URI eða greiðslubeiðni</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Valkostir skipanalínu</translation>
</message>
@@ -843,9 +831,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts
index 3f4a3e23e8..2cd0941a8c 100644
--- a/src/qt/locale/bitcoin_it.ts
+++ b/src/qt/locale/bitcoin_it.ts
@@ -71,7 +71,7 @@
</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>
+ <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>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -173,7 +173,7 @@
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Cifrare veramente il portafoglio?</translation>
+ <translation>Sei sicuro di voler cifrare il portafoglio?</translation>
</message>
<message>
<source>Wallet encrypted</source>
@@ -197,11 +197,11 @@
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation>Il tuo portafoglio sta per essere criptato. </translation>
+ <translation>Il tuo portafoglio sta per essere criptato.</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation>Il tuo portafoglio è ora criptato. </translation>
+ <translation>Il tuo portafoglio è ora criptato.</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>
@@ -374,14 +374,6 @@
<translation>Cambia la passphrase utilizzata per la cifratura del portafoglio</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Finestra di &amp;debug</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Apri la console di debugging e diagnostica</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verifica messaggio...</translation>
</message>
@@ -442,10 +434,6 @@
<translation>Mostra la lista degli indirizzi di ricezione utilizzati</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Apri un bitcoin: URI o una richiesta di pagamento</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Opzioni della riga di &amp;comando</translation>
</message>
@@ -494,6 +482,14 @@
<translation>Aggiornato</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Finestra del nodo</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Apri il debug del nodo e la console diagnostica</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>Indirizzi di &amp;spedizione</translation>
</message>
@@ -502,6 +498,10 @@
<translation>Indirizzi di &amp;ricezione</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Apri un bitcoin: URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Apri il Portafoglio</translation>
</message>
@@ -519,7 +519,7 @@
</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>
+ <translation>Mostra il messaggio di aiuto di %1 per ottenere una lista di opzioni di comando per Bitcoin</translation>
</message>
<message>
<source>default wallet</source>
@@ -812,7 +812,7 @@
</message>
<message>
<source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
- <translation>Cripta il portafoglio. Il portafoglio sarà criptato con una passphrase a tua scelta. </translation>
+ <translation>Cripta il portafoglio. Il portafoglio sarà criptato con una passphrase a tua scelta.</translation>
</message>
<message>
<source>Encrypt Wallet</source>
@@ -828,7 +828,7 @@
</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>Crea un portafoglio vuoto. I portafogli vuoti non hanno inizialmente nessuna chiave privata o script. Chiavi private e indirizzi possono essere importati, o un HD seed può essere impostato, in seguito. </translation>
+ <translation>Crea un portafoglio vuoto. I portafogli vuoti non hanno inizialmente nessuna chiave privata o script. Chiavi private e indirizzi possono essere importati, o un HD seed può essere impostato, in seguito.</translation>
</message>
<message>
<source>Make Blank Wallet</source>
@@ -924,10 +924,6 @@
<translation>versione</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Informazioni %1</translation>
</message>
@@ -956,7 +952,7 @@
</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>Cambiare questa impostazione richiede di riscaricare l'intera blockchain. E' più veloce scaricare prima tutta la chain e poi fare prune. Disabilita alcune impostazioni avanzate. </translation>
+ <translation>Cambiare questa impostazione richiede di riscaricare l'intera blockchain. E' più veloce scaricare prima tutta la chain e poi fare prune. Disabilita alcune impostazioni avanzate.</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>
@@ -1066,6 +1062,14 @@
<translation>Nascondi</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 è attualmente in fase di sincronizzazione. Scaricherà le intestazioni e i blocchi dai peer e li convaliderà fino a raggiungere la punta della catena di blocchi.</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>Sconosciuto. Sincronizzando Headers (%1, %2%)...</translation>
</message>
@@ -1073,25 +1077,13 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Apri URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Apri richiesta di pagamento da URI o file</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Apri un bitcoin URI</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Seleziona il file di richiesta di pagamento</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Seleziona il file di richiesta di pagamento da aprire</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1136,7 +1128,7 @@
</message>
<message>
<source>Number of script &amp;verification threads</source>
- <translation>Numero di thread di &amp;verifica degli script </translation>
+ <translation>Numero di thread di &amp;verifica degli script</translation>
</message>
<message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
@@ -1482,16 +1474,8 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>'bitcoin://' non è un URI valido. Usa invece 'bitcoin:'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Stai usando un URL BIP70 che, in futuro, non sarà piú supportato.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL di recupero della Richiesta di pagamento non valido: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Non posso completare la richiesta di pagamento perché il supporto per BIP70 non è stato incluso in fase di compilazione.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>Impossibile elaborare la richiesta di pagamento perché BIP70 non è supportato.</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>
@@ -1513,66 +1497,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<source>Payment request file handling</source>
<translation>Gestione del file di richiesta del pagamento</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Impossibile leggere il file della richiesta di pagamento! Il file della richiesta di pagamento potrebbe non essere valido</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Richiesta di pagamento respinta</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>La rete della richiesta di pagamento non corrisponde alla rete del client.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Richiesta di pagamento scaduta.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>La richiesta di pagamento non è stata inizializzata.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Le richieste di pagamento non verificate verso script di pagamento personalizzati non sono supportate.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Richiesta di pagamento invalida</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>L'importo di pagamento di %1 richiesto è troppo basso (considerato come trascurabile).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Rimborso da %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>La richiesta di pagamento %1 è troppo grande (%2 bytes, consentiti %3 bytes)</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Errore di comunicazione con %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>La richiesta di pagamento non può essere processata!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation> Risposta errata da parte del server %1 </translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation> Errore di richiesta di rete</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Pagamento riconosciuto</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1716,11 +1640,11 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
</message>
<message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation> L'URI risultante è troppo lungo, prova a ridurre il testo nell'etichetta / messaggio.</translation>
+ <translation>L'URI risultante è troppo lungo, prova a ridurre il testo nell'etichetta / messaggio.</translation>
</message>
<message>
<source>Error encoding URI into QR Code.</source>
- <translation> Errore nella codifica dell'URI nel codice QR.</translation>
+ <translation>Errore nella codifica dell'URI nel codice QR.</translation>
</message>
<message>
<source>QR code support not available.</source>
@@ -1750,10 +1674,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>&amp;Informazioni</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Finestra di debug</translation>
- </message>
- <message>
<source>General</source>
<translation>Generale</translation>
</message>
@@ -1874,6 +1794,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>User Agent</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Finestra del nodo</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>
@@ -2085,8 +2009,16 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Un importo opzionale da associare alla richiesta. Lasciare vuoto o a zero per non richiedere un importo specifico.</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>Un'etichetta facoltativa da associare al nuovo indirizzo di ricezione (utilizzata da te per identificare una fattura). Viene inoltre allegata alla richiesta di pagamento.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Un messaggio facoltativo che è allegato alla richiesta di pagamento e può essere visualizzato dal mittente.</translation>
+ </message>
+ <message>
<source>&amp;Create new receiving address</source>
- <translation>Crea nuovo indirizzo ricevente. </translation>
+ <translation>Crea nuovo indirizzo ricevente.</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
@@ -2294,10 +2226,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Attenzione: Il calcolo delle commissioni non è attualmente disponibile.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>minimizza le impostazioni di commissione</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>
@@ -2342,6 +2270,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Trascurabile:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Nascondi le impostazioni delle commissioni di transazione.</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>Quando il volume delle transazioni è minore dello spazio nei blocchi, i minatori e in nodi di relay potrebbero imporre una commissione minima. Va benissimo pagare solo questa commissione minima, ma tieni presente che questo potrebbe risultare in una transazione che, se la richiesta di transazioni bitcoin dovesse superare la velocità con cui la rete riesce ad elaborarle, non viene mai confermata.</translation>
</message>
@@ -2410,6 +2342,14 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>%1 (%2 blocchi)</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>Crea una Transazione Bitcoin Parzialmente Firmata (PSBT) da utilizzare con ad es. un portafoglio %1 offline o un portafoglio hardware compatibile con PSBT.</translation>
+ </message>
+ <message>
<source> from wallet '%1'</source>
<translation>dal wallet '%1'</translation>
</message>
@@ -2422,8 +2362,16 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>%1 a %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Vuoi compilare questa transazione?</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
- <translation> Sei sicuro di voler inviare?</translation>
+ <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>
</message>
<message>
<source>or</source>
@@ -2458,12 +2406,32 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Conferma invio coins</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
- <translation> L'indirizzo del destinatario non è valido. Si prega di ricontrollare.</translation>
+ <translation>L'indirizzo del destinatario non è valido. Si prega di ricontrollare.</translation>
</message>
<message>
<source>The amount to pay must be larger than 0.</source>
- <translation> L'importo da pagare deve essere maggiore di 0.</translation>
+ <translation>L'importo da pagare deve essere maggiore di 0.</translation>
</message>
<message>
<source>The amount exceeds your balance.</source>
@@ -2471,23 +2439,19 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation> Il totale è superiore al tuo saldo attuale includendo la commissione di %1. </translation>
+ <translation>Il totale è superiore al tuo saldo attuale includendo la commissione di %1.</translation>
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
- <translation> Rilevato un indirizzo duplicato Ciascun indirizzo dovrebbe essere utilizzato una sola volta.</translation>
+ <translation>Rilevato un indirizzo duplicato Ciascun indirizzo dovrebbe essere utilizzato una sola volta.</translation>
</message>
<message>
<source>Transaction creation failed!</source>
<translation>Creazione della transazione fallita!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>La transazione è stata respinta per il seguente motivo: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation> Una commissione maggiore di %1 è considerata irragionevolmente elevata.</translation>
+ <translation>Una commissione maggiore di %1 è considerata irragionevolmente elevata.</translation>
</message>
<message>
<source>Payment request expired.</source>
@@ -2537,10 +2501,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Scegli un indirizzo usato precedentemente</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Questo è un normale pagamento.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>L'indirizzo Bitcoin a cui vuoi inviare il pagamento</translation>
</message>
@@ -2561,6 +2521,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Rimuovi questa voce</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>L'ammontare da inviare nell'unità selezionata</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>La commissione sarà sottratta dall'importo che si sta inviando. Il beneficiario riceverà un totale di bitcoin inferiore al valore digitato. Nel caso in cui siano stati selezionati più beneficiari la commissione sarà suddivisa in parti uguali.</translation>
</message>
@@ -2600,17 +2564,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Inserisci un'etichetta per questo indirizzo per aggiungerlo alla tua rubrica</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Si</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2698,6 +2651,14 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>L'indirizzo Bitcoin con cui è stato contrassegnato il messaggio</translation>
</message>
<message>
+ <source>The signed message to verify</source>
+ <translation>Il messaggio firmato da verificare</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>La firma data al momento della firma del messaggio</translation>
+ </message>
+ <message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
<translation>Verifica il messaggio per accertare che sia stato firmato con l'indirizzo specificato</translation>
</message>
@@ -2730,6 +2691,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Sblocco del portafoglio annullato.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Nessun errore</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>La chiave privata per l'indirizzo inserito non è disponibile.</translation>
</message>
@@ -2904,6 +2869,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Indice di output</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(Il certificato non è stato verificato)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Commerciante</translation>
</message>
@@ -3114,7 +3083,7 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
</message>
<message>
<source>Abandon transaction</source>
- <translation>Abbandona transazione </translation>
+ <translation>Abbandona transazione</translation>
</message>
<message>
<source>Increase transaction fee</source>
@@ -3261,6 +3230,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Vuoi aumentare la commissione?</translation>
</message>
<message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Vuoi compilare una transazione con un aumento delle commissioni?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Commissione attuale:</translation>
</message>
@@ -3277,6 +3250,14 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Conferma il salto di commissione</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>Non è possibile compilare la transazione. </translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT copiata</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Non è possibile firmare la transazione.</translation>
</message>
@@ -3343,10 +3324,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Non è possibile un rescan in modalità pruned. Sarà necessario utilizzare -reindex che farà scaricare nuovamente tutta la blockchain.</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>
@@ -3372,7 +3349,7 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
</message>
<message>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
- <translation>Non è possibile fornire connessioni specifiche e contemporaneamente usare addrman per trovare connessioni uscenti. </translation>
+ <translation>Non è possibile fornire connessioni specifiche e contemporaneamente usare addrman per trovare connessioni uscenti.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
@@ -3447,6 +3424,14 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Rilevato database blocchi corrotto</translation>
</message>
<message>
+ <source>Could not find asmap file %s</source>
+ <translation>Non è possibile trovare il file asmap %s</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>Non è possibile analizzare il file asmap %s</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Vuoi ricostruire ora il database dei blocchi?</translation>
</message>
@@ -3737,10 +3722,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Questo è il costo di transazione che potresti pagare quando le stime della tariffa non sono disponibili.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Questo prodotto include software sviluppato dal progetto OpenSSL per l'uso del Toolkit OpenSSL %s, software crittografico scritto da Eric Young e software UPnP scritto da Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
diff --git a/src/qt/locale/bitcoin_it_IT.ts b/src/qt/locale/bitcoin_it_IT.ts
deleted file mode 100644
index d97d888f23..0000000000
--- a/src/qt/locale/bitcoin_it_IT.ts
+++ /dev/null
@@ -1,1081 +0,0 @@
-<TS language="it_IT" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Click destro per modificare indirizzo o etichetta</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Crea un nuovo indirizzo </translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>Nuovo</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Copia l'indirizzo selezionato nella clipboard di sistema</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>Copia</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>Chiudi </translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Cancella l'indirizzo attualmente selezionato dalla lista.</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Inserire indirizzo o etichetta da cercare</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Esportare i dati nella scheda corrente in un file</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>Esporta</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>Cancella</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Scegli l'indirizzo a cui inviare denaro</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Scegli l'indirizzo dove accreditare i coins</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>Scegli</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Indirizzi mandanti</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Indirizzi riceventi</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>Questi sono i suoi indirizzi Bitcoin per ricevere i pagamenti. Controlla sempre l'importo e gli indirizzi prima di inviare i coins.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Questi sono i tuoi indirizzi Bitcoin per ricevere i pagamenti. Si raccomanda di usare un nuovo indirizzo per ogni transazione.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>copia indirizzo </translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>copia etichetta</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>Modifica</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Esporta lista indirizzi</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Comma separated file (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Esportazione Fallita</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Etichetta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Indirizzo</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nessuna etichetta)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Finestra Password</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Inserisci la password</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Nuova password</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Ripeti nuova password</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>mostra password</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Inserisci la nuova password per il portafoglio.&lt;br/&gt;Per favore usa una password di &lt;b&gt;dieci o più caratteri casuali&lt;/b&gt;, oppure &lt;b&gt;otto o più parole&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Cripta portafoglio</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Questa operazione necessita della password del tuo portafoglio per sbloccare il portafoglio.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Sblocca portafoglio</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Questa operazione necessita della password del tuo portafoglio per decriptare il portafoglio.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Decripta portafoglio</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Cambia password</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Inserisci la vecchia password e la nuova password per decriptare il portafoglio.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Conferma criptaggio portafoglio</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Attenzione: Se cripti il tuo portafoglio e perdi la password, &lt;b&gt;PERDERAI TUTTI I TUOI BITCOIN&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Sei sicuro di voler criptare il tuo portafoglio?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Portafoglio criptato</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 ora si chiuderà per concludere il processo di criptaggio. Ricorda che criptare il tuo portafoglio non può definitivamente proteggere i tuoi bitcoin da furti tramite malware che infetta il tuo computer.</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: Qualsiasi backup precedentemente effettuato del tuo portafoglio dovrebbe essere sostituito con il nuovo file criptato generato. Per questioni di sicurezza, backup precedenti del portafoglio non criptati diverranno inutili non appena inizi ad usare il nuovo portafoglio criptato.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Criptaggio del portafoglio fallito</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Criptaggio del portafoglio fallito per un errore interno. Il tuo portafoglio non è stato criptato.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>La password fornite non corrispondono.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Sblocco portafoglio fallito</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>La password inserita per decriptare il portafoglio è errata.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Decriptaggio portafoglio fallito</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>La password del portafoglio è stata cambiata correttamente.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Attenzione: Il tasto blocco delle maiuscole è attivo!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmask</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Bannato fino </translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Firma &amp;messaggio...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Sincronizzazione con la rete...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Panoramica</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Nodo</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Mostra panoramica generale del portafoglio</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>Transazioni</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Esplora cronologia transazioni</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>Esci</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Termina applicazione</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>Di più su %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Mostra informazioni su %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Di più su Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Mostra informazioni su Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>Opzioni</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Modifica opzioni di configurazione per %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>Cripta portafoglio</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>Backup portafoglio</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>Cambia Password...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>Indirizzi di invio...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Indirizzi di ricezione...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Apri &amp;URI...</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>Portafoglio</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>Portafoglio predefinito</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Clicca per disabilitare attività di rete.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Attività di rete disabilitata.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Clicca per riabilitare attività di rete.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Sincronizzazione Header (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Reindicizzazione dei blocchi sul disco...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Invia monete ad un indirizzo Bitcoin...</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Backup del portafoglio in un'altra posizione</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Cambia la password usata per criptare il portafoglio</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>Finestra di debug</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Apri console di debug e diagnosi</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>Verifica messaggio...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Portafoglio</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>Invia</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>Ricevi</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>Mostra / Nascondi</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Mostra o nascondi la finestra principale</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Cripta le chiavi private che appartengono al tuo portafoglio</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Firma messaggi con i tuoi indirizzi Bitcoin per provare che li possiedi</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Verifica messaggi per accertarti che siano firmati dagli indirizzi Bitcoin specificati</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>File</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>Impostazioni</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>Aiuto</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Barra degli strumenti</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Richiedi pagamenti (genera codici QR e bitcoin: URI)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Mostra la lista degli indirizzi di invio usati e le relative etichette</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Mostra la lista degli indirizzi di ricezione usati e le relative etichette</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Apri un bitcoin: URI o una richiesta di pagamento</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>Opzioni linea di comando</translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Indicizzazione blocchi su disco...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Elaborazione blocchi su disco...</translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 indietro</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Ultimo blocco ricevuto generato %1 fa.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Le transazioni dopo di questa non saranno più visibili</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Errore</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Attenzione</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informazione</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Aggiornato</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Mostra il %1 messaggio d'aiuto per ottenere una lista con le possibili opzioni per la riga di comando di Bitcoin</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Data: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Importo: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Tipo: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Etichetta: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Indirizzo: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Transazione inviata</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Transazione in arrivo</translation>
- </message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Si è verificato un errore fatale. Bitcoin non può continuare in maniera sicura e sarà chiuso.</translation>
- </message>
-</context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Selezione delle monete</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Quantità:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Importo:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Tassa:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Minimo:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Cambio:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(de)seleziona tutto</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Modalità albero</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Modalità lista</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Importo</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Ricevuto con etichetta</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Ricevuto con indirizzo</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Conferme</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confermato</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Copia indirizzo</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copia etichetta</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copia importo</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copia ID transazione</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Blocca non spese</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Sblocca non spese</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copia quantità</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copia tassa</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copia bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copia minimo</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copia cambio</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 bloccato)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>si</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>Questa etichetta diventa rossa se qualsiasi destinatario riceve un importo inferiore al limite minimo corrente.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nessuna etichetta)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation>(cambio)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Modifica Indirizzo</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Etichetta</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>L'etichetta associata con questa voce dell'elenco indirizzi</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>L'indirizzo associato con questa voce dell'elenco indirizzi. Può essere modificato per inviare indirizzi.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Indirizzo</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Nuovo indirizzo di invio</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Modifica l'indirizzo di ricezione</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Modifica l'indirizzo di invio</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>L'indirizzo inserito "%1" non è un indirizzo Bitcoin valido.</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Non posso sbloccare il portafoglio.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Generazione della nuova chiave fallita.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Una nuova cartella dei dati verrà creata.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>nome</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>La cartella esiste già. Aggiungi %1 se vuoi creare una nuova cartella qui.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Il percorso esiste già, e non è una cartella.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Non posso creare la cartella dei dati qui.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>versione</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>Circa %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Opzioni linea di comando</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Benvenuto</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation>Il wallet verra' inoltre memorizzato su questa cartella.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Errore</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation>Le transazioni recenti potrebbero non essere ancora visibili, e quindi il saldo del wallet potrebbe essere incorretto. Questa informazione verra' corretta non appena il tuo wallet ha finito di sincronizzarsi con la rete bitcoin, come specificato di seguito.</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>Tentare di spendere bitcoin che sono affetti da transazioni non ancora mostrate, non verra' accettato dal network.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Numero di blocchi rimanente</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Opzioni</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Opzioni di configurazione</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Errore</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Questa modifica richiede un riavvio del client</translation>
- </message>
- </context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Available:</source>
- <translation>Disponibile:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Saldo disponibile</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Transazioni recenti</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request rejected</source>
- <translation>Richiesta di pagamento rifiutata</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Rimborso da %1</translation>
- </message>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>Sent</source>
- <translation>Inviato</translation>
- </message>
- </context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Importo</translation>
- </message>
- </context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>Sent</source>
- <translation>Inviato</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>Portafoglio predefinito</translation>
- </message>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>Copy label</source>
- <translation>Copia etichetta</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copia importo</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>Indirizzo</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Importo</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etichetta</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Portafoglio</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etichetta</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nessuna etichetta)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Quantity:</source>
- <translation>Quantità:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Importo:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Tassa:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Cambio:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Minimo:</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copia quantità</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copia importo</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copia tassa</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copia bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copia minimo</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copia cambio</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nessuna etichetta)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- </context>
-<context>
- <name>SplashScreen</name>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Importo</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etichetta</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(nessuna etichetta)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Copy address</source>
- <translation>Copia indirizzo</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copia etichetta</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copia importo</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copia ID transazione</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Comma separated file (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confermato</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etichetta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Indirizzo</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Esportazione Fallita</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Information</source>
- <translation>Informazione</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Attenzione</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Errore</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts
index 5284b1842b..ea1bf17838 100644
--- a/src/qt/locale/bitcoin_ja.ts
+++ b/src/qt/locale/bitcoin_ja.ts
@@ -70,6 +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>これらは支払いを受け取るための、あなたの Bitcoin アドレスです。新しいアドレスを作成するには受取タブ内の「新しい受取用アドレスを作成」ボタンを使用します。</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>アドレスをコピー(&amp;C)</translation>
</message>
@@ -132,6 +136,10 @@
<translation>新しいパスフレーズをもう一度</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>パスフレーズを表示</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>ウォレットを暗号化</translation>
</message>
@@ -172,6 +180,31 @@
<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>新しいウォレットのパスフレーズを入力してください。
+パスフレーズは、ランダムな10文字以上の文字か、8語以上の単語を使用してください。</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>ウォレットを暗号化しても、コンピュータに感染したマルウェアなどによる Bitcoin の盗難を完全に防ぐことはできないことにご注意ください。</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>暗号化するウォレット</translation>
+ </message>
+ <message>
+ <source>Your wallet is about 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>
@@ -294,6 +327,14 @@
<translation>URI を開く(&amp;U)...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>ウォレットを作成...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>新しいウォレットを作成</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>ウォレット:</translation>
</message>
@@ -334,14 +375,6 @@
<translation>ウォレット暗号化用パスフレーズを変更する</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>デバッグ ウインドウ(&amp;D)</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>デバッグ・診断コンソールを開く</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>メッセージの検証(&amp;V)...</translation>
</message>
@@ -402,10 +435,6 @@
<translation>受け取ったことがあるアドレスとラベルの一覧を表示する</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>bitcoin: URIや支払いリクエストを開く</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>コマンドラインオプション(&amp;C)</translation>
</message>
@@ -454,6 +483,10 @@
<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>
</message>
@@ -462,6 +495,10 @@
<translation>受取用アドレス一覧(&amp;R)...</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>bitcoin: URIを開く</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>ウォレットを開く</translation>
</message>
@@ -522,6 +559,10 @@
<translation>エラー: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>警告: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>日付: %1
@@ -743,10 +784,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <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>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>ウォレットを作成 - 警告</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>ウォレットを作成する</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>ウォレット名</translation>
+ </message>
+ <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>Create</source>
+ <translation>作成</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -832,10 +921,6 @@
<translation>バージョン</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1 ビット)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>%1 について</translation>
</message>
@@ -863,6 +948,10 @@
<translation>OKをクリックすると、%1 は %4 がリリースされた%3年最初の取引からの完全な %4 ブロックチェーン(%2GB)のダウンロードおよび処理を開始します。</translation>
</message>
<message>
+ <source>Reverting this setting requires re-downloading the entire blockchain. It is faster to download the full chain first and prune it later. Disables some advanced features.</source>
+ <translation>この設定を元に戻すには、ブロックチェーン全体を再ダウンロードする必要があります。先にチェーン全体をダウンロードしてから、剪定する方が高速です。一部の高度な機能を無効にします。</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>
@@ -883,6 +972,10 @@
<translation>Bitcoin</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 GBのデータをこのディレクトリに保存する必要があります。またこのデータは時間とともに増加していきます。</translation>
</message>
@@ -914,7 +1007,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>
@@ -962,6 +1059,10 @@
<translation>隠す</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>
@@ -969,28 +1070,24 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>URIを開く</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>URIまたはファイルから支払いリクエストを開く</translation>
+ <source>Open bitcoin URI</source>
+ <translation>bitcoin URIを開く</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>支払いリクエストファイルを選択</translation>
+ <source>Open wallet failed</source>
+ <translation>ウォレットを開くことに失敗しました</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>支払いリクエストファイルを選択</translation>
+ <source>Open wallet warning</source>
+ <translation>ウォレットを開く - 警告</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>デフォルトウォレット</translation>
@@ -1369,16 +1466,16 @@
<translation>'bitcoin://' は正しいURIではありません。 'bitcoin:'を使用してください。</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>将来サポートされなくなる予定のBIP70形式のURLをお使いです。</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>BIP70がサポートされていないため、支払いリクエストを処理することができません。</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>支払いリクエストの取得先URLが無効です: %1</translation>
+ <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>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>BIP70のサポートが組み込まれていないため、支払いリクエストを処理することができません。</translation>
+ <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>
@@ -1392,66 +1489,6 @@
<source>Payment request file handling</source>
<translation>支払いリクエストファイルの処理</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>支払いリクエストファイルを読み込めませんでした! 無効な支払いリクエストファイルである可能性があります。</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>支払いリクエストの拒否</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>支払いリクエストのネットワークが現在のクライアントのネットワークと一致しません。</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>支払いリクエストが期限切れです。</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>支払いリクエストが初期化されていません。</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>カスタム支払いスクリプトに対する、未検証支払いリクエストはサポートされていません。</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>無効な支払いリクエストです。</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>リクエストされた支払い額 %1 は小さすぎます(ダストとみなされてしまいます)。</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>%1 からのお釣り</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>支払いリクエスト %1 は大きすぎます(サイズ: %2バイト / 最大処理可能サイズ: %3バイト)。</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>%1 との通信時にエラーが発生しました: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>支払いリクエストを解析できませんでした!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>%1 サーバーの応答が無効でした</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>ネットワーク リクエストエラー</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>支払いは承認されました</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1602,6 +1639,10 @@
<translation>URIをQRコードへ変換している際にエラーが発生しました。</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>QRコードは利用できません。</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>QRコードの保存</translation>
</message>
@@ -1625,10 +1666,6 @@
<translation>情報(&amp;I)</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>デバッグ ウインドウ</translation>
- </message>
- <message>
<source>General</source>
<translation>全般</translation>
</message>
@@ -1960,6 +1997,18 @@
<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>新しい受取用アドレスを作成</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>全ての入力欄をクリア</translation>
</message>
@@ -2158,17 +2207,13 @@
</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> 代替料金を利用することで、承認されるまでに数時間または数日 (ないし一生承認されない) トランザクションを送信してしまう可能性があります。手動にて手数料を選択するか、完全なブロックチェーンの検証が終わるまで待つことを検討しましょう</translation>
+ <translation>代替料金を利用することで、承認されるまでに数時間または数日 (ないし一生承認されない) トランザクションを送信してしまう可能性があります。手動にて手数料を選択するか、完全なブロックチェーンの検証が終わるまで待つことを検討しましょう</translation>
</message>
<message>
<source>Warning: Fee estimation is currently not possible.</source>
<translation>警告: 手数料推定機能は現在利用できません。</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>手数料設定を折りたたむ</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>
@@ -2281,6 +2326,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%1 (%2 ブロック)</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>オフライン%1ウォレットまたはPSBTに対応したハードウェアウォレットと合わせて使用するためのPSBT(部分的に署名されたトランザクション)を作成します。</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation>ウォレット '%1' から</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 から '%2'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 送金先: %2</translation>
</message>
@@ -2313,10 +2370,22 @@ 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>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBTがコピーされました</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>送金先アドレスが不正です。再確認してください。</translation>
</message>
@@ -2341,10 +2410,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>取引の作成に失敗しました!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>取引は次の理由により拒否されました: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>%1 よりも高い手数料は、異常に高すぎです。</translation>
</message>
@@ -2396,10 +2461,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>これまでに送金したことがあるアドレスから選択</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>これは通常の支払いです。</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>支払い先 Bitcoin アドレス</translation>
</message>
@@ -2459,17 +2520,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Memo:</source>
<translation>メモ:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>アドレス帳に追加するには、このアドレスのラベルを入力します</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>はい</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2557,6 +2607,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>メッセージの署名に使われた Bitcoin アドレス</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>
</message>
@@ -2589,6 +2647,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>
@@ -2763,6 +2825,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>
@@ -3086,6 +3152,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>ウォレットを閉じる</translation>
</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>
+ </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>
@@ -3132,6 +3202,10 @@ 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>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>トランザクションを署名できませんでした。</translation>
</message>
@@ -3198,10 +3272,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>剪定: 最後のウォレット同期ポイントが、剪定されたデータを越えています。-reindex を実行する必要があります (剪定されたノードの場合、ブロックチェーン全体を再ダウンロードします)</translation>
</message>
<message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>剪定モードでは再スキャンを行うことはできません。-reindex オプションを指定し、ブロックチェーン全体を再ダウンロードする必要があります。</translation>
- </message>
- <message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>エラー: 致命的な内部エラーが発生しました。詳細は debug.log を参照してください</translation>
</message>
@@ -3302,6 +3372,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
<translation>ブロック データベースを今すぐ再構築しますか?</translation>
</message>
@@ -3358,6 +3436,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>初期化時の健全性検査に失敗しました。%s を終了します。</translation>
</message>
<message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>無効なP2Pアクセス権: '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
<translation>-%s=&lt;amount&gt; オプションに対する不正な amount: '%s'</translation>
</message>
@@ -3390,6 +3472,10 @@ 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>
@@ -3498,6 +3584,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>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>剪定モードは -blockfilterindex オプションと互換性がありません。</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>システム上の制約から、-maxconnections を %d から %d に削減しました。</translation>
</message>
@@ -3556,6 +3646,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>イニシャル鍵を生成できません</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>不明な -blockfilterindex の値 %s。</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>ウォレットの確認中...</translation>
</message>
@@ -3576,10 +3670,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>これは、手数料推定機能が利用できない場合に支払う取引手数料です。</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>この製品は、OpenSSLツールキット %s で使用するためにOpenSSLプロジェクトにより開発されたソフトウェアと、Eric Young氏により開発された暗号ソフトウェア、Thomas Bernard氏により開発されたUPnPソフトウェアを使用しています。</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation>ネットワークバージョン文字列の長さ(%i)が、最大の長さ(%i) を超えています。UAコメントの数や長さを削減してください。</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts
index 25bf390524..5d230d28c4 100644
--- a/src/qt/locale/bitcoin_ka.ts
+++ b/src/qt/locale/bitcoin_ka.ts
@@ -192,10 +192,22 @@
<translation>საფულის გახსნა წარუმატებლად შესრულდა</translation>
</message>
<message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>საფულის განშიფრვის ფრაზა-პაროლი არაწორია</translation>
+ </message>
+ <message>
<source>Wallet decryption failed</source>
<translation>საფულის გაშიფვრა ვერ შესრულდა</translation>
</message>
- </context>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>საფულის ფრაზა-პაროლი შეცვლილია.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>ყურადღება: ჩართულია Caps Lock რეჟიმი!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
<message>
@@ -306,14 +318,6 @@
<translation>საფულის დაშიფრვის ფრაზა-პაროლის შეცვლა</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>და&amp;ხვეწის ფანჯარა</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>დახვეწისა და გიაგნოსტიკის კონსოლის გაშვება</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;ვერიფიკაცია</translation>
</message>
@@ -374,10 +378,6 @@
<translation>გამოყენებული მიღების მისამართებისა და ნიშნულების სიის ჩვენება</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>bitcoin: URI-ის ან გადახდის მოთხოვნის გახსნა</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>საკომანდო სტრიქონის ოპ&amp;ციები</translation>
</message>
@@ -481,7 +481,11 @@
<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>
- </context>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>ფატალური შეცდომა. Bitcoin ვერ უზრუნველყოფს უსაფრთხო გაგრძელებას, ამიტომ იხურება.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -553,10 +557,42 @@
<translation>რაოდენობის კოპირება</translation>
</message>
<message>
+ <source>Copy transaction ID</source>
+ <translation>ტრანსაქციის ID-ს კოპირება</translation>
+ </message>
+ <message>
<source>Lock unspent</source>
<translation>დაუხარჯავის ჩაკეტვა</translation>
</message>
<message>
+ <source>Unlock unspent</source>
+ <translation>დაუხარჯავის განბლოკვა</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>რაოდენობის კოპირება</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>საკომისიოს კოპირება</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>დამატებითი საკომისიოს კოპირება</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>ბაიტების კოპირება</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>ხურდის კოპირება</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 დაბლოკილია)</translation>
+ </message>
+ <message>
<source>yes</source>
<translation>დიახ</translation>
</message>
@@ -569,6 +605,10 @@
<translation>(ნიშნული არ არის)</translation>
</message>
<message>
+ <source>change from %1 (%2)</source>
+ <translation>ხურდა %1-დან (%2)</translation>
+ </message>
+ <message>
<source>(change)</source>
<translation>(ხურდა)</translation>
</message>
@@ -601,7 +641,31 @@
<source>&amp;Address</source>
<translation>მის&amp;ამართი</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>ახალი გაგზავნის მისამართი</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>მიღების მისამართის შეცვლა</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>გაგზავნის მისამართის შეცვლა</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>შეყვანილი მისამართი "%1" არ არის ვალიდური Bitcoin-მისამართი.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>საფულის განბლოკვა ვერ მოხერხდა.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>ახალი გასაღების გენერირება ვერ მოხერხდა</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
@@ -632,10 +696,6 @@
<translation>ვერსია</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-ბიტი)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>%1-ის შესახებ</translation>
</message>
@@ -701,22 +761,10 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>URI-ის გახსნა</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>გადახდის მოთხოვნის შექმნა URI-იდან ან ფაილიდან</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>გადახდის მოთხოვნის ფაილის არჩევა</translation>
- </message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
<message>
@@ -920,7 +968,27 @@
</context>
<context>
<name>PaymentServer</name>
- </context>
+ <message>
+ <source>Payment request error</source>
+ <translation>გადახდის მოთხოვნის შეცდომა</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>ვერ გაიშვა bitcoin: click-to-pay</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>URI-ების დამუშავება</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>გადახდის მისამართი არასწორია: %1</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>გადახდის მოთხოვნის ფაილის დამუშავება</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
</context>
@@ -978,6 +1046,10 @@
<translation>გამო&amp;სახულების შენახვა...</translation>
</message>
<message>
+ <source>&amp;Copy Image</source>
+ <translation>გამოსახულების &amp;კოპირება</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI ძალიან გრძელი გამოდის, შეამოკლეთ ნიშნულის/მესიჯის ტექსტი.</translation>
</message>
@@ -985,7 +1057,15 @@
<source>Error encoding URI into QR Code.</source>
<translation>შედომა URI-ის QR-კოდში გადაყვანისას.</translation>
</message>
- </context>
+ <message>
+ <source>Save QR Code</source>
+ <translation>QR-კოდის შენახვა</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>PNG სურათი (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -1001,10 +1081,6 @@
<translation>&amp;ინფორმაცია</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>დახვეწის ფანჯარა</translation>
- </message>
- <message>
<source>General</source>
<translation>საერთო</translation>
</message>
@@ -1132,6 +1208,10 @@
<translation>ლეიბლის კოპირება</translation>
</message>
<message>
+ <source>Copy message</source>
+ <translation>მესიჯის კოპირება</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>რაოდენობის კოპირება</translation>
</message>
@@ -1155,6 +1235,18 @@
<translation>გამო&amp;სახულების შენახვა...</translation>
</message>
<message>
+ <source>Request payment to %1</source>
+ <translation>%1-ის გადაზდის მოთხოვნა</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>ინფორმაცია გადახდის შესახებ</translation>
+ </message>
+ <message>
+ <source>URI</source>
+ <translation>URI</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>მისამართი</translation>
</message>
@@ -1167,6 +1259,10 @@
<translation>ნიშნული</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>მესიჯი</translation>
+ </message>
+ <message>
<source>Wallet</source>
<translation>საფულე</translation>
</message>
@@ -1182,9 +1278,17 @@
<translation>ნიშნული</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>მესიჯი</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(ნიშნული არ არის)</translation>
</message>
+ <message>
+ <source>(no message)</source>
+ <translation>(მესიჯები არ არის)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -1281,14 +1385,74 @@
<translation>გაგ&amp;ზავნა</translation>
</message>
<message>
+ <source>Copy quantity</source>
+ <translation>რაოდენობის კოპირება</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>რაოდენობის კოპირება</translation>
</message>
<message>
+ <source>Copy fee</source>
+ <translation>საკომისიოს კოპირება</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>დამატებითი საკომისიოს კოპირება</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>ბაიტების კოპირება</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>ხურდის კოპირება</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1-დან %2-ში</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>დარწმუნებული ხართ, რომ გინდათ გაგზავნა?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ან</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>ტრანსაქციის საფასური - საკომისიო</translation>
</message>
<message>
+ <source>Confirm send coins</source>
+ <translation>მონეტების გაგზავნის დადასტურება</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>გადახდის მოცულობა 0-ზე მეტი უნდა იყოს</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>თანხა აღემატება თქვენს ბალანსს</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>საკომისიო %1-ის დამატების შემდეგ თანხა აჭარბებს თქვენს ბალანსს</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>შეცდომა ტრანსაქციის შექმნისას!</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>ყურადღება: არასწორია Bitcoin-მისამართი</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>ყურადღება: უცნობია ხურდის მისამართი</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(ნიშნული არ არის)</translation>
</message>
@@ -1312,10 +1476,6 @@
<translation>აირჩიეთ ადრე გამოყენებული მისამართი</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>ეს არის ჩვეულებრივი გადახდა.</translation>
- </message>
- <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -1351,10 +1511,7 @@
<source>Memo:</source>
<translation>შენიშვნა:</translation>
</message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
+</context>
<context>
<name>ShutdownWindow</name>
<message>
@@ -1432,7 +1589,59 @@
<source>Reset all verify message fields</source>
<translation>ვერიფიკაციის ყველა ველის წაშლა</translation>
</message>
- </context>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>ხელმოწერის გენერირებისათვის დააჭირეთ "მესიჯის ხელმოწერა"-ს</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>შეყვანილი მისამართი არასწორია.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>შეამოწმეთ მისამართი და სცადეთ ხელახლა.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>შეყვანილი მისამართი არ არის კავშირში გასაღებთან.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>საფულის განბლოკვა შეწყვეტილია.</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>ამ მისამართისათვის პირადი გასაღები მიუწვდომელია.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>ვერ მოხერხდა მესიჯის ხელმოწერა.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>მესიჯი ხელმოწერილია.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>ხელმოწერის დეკოდირება ვერ ხერხდება.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>შეამოწმეთ ხელმოწერა და სცადეთ ხელახლა.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>ხელმოწერა არ შეესაბამება მესიჯის დაიჯესტს.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>მესიჯის ვერიფიკაცია ვერ მოხერხდა.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>მესიჯი ვერიფიცირებულია.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
<message>
@@ -1443,22 +1652,118 @@
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>ღია იქნება სანამ %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/დაუდასტურებელია</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 დადასტურებულია</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>სტატუსი</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>თარიღი</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>წყარო</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>გენერირებულია</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>გამგზავნი</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>უცნობია</translation>
</message>
<message>
+ <source>To</source>
+ <translation>მიმღები</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>საკუთარი მისამართი</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>ნიშნული</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>კრედიტი</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>უარყოფილია</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>დებიტი</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>ტრანსაქციის საფასური - საკომისიო</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>სუფთა თანხა</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>მესიჯი</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>შენიშვნა</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ტრანსაქციის ID</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>გამყიდველი</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>გენერირებული მონეტები გასაგზავნად მომწიფდება %1 ბლოკის შემდეგ. ეს ბლოკი გენერირების შემდეგ გავრცელებულ იქნა ქსელში ბლოკთა ჯაჭვზე დასამატებლად. თუ ის ვერ ჩაჯდა ჯაჭვში, მიეცემა სტატუსი "უარყოფილია" და ამ მონეტებს ვერ გამოიყენებთ. ასეთი რამ შეიძლება მოხდეს, თუ რომელიმე კვანძმა რამდენიმე წამით დაგასწროთ ბლოკის გენერირება.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>დახვეწის ინფორმაცია</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>ტრანსაქცია</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>ხარჯები</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>თანხა</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>ჭეშმარიტი</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>მცდარი</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
@@ -1473,17 +1778,141 @@
<translation>თარიღი</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>ტიპი</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>ნიშნული</translation>
</message>
<message>
+ <source>Open until %1</source>
+ <translation>ღია იქნება სანამ %1</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>დაუდასტურებელია</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>დადასტურებულია (%1, რეკომენდებულია %2)</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>დადასტურებულია (%1დასტური)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation>კონფლიქტშია</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>არ არის მომწიფებული (%1 დასტური, საჭიროა სულ %2)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>გენერირებულია, მაგრამ უარყოფილია</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>შემოსულია</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>გამომგზავნი</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>გაგზავნილია</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>გადახდილია საკუთარი თავისათვის</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>მოპოვებულია</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(მიუწვდ.)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(ნიშნული არ არის)</translation>
</message>
- </context>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>ტრანსაქციის სტატუსი. ველზე კურსორის შეყვანისას გამოჩნდება დასტურების რაოდენობა.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>ტრანსაქციის მიღების თარიღი და დრო.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>ტრანსაქციის ტიპი.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>ბალანსიდან მოხსნილი ან დამატებული თანხა.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>ყველა</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>დღეს</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>ამ კვირის</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>ამ თვის</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>ბოლო თვის</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>ამ წლის</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>შუალედი...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>შემოსულია</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>გაგზავნილია</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>საკუთარი თავისათვის</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>მოპოვებულია</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>სხვა</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>მინ. თანხა</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>მისამართის კოპირება</translation>
</message>
@@ -1496,6 +1925,22 @@
<translation>რაოდენობის კოპირება</translation>
</message>
<message>
+ <source>Copy transaction ID</source>
+ <translation>ტრანსაქციის ID-ს კოპირება</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>ნიშნულის რედაქტირება</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>ტრანსაქციის დეტალების ჩვენება</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>ტრანსაქციების ისტორიის ექსპორტი</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>CSV ფორმატის ფაილი (*.csv)</translation>
</message>
@@ -1508,6 +1953,10 @@
<translation>თარიღი</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>ტიპი</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>ნიშნული</translation>
</message>
@@ -1516,10 +1965,34 @@
<translation>მისამართი</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>ექპორტი ვერ განხორციელდა</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>შეცდომა %1-ში ტრანსაქციების შენახვის მცდელობისას.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>ეხპორტი განხორციელებულია</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>ტრანსაქციების ისტორია შენახულია %1-ში.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>შუალედი:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>-</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
@@ -1528,7 +2001,11 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>არ არის ჩატვირთული საფულე.</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
@@ -1550,10 +2027,46 @@
<source>Export the data in the current tab to a file</source>
<translation>ამ ბარათიდან მონაცემების ექსპორტი ფაილში</translation>
</message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>საფულის არქივირება</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>საფულის მონაცემები (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>არქივირება ვერ მოხერხდა</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>შეცდომა %1-ში საფულის მონაცემების შენახვის მცდელობისას.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>არქივირება შესრულებულია</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>საფულის მონაცემები შენახულია %1-ში.</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<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>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>ყურადღება: ქსელში შეუთანხმებლობაა. შესაძლოა ცალკეულ მომპოვებლებს პრობლემები ექმნებათ!</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>ყურადღება: ჩვენ არ ვეთანხმებით ყველა პირს. შესაძლოა თქვენ ან სხვა კვანძებს განახლება გჭირდებათ.</translation>
+ </message>
+ <message>
<source>Corrupted block database detected</source>
<translation>შენიშნულია ბლოკთა ბაზის დაზიანება</translation>
</message>
diff --git a/src/qt/locale/bitcoin_kk.ts b/src/qt/locale/bitcoin_kk.ts
index 5b13dd7b97..9ca9b48149 100644
--- a/src/qt/locale/bitcoin_kk.ts
+++ b/src/qt/locale/bitcoin_kk.ts
@@ -277,9 +277,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_km.ts b/src/qt/locale/bitcoin_km.ts
index 39156c7598..e00ea3145d 100644
--- a/src/qt/locale/bitcoin_km.ts
+++ b/src/qt/locale/bitcoin_km.ts
@@ -7,7 +7,7 @@
</message>
<message>
<source>Create a new address</source>
- <translation> បង្កើតអាស្រយដ្ឋានថ្មីមួយ</translation>
+ <translation>បង្កើតអាស្រយដ្ឋានថ្មីមួយ</translation>
</message>
<message>
<source>&amp;New</source>
@@ -118,7 +118,7 @@
</message>
<message>
<source>Decrypt wallet</source>
- <translation>កាបូប​​ ឌីក្រីព </translation>
+ <translation>កាបូប​​ ឌីក្រីព</translation>
</message>
<message>
<source>Change passphrase</source>
@@ -246,9 +246,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_ko.ts b/src/qt/locale/bitcoin_ko.ts
index 34697d4c0f..7cc6797c21 100644
--- a/src/qt/locale/bitcoin_ko.ts
+++ b/src/qt/locale/bitcoin_ko.ts
@@ -70,6 +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>지불 수신용 비트코인주소. 신규 주소를 만들려면 'Create new receiving address' 버튼을 사용하세요.</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>주소 복사(&amp;C)</translation>
</message>
@@ -132,6 +136,10 @@
<translation>새로운 암호 재입력</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>암호 보기</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>지갑 암호화</translation>
</message>
@@ -172,6 +180,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>새로운 지갑 비밀번호를 입력하세요. 암호는 10개 이상의 문자 또는 8개 이상의 단어로 입력하세요.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</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>
@@ -334,14 +350,6 @@
<translation>지갑 암호화에 사용되는 암호를 변경합니다</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>디버그 창(&amp;D)</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>디버깅 및 진단 콘솔을 엽니다</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>메시지 검증(&amp;V)...</translation>
</message>
@@ -402,10 +410,6 @@
<translation>한번 이상 사용된 받는 주소와 라벨의 목록을 보여줍니다</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>bitcoin: URI 또는 지불요청 열기</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>명령줄 옵션(&amp;C)</translation>
</message>
@@ -682,7 +686,7 @@
</message>
<message>
<source>Unlock unspent</source>
- <translation>사용되지 않은 주소를 잠금 해제합니다. </translation>
+ <translation>사용되지 않은 주소를 잠금 해제합니다.</translation>
</message>
<message>
<source>Copy quantity</source>
@@ -759,7 +763,7 @@
</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>
@@ -814,7 +818,7 @@
</message>
<message>
<source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>폴더가 이미 존재합니다. 새로운 폴더 생성을 원한다면 %1 명령어를 추가하세요. </translation>
+ <translation>폴더가 이미 존재합니다. 새로운 폴더 생성을 원한다면 %1 명령어를 추가하세요.</translation>
</message>
<message>
<source>Path already exists, and is not a directory.</source>
@@ -832,10 +836,6 @@
<translation>버전</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-비트)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>%1 정보</translation>
</message>
@@ -856,7 +856,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>프로그램이 처음으로 실행되고 있습니다. %1가 어디에 데이터를 저장할지 선택할 수 있습니다. </translation>
+ <translation>프로그램이 처음으로 실행되고 있습니다. %1가 어디에 데이터를 저장할지 선택할 수 있습니다.</translation>
</message>
<message>
<source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
@@ -969,25 +969,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>URI 열기</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>지불 요청 URI 또는 파일 열기</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>지불 요청 파일을 선택하세요</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>지불 요청 파일을 열기 위해서 선택하세요</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1080,7 +1064,7 @@
</message>
<message>
<source>Prune &amp;block storage to</source>
- <translation>블록 데이터를 지정된 크기로 축소합니다: </translation>
+ <translation>블록 데이터를 지정된 크기로 축소합니다:</translation>
</message>
<message>
<source>GB</source>
@@ -1268,7 +1252,7 @@
</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>
@@ -1369,18 +1353,6 @@
<translation>'bitcoin://"은 잘못된 URI입니다. 'bitcoin:'을 사용하십시오.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>지금 사용하고 있는 BIP70 URL은 나중에 지원되지 않을 수 있습니다.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>지불 요청의 URL이 올바르지 않습니다: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>BIP70 기능이 포함되지 않아서 지불 요청을 처리할 수 없습니다.</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>잘못된 지불 주소 %1</translation>
</message>
@@ -1392,66 +1364,6 @@
<source>Payment request file handling</source>
<translation>지불 요청 파일 처리중</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>지불 요청 파일을 읽을 수 없습니다. 이것은 잘못된 지불 요청 파일에 의해 발생하는 오류일 수 있습니다.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>지불 요청이 거부됨</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>지불 요청 네트워크가 클라이언트 네트워크와 일치하지 않습니다.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>지불 요청이 만료되었습니다.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>지불 요청이 초기화 되지 않았습니다.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>임의로 변경한 결제 스크립트 기반의 지불 요청 양식은 검증되기 전까지는 지원되지 않습니다.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>잘못된 지불 요청입니다.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>요청한 금액 %1의 양이 너무 적습니다. (더스트로 간주)</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>%1 으로부터의 환불</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>지불 요청 %1은 너무 큽니다 (%2 바이트, %3 바이트까지 허용됩니다).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>%1과의 통신 오류: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>지불요청을 파싱할 수 없습니다.</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>서버 %1로 부터 잘못된 반응</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>네트워크 요청 오류</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>지불이 승인됨</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1625,10 +1537,6 @@
<translation>정보(&amp;I)</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>디버그 창</translation>
- </message>
- <message>
<source>General</source>
<translation>일반</translation>
</message>
@@ -1957,7 +1865,7 @@
</message>
<message>
<source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation>요청할 금액 입력칸으로 선택 사항입니다. 빈 칸으로 두거나 특정 금액이 필요하지 않는 경우 0을 입력하세요. </translation>
+ <translation>요청할 금액 입력칸으로 선택 사항입니다. 빈 칸으로 두거나 특정 금액이 필요하지 않는 경우 0을 입력하세요.</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
@@ -2165,10 +2073,6 @@
<translation>경고: 지금은 수수료 예측이 불가능합니다.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>수수료 설정 접기</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>
@@ -2341,10 +2245,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>거래 생성에 실패했습니다!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>거래가 다음과 같은 이유로 거부되었습니다: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>%1 보다 큰 수수료는 지나치게 높은 수수료 입니다.</translation>
</message>
@@ -2396,10 +2296,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>이전에 사용한 주소를 선택하기</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>이것은 정상적인 지불입니다.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>이 비트코인 주소로 송금됩니다</translation>
</message>
@@ -2459,17 +2355,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Memo:</source>
<translation>메모:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>주소록에 추가하려면 라벨을 입력하세요</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>예</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2768,7 +2653,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>신규 채굴된 코인이 사용되기 위해서는 %1 개의 블록이 경과되어야 합니다. 블록을 생성할 때 블록체인에 추가되도록 네트워크에 전파되는 과정을 거치는데, 블록체인에 포함되지 못하고 실패한다면 해당 블록의 상태는 '미승인'으로 표현되고 비트코인 또한 사용될 수 없습니다. 이 현상은 다른 노드가 비슷한 시간대에 동시에 블록을 생성할 때 종종 발생할 수 있습니다. </translation>
+ <translation>신규 채굴된 코인이 사용되기 위해서는 %1 개의 블록이 경과되어야 합니다. 블록을 생성할 때 블록체인에 추가되도록 네트워크에 전파되는 과정을 거치는데, 블록체인에 포함되지 못하고 실패한다면 해당 블록의 상태는 '미승인'으로 표현되고 비트코인 또한 사용될 수 없습니다. 이 현상은 다른 노드가 비슷한 시간대에 동시에 블록을 생성할 때 종종 발생할 수 있습니다.</translation>
</message>
<message>
<source>Debug information</source>
@@ -3168,7 +3053,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>There was an error trying to save the wallet data to %1.</source>
- <translation>지갑 데이터를 %1 폴더에 저장하는 동안 오류가 발생했습니다. </translation>
+ <translation>지갑 데이터를 %1 폴더에 저장하는 동안 오류가 발생했습니다.</translation>
</message>
<message>
<source>Backup Successful</source>
@@ -3198,10 +3083,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>블록 축소: 마지막 지갑 동기화 지점이 축소된 데이터보다 과거의 것 입니다. -reindex가 필요합니다 (축소된 노드의 경우 모든 블록체인을 재다운로드합니다)</translation>
</message>
<message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>블록 축소 모드에서는 재검색이 불가능 합니다. -reindex 명령을 사용해서 모든 블록체인을 다시 다운로드 해야 합니다.</translation>
- </message>
- <message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>오류: 치명적인 내부 오류가 발생했습니다, 자세한 내용은 debug.log 를 확인해주세요.</translation>
</message>
@@ -3263,7 +3144,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>경고 : 모든 네트워크가 동의해야 하나, 일부 채굴자들에게 문제가 있는 것으로 보입니다. </translation>
+ <translation>경고 : 모든 네트워크가 동의해야 하나, 일부 채굴자들에게 문제가 있는 것으로 보입니다.</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>
@@ -3387,7 +3268,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Not enough file descriptors available.</source>
- <translation>파일 디스크립터가 부족합니다. </translation>
+ <translation>파일 디스크립터가 부족합니다.</translation>
</message>
<message>
<source>Prune cannot be configured with a negative value.</source>
@@ -3568,16 +3449,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>이것은 수수료 추정을 이용할 수 없을 때 사용되는 거래 수수료입니다.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>이 제품에는 OpenSSL 프로젝트에서 OpenSSL Toolkit %s으로 사용하기 위해 개발 한 소프트웨어와 에릭 영이 작성한 암호화 소프트웨어 및 토머스 버나드가 작성한 UPnP 소프트웨어가 포함되어 있습니다.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
+ <translation>경고 : 지갑파일이 손상되어 데이터가 복구되었습니다. 원래의 %s 파일은 %s 후에 %s 이름으로 저장됩니다. 잔액과 거래 내역이 정확하지 않다면 백업 파일로 부터 복원해야 합니다.</translation>
</message>
<message>
<source>%s is set very high!</source>
diff --git a/src/qt/locale/bitcoin_ku_IQ.ts b/src/qt/locale/bitcoin_ku_IQ.ts
index afdb4c781f..68ddf09ddc 100644
--- a/src/qt/locale/bitcoin_ku_IQ.ts
+++ b/src/qt/locale/bitcoin_ku_IQ.ts
@@ -25,6 +25,14 @@
<source>&amp;Delete</source>
<translation>&amp;سڕینەوە</translation>
</message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;ڕوونووسکردن ناوونیشان</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;دەسکاریکردن</translation>
+ </message>
</context>
<context>
<name>AddressTableModel</name>
@@ -89,6 +97,10 @@
<translation>رێکەت</translation>
</message>
<message>
+ <source>Copy address</source>
+ <translation>ڕوونووسکردن ناوونیشان</translation>
+ </message>
+ <message>
<source>yes</source>
<translation>بەڵێ</translation>
</message>
@@ -286,6 +298,10 @@
<source>Amount</source>
<translation>سەرجەم</translation>
</message>
+ <message>
+ <source>Message</source>
+ <translation>پەیام</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -293,6 +309,10 @@
<source>Date</source>
<translation>رێکەت</translation>
</message>
+ <message>
+ <source>Message</source>
+ <translation>پەیام</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -304,6 +324,10 @@
<source>Fee:</source>
<translation>تێچوون:</translation>
</message>
+ <message>
+ <source>or</source>
+ <translation>یان</translation>
+ </message>
</context>
<context>
<name>SendCoinsEntry</name>
@@ -313,13 +337,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>بەڵێ</translation>
- </message>
-</context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -331,14 +348,42 @@
<context>
<name>TransactionDesc</name>
<message>
+ <source>Status</source>
+ <translation>بارودۆخ</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>رێکەت</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>سەرچاوە</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>لە</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>بۆ</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>پەیام</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>سەرجەم</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>دروستە</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>نادروستە</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
</context>
@@ -348,18 +393,42 @@
<source>Date</source>
<translation>رێکەت</translation>
</message>
+ <message>
+ <source>Type</source>
+ <translation>جۆر</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>ناردن بۆ</translation>
+ </message>
</context>
<context>
<name>TransactionView</name>
<message>
+ <source>Sent to</source>
+ <translation>ناردن بۆ</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>ڕوونووسکردن ناوونیشان</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>رێکەت</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>جۆر</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>ناوونیشان</translation>
</message>
- </context>
+ <message>
+ <source>to</source>
+ <translation>بۆ</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
diff --git a/src/qt/locale/bitcoin_ky.ts b/src/qt/locale/bitcoin_ky.ts
index 6f2560e1d6..bfb9c663fd 100644
--- a/src/qt/locale/bitcoin_ky.ts
+++ b/src/qt/locale/bitcoin_ky.ts
@@ -269,9 +269,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts
index 6866b1d17e..830a665844 100644
--- a/src/qt/locale/bitcoin_la.ts
+++ b/src/qt/locale/bitcoin_la.ts
@@ -29,10 +29,42 @@
<source>&amp;Delete</source>
<translation>&amp;Dele</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>Hae sunt inscriptiones mittendi pensitationes. Semper inspice quantitatem et inscriptionem accipiendi antequam nummos mittis.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Copia Inscriptionem</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Copia &amp;Titulum</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Muta</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Comma Separata Plica (*.csv)</translation>
+ </message>
</context>
<context>
<name>AddressTableModel</name>
- </context>
+ <message>
+ <source>Label</source>
+ <translation>Titulus</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Inscriptio</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(nullus titulus)</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
<message>
@@ -51,7 +83,83 @@
<source>Repeat new passphrase</source>
<translation>Itera novam tesseram</translation>
</message>
- </context>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Cifra cassidile</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Huic operationi necesse est tessera cassidili tuo ut cassidile reseret.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Resera cassidile</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Huic operationi necesse est tessera cassidili tuo ut cassidile decifret.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Decifra cassidile</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Muta tesseram</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Confirma cifrationem cassidilis</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Monitio: Si cassidile tuum cifras et tesseram amittis, tu &lt;b&gt;AMITTES OMNES TUOS NUMMOS BITOS&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Certusne es te velle tuum cassidile cifrare?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Cassidile cifratum</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>GRAVE: Oportet ulla prioria conservata quae fecisti de plica tui cassidilis reponi a nove generata cifrata plica cassidilis. Propter securitatem, prioria conservata de plica non cifrata cassidilis inutilia fiet simul atque incipis uti novo cifrato cassidili.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Cassidile cifrare abortum est</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Cassidile cifrare abortum est propter internum errorem. Tuum cassidile cifratum non est.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Tesserae datae non eaedem sunt.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Cassidile reserare abortum est.</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Tessera inserta pro cassidilis decifrando prava erat.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Cassidile decifrare abortum est.</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Tessera cassidilis successa est in mutando.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Monitio: Litterae ut capitales seratae sunt!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
</context>
@@ -130,14 +238,6 @@
<translation>Muta tesseram utam pro cassidilis cifrando</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Fenestra &amp;Debug</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Aperi terminalem debug et diagnosticalem</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verifica nuntium...</translation>
</message>
@@ -241,7 +341,11 @@
<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>
- </context>
+ <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>
<name>CoinControlDialog</name>
<message>
@@ -260,6 +364,26 @@
<source>Confirmed</source>
<translation>Confirmatum</translation>
</message>
+ <message>
+ <source>Copy address</source>
+ <translation>Copia inscriptionem</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copia titulum</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copia quantitatem</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copia transactionis ID</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(nullus titulus)</translation>
+ </message>
</context>
<context>
<name>CreateWalletActivity</name>
@@ -281,7 +405,31 @@
<source>&amp;Address</source>
<translation>&amp;Inscriptio</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Nova inscriptio mittendi</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Muta inscriptionem accipiendi</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Muta inscriptionem mittendi</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>Inscriptio inserta "%1" non valida inscriptio Bitcoin est.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Non potuisse cassidile reserare</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Generare novam clavem abortum est.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
</context>
@@ -448,6 +596,14 @@
</context>
<context>
<name>PaymentServer</name>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Bitcoin incipere non potest: cliccare-ad-pensandum handler</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>Tractatio URI</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -477,6 +633,10 @@
<source>Error encoding URI into QR Code.</source>
<translation>Error codificandi URI in codicem QR.</translation>
</message>
+ <message>
+ <source>Save QR Code</source>
+ <translation>Salva codicem QR</translation>
+ </message>
</context>
<context>
<name>RPCConsole</name>
@@ -493,10 +653,6 @@
<translation>&amp;Informatio</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Fenestra Debug</translation>
- </message>
- <message>
<source>Startup time</source>
<translation>Tempus initiandi</translation>
</message>
@@ -551,7 +707,15 @@
<source>&amp;Message:</source>
<translation>Nuntius:</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>Copia titulum</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copia quantitatem</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -559,10 +723,22 @@
<translation>&amp;Copia Inscriptionem</translation>
</message>
<message>
+ <source>Address</source>
+ <translation>Inscriptio</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Quantitas</translation>
</message>
<message>
+ <source>Label</source>
+ <translation>Titulus</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Nuntius</translation>
+ </message>
+ <message>
<source>Wallet</source>
<translation>Cassidile</translation>
</message>
@@ -573,6 +749,18 @@
<source>Date</source>
<translation>Dies</translation>
</message>
+ <message>
+ <source>Label</source>
+ <translation>Titulus</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Nuntius</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(nullus titulus)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -617,10 +805,34 @@
<translation>&amp;Mitte</translation>
</message>
<message>
+ <source>Copy amount</source>
+ <translation>Copia quantitatem</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Transactionis merces</translation>
</message>
- </context>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Confirma mittendum nummorum</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Oportet quantitatem ad pensandum maiorem quam 0 esse.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Quantitas est ultra quod habes.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>Quantitas est ultra quod habes cum merces transactionis %1 includitur.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(nullus titulus)</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
<message>
@@ -657,9 +869,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -728,29 +937,169 @@
<source>Reset all verify message fields</source>
<translation>Reconstitue omnes campos verificandi nuntii</translation>
</message>
- </context>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Clicca "Signa Nuntium" ut signatio generetur</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>Inscriptio inserta non valida est.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Sodes inscriptionem proba et rursus conare.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>Inserta inscriptio clavem non refert.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>Cassidilis reserare cancellatum est.</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>Clavis privata absens est pro inserta inscriptione.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Nuntium signare abortum est.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Nuntius signatus.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>Signatio decodificari non potuit.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Sodes signationem proba et rursus conare.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>Signatio non convenit digesto nuntii</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Nuntium verificare abortum est.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Nuntius verificatus.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
</context>
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>Apertum donec %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/non confirmata</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 confirmationes</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Status</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Dies</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>Fons</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Generatum</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>Ab</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>ignotum</translation>
</message>
<message>
+ <source>To</source>
+ <translation>Ad</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>inscriptio propria</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>titulus</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Creditum</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>non acceptum</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Debitum</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Transactionis merces</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>Cuncta quantitas</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Nuntius</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Annotatio</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID transactionis</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Informatio de debug</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transactio</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>Lectenda</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Quantitas</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>verum</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>falsum</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
@@ -764,10 +1113,154 @@
<source>Date</source>
<translation>Dies</translation>
</message>
- </context>
+ <message>
+ <source>Type</source>
+ <translation>Typus</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Titulus</translation>
+ </message>
+ <message>
+ <source>Open until %1</source>
+ <translation>Apertum donec %1</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Confirmatum (%1 confirmationes)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Generatum sed non acceptum</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Acceptum cum</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Acceptum ab</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Missum ad</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Pensitatio ad te ipsum</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Fossa</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n/a)</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(nullus titulus)</translation>
+ </message>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Status transactionis. Supervola cum mure ut monstretur numerus confirmationum.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Dies et tempus quando transactio accepta est.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Typus transactionis.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Quantitas remota ex pendendo aut addita ei.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Omne</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Hodie</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Hac hebdomade</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Hoc mense</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Postremo mense</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Hoc anno</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Intervallum...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Acceptum cum</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Missum ad</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Ad te ipsum</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Fossa</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Alia</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Quantitas minima</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Copia inscriptionem</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copia titulum</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copia quantitatem</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copia transactionis ID</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Muta titulum</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Monstra particularia transactionis</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Comma Separata Plica (*.csv)</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation>Confirmatum</translation>
</message>
@@ -775,7 +1268,31 @@
<source>Date</source>
<translation>Dies</translation>
</message>
- </context>
+ <message>
+ <source>Type</source>
+ <translation>Typus</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Titulus</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Inscriptio</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Intervallum:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>ad</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
@@ -802,10 +1319,30 @@
<source>Export the data in the current tab to a file</source>
<translation>Exporta data in hac tabella in plicam</translation>
</message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Conserva cassidile</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>Data cassidilis (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Conservare abortum est.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Successum in conservando</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation>Hoc est prae-dimittum experimentala aedes - utere eo periculo tuo proprio - nolite utere fodendo vel applicationibus mercatoriis</translation>
+ </message>
+ <message>
<source>Corrupted block database detected</source>
<translation>Corruptum databasum frustorum invenitur</translation>
</message>
diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts
index 055b4229c1..afdc7ffb8d 100644
--- a/src/qt/locale/bitcoin_lt.ts
+++ b/src/qt/locale/bitcoin_lt.ts
@@ -67,7 +67,7 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>Tai yra jūsų Bitcoin adresai išeinantiems mokėjimams. Visada pasitikrinkite sumą ir gavėjo adresą prieš siunčiant lėšas. </translation>
+ <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>&amp;Copy Address</source>
@@ -132,6 +132,10 @@
<translation>Pakartokite naują slaptafrazę</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Rodyti slaptafrazę</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Užšifruoti piniginę</translation>
</message>
@@ -161,7 +165,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>Dėmesio: jei užšifruosite savo piniginę ir pamesite slaptafrazę, jūs&lt;b&gt;PRARASITE VISUS SAVO BITCOINUS&lt;/b&gt;! </translation>
+ <translation>Dėmesio: jei užšifruosite savo piniginę ir pamesite slaptafrazę, jūs&lt;b&gt;PRARASITE VISUS SAVO BITCOINUS&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -173,7 +177,7 @@
</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>SVARBU: Betkokios ankstesnės jūsų piniginės atsarginės kopijos turėtų būti pakeistos naujai sugeneruotu, užšifruotu piniginės failu. Dėl saugumo sumetimų, anstesnės neužšifruotos piniginės kopijos failas taps nenaudingu nuo momento, kai nauja ir užšifruota piniginė bus pradėta naudoti. </translation>
+ <translation>SVARBU: Betkokios ankstesnės jūsų piniginės atsarginės kopijos turėtų būti pakeistos naujai sugeneruotu, užšifruotu piniginės failu. Dėl saugumo sumetimų, anstesnės neužšifruotos piniginės kopijos failas taps nenaudingu nuo momento, kai nauja ir užšifruota piniginė bus pradėta naudoti.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
@@ -334,14 +338,6 @@
<translation>Pakeisti slaptafrazę naudojamą piniginės užšifravimui</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Derinimo langas</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Atverti derinimo ir diagnostikos konsolę</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Tikrinti žinutę...</translation>
</message>
@@ -367,7 +363,7 @@
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Pasirašydami žinutes su savo Bitcoin adresais įrodysite jog esate jų savininkas </translation>
+ <translation>Pasirašydami žinutes su savo Bitcoin adresais įrodysite jog esate jų savininkas</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
@@ -402,10 +398,6 @@
<translation>Rodyti sąrašą panaudotų gavimo adresų ir žymių</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Atidaryti bitcoin: URI ar apmokėjimo reikalavimą</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Komandinės eilutės parametrai</translation>
</message>
@@ -435,7 +427,7 @@
</message>
<message>
<source>Transactions after this will not yet be visible.</source>
- <translation>Sekančios operacijos dar nebus matomos. </translation>
+ <translation>Sekančios operacijos dar nebus matomos.</translation>
</message>
<message>
<source>Error</source>
@@ -828,10 +820,6 @@
<translation>versija</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>&amp;Apie %1</translation>
</message>
@@ -965,25 +953,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Atidaryti URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Atidaryti mokėjimo užklausą iš URI arba failo</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Pasirinkite mokėjimo užklausos failą</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Pasirinkite mokėjimo užklausos failą</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1365,18 +1337,6 @@
<translation>„bitcoin: //“ nėra galiojantis URI. Vietoj to naudokite „bitcoin:“.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Jūs naudojate BIP70 URL, kuris ateityje nebus palaikomas.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Mokėjimo užklausos atsiuntimo URL neteisingas: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Nepavyksta apdoroti mokėjimo užklausos, nes „BIP70“ pagalba nebuvo surinkta.</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>Neteisingas mokėjimo adresas %1</translation>
</message>
@@ -1388,66 +1348,6 @@
<source>Payment request file handling</source>
<translation>Mokėjimo užklausos failų tvarkymas</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Mokėjimo užklausos failo negalima skaityti! Tai gali sukelti neteisingas mokėjimo užklausos failas.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Mokėjimo prašymas atmestas</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Mokėjimo užklausų tinklas neatitinka klientų tinklo.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Mokėjimo prašymas pasibaigė</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Mokėjimo prašymas nėra inicijuotas.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Nepatvirtinti mokėjimo prašymai pagal individualius mokėjimo scenarijus nepalaikomi.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Neteisingas mokėjimo prašymas.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Prašoma %1 mokėjimo suma yra per maža (laikoma kaip dulkės).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Grąžinimas iš %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Mokėjimo užklausa %1 yra per didelė (%2 baitai, leidžiama %3 baitų).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Ryšio klaida su %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Mokėjimo užklausos negalima perskaityti!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Blogas atsakymas iš serverio %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Tinklo užklausos klaida</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Mokėjimas patvirtintas</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1621,10 +1521,6 @@
<translation>&amp;Informacija</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Derinimo langas</translation>
- </message>
- <message>
<source>General</source>
<translation>Bendras</translation>
</message>
@@ -2161,10 +2057,6 @@
<translation>Įspėjimas: šiuo metu neįmanoma apskaičiuoti mokesčio.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>sumažinti mokesčio nustatymus</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>
@@ -2333,10 +2225,6 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<translation>Sandorio sudarymas nepavyko!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Sandoris buvo atmestas dėl šios priežasties: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Mokestis, didesnis nei %1, laikomas absurdiškai aukštu mokesčiu.</translation>
</message>
@@ -2388,10 +2276,6 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<translation>Pasirinkite anksčiau naudojamą adresą</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Tai įprastas mokėjimas.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Bitcoin adresas, į kurį siunčiamas mokėjimas</translation>
</message>
@@ -2451,17 +2335,6 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<source>Memo:</source>
<translation>Atmintinė:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Įveskite šio adreso etiketę, kad ją pridėtumėte prie adresų knygos</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Taip</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2715,6 +2588,10 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<translation>Sandorio mokestis</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>Neto suma</translation>
+ </message>
+ <message>
<source>Message</source>
<translation>Žinutė</translation>
</message>
@@ -2723,6 +2600,10 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<translation>Komentaras</translation>
</message>
<message>
+ <source>Transaction ID</source>
+ <translation>Sandorio ID</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Prekybininkas</translation>
</message>
diff --git a/src/qt/locale/bitcoin_lv.ts b/src/qt/locale/bitcoin_lv.ts
index f4f3cea70d..a5c96c1a2a 100644
--- a/src/qt/locale/bitcoin_lv.ts
+++ b/src/qt/locale/bitcoin_lv.ts
@@ -210,14 +210,6 @@
<translation>Mainīt maciņa šifrēšanas paroli</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Atkļūdošanas logs</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Atvērt atkļūdošanas un diagnostikas konsoli</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Pārbaudīt ziņojumu...</translation>
</message>
@@ -270,10 +262,6 @@
<translation>Pieprasīt maksājumus (izveido QR kodu un bitcoin: URIs)</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Atvērt bitcoin URI vai maksājuma pieprasījumu</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Komandrindas iespējas</translation>
</message>
@@ -432,10 +420,6 @@
<translation>versija</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-biti)</translation>
- </message>
- <message>
<source>Command-line options</source>
<translation>Komandrindas iespējas</translation>
</message>
@@ -477,22 +461,10 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Atvērt URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Atvērt maksājuma pieprasījumu no URI vai datnes</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Izvēlies maksājuma pieprasījuma datni</translation>
- </message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
</context>
@@ -745,10 +717,6 @@
<translation>&amp;Informācija</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Atkļūdošanas logs</translation>
- </message>
- <message>
<source>General</source>
<translation>Vispārējs</translation>
</message>
@@ -1016,10 +984,6 @@
<translation>Izvēlies iepriekš izmantoto adresi</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Šis ir parasts maksājums.</translation>
- </message>
- <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -1047,10 +1011,7 @@
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
+</context>
<context>
<name>ShutdownWindow</name>
<message>
diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts
deleted file mode 100644
index fc74e787ed..0000000000
--- a/src/qt/locale/bitcoin_lv_LV.ts
+++ /dev/null
@@ -1,1279 +0,0 @@
-<TS language="lv_LV" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Create a new address</source>
- <translation>Izveidot jaunu adresi</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Jauns</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Kopēt iezīmēto adresi uz starpliktuvi</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Kopēt</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>&amp;Aizvērt</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Izdzēst iezīmētās adreses no saraksta</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Ierakstiet meklējamo nosaukumu vai adresi</translation>
- </message>
- <message>
- <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>&amp;Export</source>
- <translation>&amp;Eksportēt</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Dzēst</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Izvēlies adresi uz kuru sūtīt bitcoins</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Izvēlies adresi ar kuru saņemt bitcoins</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Kopēt adresi</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Kopēt &amp;Marķējumu</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Rediģēt</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Eksportēt Adrešu Sarakstu</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Eksportēšana Neizdevās</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Nosaukums</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adrese</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez nosaukuma)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Paroles dialogs</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Ierakstiet paroli</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Jauna parole</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Jaunā parole vēlreiz</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Rādīt paroli</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Šifrēt maciņu</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Atslēgt maciņu</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Atšifrēt maciņu</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Apstiprināt maciņa šifrēšanu</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Vai tu tiešām vēlies šifrēt savu maciņu?</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Maciņa šifrēšana neizdevās</translation>
- </message>
- </context>
-<context>
- <name>BanTableModel</name>
- </context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Parakstīt &amp;ziņojumu...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Sinhronizācija ar tīklu...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Pārskats</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Node</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Rādīt vispārēju maciņa pārskatu</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transakcijas</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Skatīt transakciju vēsturi</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>&amp;Iziet</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Aizvērt programmu</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Par &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Parādīt informāciju par Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Iespējas...</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>Šifrēt &amp;maciņu...</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Maciņa Rezerves Kopija...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>Mainīt &amp;Paroli...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Sūtīšanas adreses...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Saņemšanas &amp;adreses...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Atvērt &amp;URI...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Bloku reindeksēšana no diska...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Nosūtīt bitkoinus uz Bitcoin adresi</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Izveidot maciņa rezerves kopiju citur</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Mainīt maciņa šifrēšanas paroli</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Atkļūdošanas logs</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Atvērt atkļūdošanas un diagnostikas konsoli</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Pārbaudīt ziņojumu...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Maciņš</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Sūtīt</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Saņemt</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Rādīt / Paslēpt</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Parādīt vai paslēpt galveno Logu</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Šifrēt privātās atslēgas kuras pieder tavam maciņam</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Parakstīt ziņojumus ar savām Bitcoin adresēm lai pierādītu ka tās pieder tev</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Pārbaudīt ziņojumus lai pārliecinātos, ka tie tika parakstīti ar norādītajām Bitcoin adresēm</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Fails</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Uzstādījumi</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Palīdzība</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Ciļņu rīkjosla</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Pieprasīt maksājumus (izveido QR kodu un bitcoin: URIs)</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Atvērt bitcoin URI vai maksājuma pieprasījumu</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Komandrindas iespējas</translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 aizmugurē</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Transakcijas pēc šī vel nebūs redzamas</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Kļūda</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Brīdinājums</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informācija</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Sinhronizēts</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Sinhronizējos...</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Transakcija nosūtīta</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Ienākoša transakcija</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>Maciņš ir &lt;b&gt;šifrēts&lt;/b&gt; un pašlaik &lt;b&gt;atslēgts&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>Maciņš ir &lt;b&gt;šifrēts&lt;/b&gt; un pašlaik &lt;b&gt;slēgts&lt;/b&gt;</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Quantity:</source>
- <translation>Daudzums:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Baiti:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Daudzums:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Maksa:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Pēc Maksas:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Atlikums:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>iezīmēt visus</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Koka režīms</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Saraksta režīms</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Daudzums</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Datums</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Apstiprinājumi</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Apstiprināts</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez nosaukuma)</translation>
- </message>
- </context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Mainīt adrese</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Nosaukums</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Adrese</translation>
- </message>
- </context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Tiks izveidota jauna datu mape.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>vārds</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Šāds ceļš jau pastāv un tā nav mape.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Šeit nevar izveidot datu mapi.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>versija</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-biti)</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Komandrindas iespējas</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Sveiciens</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Izmantot noklusēto datu mapi</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Izmantot pielāgotu datu mapi:</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Kļūda</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Forma</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Pēdējā bloka laiks</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Atvērt URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Atvērt maksājuma pieprasījumu no URI vai datnes</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Izvēlies maksājuma pieprasījuma datni</translation>
- </message>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Iespējas</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Galvenais</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>&amp;Datubāzes kešatmiņas izmērs</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>Skriptu &amp;pārbaudes pavedienu skaits</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Starpniekservera IP adrese (piem. IPv4: 127.0.0.1 / IPv6: ::1)</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>Minimizēt nevis aizvērt aplikāciju, kad logs tiek aizvērts. Kad šī iespēja ir ieslēgta, aplikācija tiks aizvērta, izvēloties Aizvērt izvēlnē.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Aktīvās komandrindas opcijas, kuras pārspēko šos iestatījumus:</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Atiestatīt visus klienta iestatījumus uz noklusējumu.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Atiestatīt Iestatījumus.</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Tīkls</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>&amp;Maciņš</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Eksperts</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Ieslēgt bitcoin &amp;kontroles funkcijas</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>&amp;Tērēt neapstiprinātu atlikumu</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>Uz rūtera automātiski atvērt Bitcoin klienta portu. Tas strādā tikai tad, ja rūteris atbalsta UPnP un tas ir ieslēgts.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Kartēt portu, izmantojot &amp;UPnP</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>Starpniekservera &amp;IP:</translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>&amp;Ports:</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Starpniekservera ports (piem. 9050)</translation>
- </message>
- <message>
- <source>&amp;Window</source>
- <translation>&amp;Logs</translation>
- </message>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Pēc loga minimizācijas rādīt tikai ikonu sistēmas teknē.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimizēt uz sistēmas tekni, nevis rīkjoslu</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>M&amp;inimizēt aizverot</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Izskats</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>Lietotāja interfeiss un &amp;valoda:</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Vienības, kurās attēlot daudzumus:</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Izvēlēties dalījuma vienību pēc noklusēšanas, ko izmantot interfeisā un nosūtot bitkoinus.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Vai rādīt Bitcoin kontroles funkcijas vai nē.</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;Labi</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Atcelt</translation>
- </message>
- <message>
- <source>default</source>
- <translation>pēc noklusēšanas</translation>
- </message>
- <message>
- <source>none</source>
- <translation>neviena</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Apstiprināt iestatījumu atiestatīšanu</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Kļūda</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Norādītā starpniekservera adrese nav derīga.</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Forma</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>Attēlotā informācija var būt novecojusi. Jūsu maciņš pēc savienojuma izveides automātiski sinhronizējas ar Bitcoin tīklu, taču šis process vēl nav beidzies.</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Pieejams:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Tava pašreizējā tērējamā bilance</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Neizšķirts:</translation>
- </message>
- <message>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Kopējā apstiprināmo transakciju vērtība, vēl nav ieskaitīta tērējamajā bilancē</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Nenobriedušu:</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Kopsumma:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Jūsu kopējā tekošā bilance</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- </context>
-<context>
- <name>PeerTableModel</name>
- </context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Daudzums</translation>
- </message>
- <message>
- <source>%1 h</source>
- <translation>%1 st</translation>
- </message>
- <message>
- <source>%1 m</source>
- <translation>%1 m</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>N/A</translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 un %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>unknown</source>
- <translation>nav zināms</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>N/A</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Klienta versija</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Informācija</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Atkļūdošanas logs</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Vispārējs</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Sākuma laiks</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Tīkls</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Vārds</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Savienojumu skaits</translation>
- </message>
- <message>
- <source>Block chain</source>
- <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>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Atvērt</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Konsole</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Tīkla Satiksme</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Kopsummas</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Ie.:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Iz.:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Atkļūdošanas žurnāla datne</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Notīrīt konsoli</translation>
- </message>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>&amp;Daudzums:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Nosaukums:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Ziņojums:</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Notīrīt visus laukus formā.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Notīrīt</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>Pieprasīto maksājumu vēsture</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Pieprasīt maksājumu</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Parādīt atlasītos pieprasījumus (tas pats, kas dubultklikšķis uz ieraksta)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Rādīt</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Noņemt atlasītos ierakstus no saraksta.</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Noņemt</translation>
- </message>
- </context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>QR Kods</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Kopēt &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Kopēt &amp;Adresi</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Saglabāt Attēlu...</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adrese</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Nosaukums</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Maciņš</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Label</source>
- <translation>Nosaukums</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez nosaukuma)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Sūtīt Bitkoinus</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Bitcoin Kontroles Funkcijas</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Ieejas...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>automātiski atlasīts</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Nepietiekami līdzekļi!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Daudzums:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Baiti:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Daudzums:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Maksa:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Pēc Maksas:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Atlikums:</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Pielāgota atlikuma adrese</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Transakcijas maksa:</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Sūtīt vairākiem saņēmējiem uzreiz</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>&amp;Pievienot Saņēmēju</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Notīrīt visus laukus formā.</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>&amp;Notīrīt visu</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Bilance:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Apstiprināt nosūtīšanu</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>&amp;Sūtīt</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Transakcijas maksa</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez nosaukuma)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>Apjo&amp;ms</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>&amp;Saņēmējs:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Nosaukums:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Izvēlies iepriekš izmantoto adresi</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Šis ir parasts maksājums.</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>ielīmēt adresi no starpliktuves</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Noņem šo ierakstu</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Ziņojums:</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Maksāt:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Memo:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>Neizslēdziet datoru kamēr šis logs nepazūd.</translation>
- </message>
-</context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Paraksti - Parakstīt / Pabaudīt Ziņojumu</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>Parakstīt &amp;Ziņojumu</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Izvēlies iepriekš izmantoto adresi</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>ielīmēt adresi no starpliktuves</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Šeit ievadi ziņojumu kuru vēlies parakstīt</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Paraksts</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Kopēt parakstu uz sistēmas starpliktuvi</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Parakstīt ziņojumu lai pierādītu, ka esi šīs Bitcoin adreses īpašnieks.</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Parakstīt &amp;Ziņojumu</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Atiestatīt visus laukus</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>&amp;Notīrīt visu</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Pārbaudīt Ziņojumu</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>&amp;Pārbaudīt Ziņojumu</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Atiestatīt visus laukus</translation>
- </message>
- </context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnets]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KB/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Šis panelis parāda transakcijas detaļas</translation>
- </message>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Label</source>
- <translation>Nosaukums</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(bez nosaukuma)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Label</source>
- <translation>Nosaukums</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adrese</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Eksportēšana Neizdevās</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Kļūda ielādējot bloku datubāzi</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Kļūda: Zema diska vieta!</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>Importē...</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Pārbauda blokus...</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informācija</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Transakcijas parakstīšana neizdevās</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Transakcijas summa ir pārāk maza</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Transakcija ir pārāk liela</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Brīdinājums</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>-onlynet komandā norādīts nepazīstams tīkls: '%s'</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Nepietiek bitkoinu</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Ielādē bloku indeksu...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Ielādē maciņu...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Nevar maciņa formātu padarīt vecāku</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Skanēju no jauna...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Ielāde pabeigta</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Kļūda</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_mk.ts b/src/qt/locale/bitcoin_mk.ts
index 3945687845..72aea8582f 100644
--- a/src/qt/locale/bitcoin_mk.ts
+++ b/src/qt/locale/bitcoin_mk.ts
@@ -281,10 +281,6 @@
<source>version</source>
<translation>верзија</translation>
</message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-бит)</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -303,14 +299,10 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Отвори URI</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
</context>
@@ -547,9 +539,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_ml.ts b/src/qt/locale/bitcoin_ml.ts
index 8bc0f3b54c..299d81bf75 100644
--- a/src/qt/locale/bitcoin_ml.ts
+++ b/src/qt/locale/bitcoin_ml.ts
@@ -258,9 +258,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_mn.ts b/src/qt/locale/bitcoin_mn.ts
index 07093aca94..0423c35a68 100644
--- a/src/qt/locale/bitcoin_mn.ts
+++ b/src/qt/locale/bitcoin_mn.ts
@@ -41,10 +41,66 @@
<source>&amp;Delete</source>
<translation>&amp;Устгах</translation>
</message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Зооснуудыг илгээх хаягийг сонгоно уу</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Зооснуудыг хүлээн авах хаягийг сонгоно уу</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>С&amp;онго</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Илгээх хаягууд</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <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>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>&amp;Шошгыг хуулбарлах</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Ѳѳрчлѳх</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Экспорт хийх хаягуудын жагсаалт</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Таслалаар тусгаарлагдсан хүснэгтэн файл (.csv)</translation>
+ </message>
</context>
<context>
<name>AddressTableModel</name>
- </context>
+ <message>
+ <source>Label</source>
+ <translation>Шошго</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Хаяг</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(шошгогүй)</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
<message>
@@ -59,6 +115,66 @@
<source>Repeat new 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>
+ <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>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Түрүйвч цоожлогдлоо</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Түрүйвчийн цоожлол амжилттай болсонгүй</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Түрүйвчийн цоожлол дотоод алдаанаас үүдэн амжилттай болсонгүй. Түрүйвч цоожлогдоогүй байна.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Таны оруулсан нууц үг таарсангүй</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Түрүйвчийн цоож тайлагдсангүй</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Таны оруулсан түрүйвчийн цоожийг тайлах нууц үг буруу байна</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Түрүйвчийн цоож амжилттай устгагдсангүй</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Түрүйвчийн нууц үг амжилттай ѳѳр</translation>
+ </message>
</context>
<context>
<name>BanTableModel</name>
@@ -118,10 +234,6 @@
<translation>Түрүйвчийг цоожлох нууц үгийг солих</translation>
</message>
<message>
- <source>Open debugging and diagnostic console</source>
- <translation>Оношилгоо ба засварын консолыг онгойлго</translation>
- </message>
- <message>
<source>&amp;Show / Hide</source>
<translation>&amp;Харуул / Нуу</translation>
</message>
@@ -188,7 +300,31 @@
<source>Confirmed</source>
<translation>Баталгаажлаа</translation>
</message>
- </context>
+ <message>
+ <source>Copy address</source>
+ <translation>Хаягийг санах</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Шошгыг санах</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Хэмжээг санах</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Ѳѳрчлѳлтийг санах</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(шошгогүй)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(ѳѳрчлѳх)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
</context>
@@ -209,7 +345,27 @@
<source>&amp;Address</source>
<translation>&amp;Хаяг</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Шинэ явуулах хаяг</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Хүлээн авах хаягийг ѳѳрчлѳх</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Явуулах хаягийг ѳѳрчлѳх</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Түрүйвчийн цоожийг тайлж чадсангүй</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Шинэ түлхүүр амжилттай гарсангүй</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
</context>
@@ -305,7 +461,11 @@
</context>
<context>
<name>QRImageWidget</name>
- </context>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>PNG форматын зураг (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -387,7 +547,19 @@
<source>Remove</source>
<translation>Устгах</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>Шошгыг санах</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Зурвасыг санах</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Хэмжээг санах</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -395,10 +567,22 @@
<translation>Хаягийг &amp;Хуулбарлах</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>
@@ -409,6 +593,22 @@
<source>Date</source>
<translation>Огноо</translation>
</message>
+ <message>
+ <source>Label</source>
+ <translation>Шошго</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Зурвас</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(шошгогүй)</translation>
+ </message>
+ <message>
+ <source>(no message)</source>
+ <translation>(зурвас алга)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -456,7 +656,43 @@
<source>S&amp;end</source>
<translation>Яв&amp;уул</translation>
</message>
- </context>
+ <message>
+ <source>Copy amount</source>
+ <translation>Хэмжээг санах</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Ѳѳрчлѳлтийг санах</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>эсвэл</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Зоос явуулахыг баталгаажуулна уу</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Тѳлѳх хэмжээ 0.-оос их байх ёстой</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Энэ хэмжээ таны балансаас хэтэрсэн байна.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>Гүйлгээний тѳлбѳр %1-ийг тооцхоор нийт дүн нь таны балансаас хэтрээд байна.</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Анхаар:Буруу Биткойны хаяг байна</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(шошгогүй)</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
<message>
@@ -493,9 +729,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
<message>
<source>Do not shut down the computer until this window disappears.</source>
@@ -527,6 +760,18 @@
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>%1 хүртэл нээлттэй</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/баталгаажаагүй</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 баталгаажилтууд</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Огноо</translation>
</message>
@@ -535,6 +780,14 @@
<translation>үл мэдэгдэх</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Зурвас</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>Тодорхойлолт</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Хэмжээ</translation>
</message>
@@ -552,10 +805,154 @@
<source>Date</source>
<translation>Огноо</translation>
</message>
- </context>
+ <message>
+ <source>Type</source>
+ <translation>Тѳрѳл</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Шошго</translation>
+ </message>
+ <message>
+ <source>Open until %1</source>
+ <translation>%1 хүртэл нээлттэй</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>Баталгаажаагүй</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Баталгаажлаа (%1 баталгаажилт)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation>Зѳрчилдлѳѳ</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Үүсгэгдсэн гэхдээ хүлээн авагдаагүй</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Хүлээн авсан хаяг</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Хүлээн авагдсан хаяг</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Явуулсан хаяг</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Ѳѳрлүүгээ хийсэн тѳлбѳр</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Олборлогдсон</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(алга байна)</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(шошгогүй)</translation>
+ </message>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Гүйлгээний байдал. Энд хулганыг авчирч баталгаажуулалтын тоог харна уу.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Гүйлгээг хүлээн авсан огноо ба цаг.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Гүйлгээний тѳрѳл</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Балансаас авагдсан болон нэмэгдсэн хэмжээ.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Бүгд</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Ѳнѳѳдѳр</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Энэ долоо хоног</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Энэ сар</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Ѳнгѳрсѳн сар</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Энэ жил</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Хүлээн авсан хаяг</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Явуулсан хаяг</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Ѳѳрлүүгээ</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Олборлогдсон</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Бусад</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Хамгийн бага хэмжээ</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Хаягийг санах</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Шошгыг санах</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Хэмжээг санах</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Шошгыг ѳѳрчлѳх</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Гүйлгээний дэлгэрэнгүйг харуул</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Таслалаар тусгаарлагдсан хүснэгтэн файл (.csv)</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation>Баталгаажлаа</translation>
</message>
@@ -563,7 +960,31 @@
<source>Date</source>
<translation>Огноо</translation>
</message>
- </context>
+ <message>
+ <source>Type</source>
+ <translation>Тѳрѳл</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Шошго</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Хаяг</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>Тодорхойлолт</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>Гүйлгээнүй түүхийг %1-д амжилттай хадгаллаа.</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>-рүү/руу</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
@@ -572,7 +993,11 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>Ямар ч түрүйвч ачааллагдсангүй.</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
diff --git a/src/qt/locale/bitcoin_mr_IN.ts b/src/qt/locale/bitcoin_mr_IN.ts
index 9dc3dd19c8..4a74385b29 100644
--- a/src/qt/locale/bitcoin_mr_IN.ts
+++ b/src/qt/locale/bitcoin_mr_IN.ts
@@ -47,7 +47,7 @@
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>ज्या पत्त्यावर नाणी प्राप्त करायची आहेत तो </translation>
+ <translation>ज्या पत्त्यावर नाणी प्राप्त करायची आहेत तो</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -157,9 +157,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -196,7 +193,7 @@
<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>
diff --git a/src/qt/locale/bitcoin_ms.ts b/src/qt/locale/bitcoin_ms.ts
index ada2bfbde6..f5f5bb7a87 100644
--- a/src/qt/locale/bitcoin_ms.ts
+++ b/src/qt/locale/bitcoin_ms.ts
@@ -245,7 +245,7 @@ Alihkan fail data ke dalam tab semasa</translation>
</message>
<message>
<source>Browse transaction history</source>
- <translation>Menyemak imbas sejarah transaksi </translation>
+ <translation>Menyemak imbas sejarah transaksi</translation>
</message>
<message>
<source>E&amp;xit</source>
@@ -332,14 +332,6 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Tukar kata laluan untuk dompet disulitkan</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Tetingkap windows</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>buka debug dan konsol diagnostik</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>sahkan mesej</translation>
</message>
@@ -361,7 +353,7 @@ Alihkan fail data ke dalam tab semasa</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
- <translation>sulitkan kata laluan milik peribadi anda </translation>
+ <translation>sulitkan kata laluan milik peribadi anda</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
@@ -435,6 +427,10 @@ Alihkan fail data ke dalam tab semasa</translation>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Amount</source>
+ <translation>Amount</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(tiada label)</translation>
</message>
@@ -509,6 +505,10 @@ Alihkan fail data ke dalam tab semasa</translation>
</context>
<context>
<name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>Amount</translation>
+ </message>
</context>
<context>
<name>QRImageWidget</name>
@@ -530,6 +530,10 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Alamat</translation>
</message>
<message>
+ <source>Amount</source>
+ <translation>Amount</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Label</translation>
</message>
@@ -564,9 +568,6 @@ Alihkan fail data ke dalam tab semasa</translation>
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -577,6 +578,10 @@ Alihkan fail data ke dalam tab semasa</translation>
</context>
<context>
<name>TransactionDesc</name>
+ <message>
+ <source>Amount</source>
+ <translation>Amount</translation>
+ </message>
</context>
<context>
<name>TransactionDescDialog</name>
diff --git a/src/qt/locale/bitcoin_ms_MY.ts b/src/qt/locale/bitcoin_ms_MY.ts
deleted file mode 100644
index 075c44c75f..0000000000
--- a/src/qt/locale/bitcoin_ms_MY.ts
+++ /dev/null
@@ -1,632 +0,0 @@
-<TS language="ms_MY" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Klik-kanan untuk edit alamat ataupun label</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Cipta alamat baru</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Baru</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Salin alamat terpilih ke dalam sistem papan klip</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Salin</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>&amp;Tutup</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Padam alamat semasa yang dipilih dari senaraiyang dipilih dari senarai</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Masukkan alamat atau label untuk carian
-</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>
-Alihkan fail data ke dalam tab semasa</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Eksport</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Padam</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Pilih alamat untuk hantar koin kepada</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Pilih alamat untuk menerima koin dengan</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>&amp;Pilih</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>alamat-alamat penghantaran</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>alamat-alamat penerimaan</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>Ini adalah alamat Bitcoin anda untuk pembayaran. Periksa jumlah dan alamat penerima sebelum membuat penghantaran koin sentiasa.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Ini adalah alamat Bitcoin anda untuk menerima pembayaraan. Anda disyorkan untuk menguna alamat menerima untuk setiap transaksi.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Salin Aamat</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Salin &amp; Label</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Edit</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Eskport Senarai Alamat</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Fail dibahagi oleh koma(*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Mengeksport Gagal</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Terdapat ralat semasa cubaan menyimpan senarai alamat kepada %1. Sila cuba lagi.</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Alamat</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(tiada label)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Dialog frasa laluan</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>memasukkan frasa laluan</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Frasa laluan baru</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Ulangi frasa laluan baru</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Tunjukkan kata laluan
-</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Memasukkan frasa laluan baru kepada dompet.&lt;br/&gt;Sila mengunakkan frasa laluan yang&lt;b&gt;mengandungi 10 atau lebih aksara rawak&lt;/b&gt;,ataupun&lt;b&gt;lapan atau lebih perkataan.&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Dompet encrypt</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Operasi ini perlukan frasa laluan dompet anda untuk membuka kunci dompet.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Membuka kunci dompet</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Operasi ini memerlukan frasa laluan dompet anda untuk menyahsulit dompet.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Menyahsulit dompet</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Menukar frasa laluan</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Memasukkan frasa laluan lama dan frasa laluan baru untuk.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Mengesahkan enkripsi dompet</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Amaran: Jika anda enkripkan dompet anda dan hilangkan frasa laluan, anda akan &lt;b&gt;ANDA AKAN HILANGKAN SEMUA BITCOIN ANDA&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Anda pasti untuk membuat enkripsi dompet anda?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Dompet dienkripsi</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 akan tutup untuk menyelesaikan proses enkripsi. Ingat bahawa enkripsi tidak boleh melidungi sepenuhnya bitcoins anda daripada dicuri oleh malware yang menjangkiti komputer anda.</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>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Enkripsi dompet gagal</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Enkripsi dompet gagal kerana ralat dalaman. Dompet anda tidak dienkripkan.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Frasa laluan yang dibekalkan tidak sepadan.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Pembukaan kunci dompet gagal</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Frasa laluan dimasukki untuk dekripsi dompet adalah tidak betul.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Dekripsi dompet gagal</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Frasa laluan dompet berjaya ditukar.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Amaran: Kunci Caps Lock buka!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmask</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Diharamkan sehingga</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Tandatangan &amp; mesej...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Penyegerakan dengan rangkaian...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Gambaran Keseluruhan</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Nod</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Tunjuk gambaran keseluruhan umum dompet</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transaksi</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Menyemak imbas sejarah transaksi </translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>&amp;Keluar</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Berhenti aplikasi</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Mengenai%1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Menunjuk informasi mengenai%1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Mengenai &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Menunjuk informasi megenai Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>Pilihan</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Mengubah suai pilihan konfigurasi untuk %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Enkripsi Dompet</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Dompet Sandaran...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Menukar frasa-laluan</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Menghantar frasa-laluan</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>&amp;Menerima frasa-laluan...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Buka &amp;URI...</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>dompet</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>dompet lalai
-</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Tekan untuk lumpuhkan rangkaian</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Aktiviti rangkaian dilumpuhkan</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Tekan untuk mengaktifkan rangkain semula</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Penyelarasn tajuk (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Reindexi blok pada cakera...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Menghantar koin kepada alamat Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Wallet sandaran ke lokasi lain</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Tukar kata laluan untuk dompet disulitkan</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>Tetingkap windows</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>buka debug dan konsol diagnostik</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>sahkan mesej</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>dompet</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>hantar</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>terima</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;tunjuk/sembunyi</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>tunjuk atau sembunyi tetingkap utama</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>sulitkan kata laluan milik peribadi anda </translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>sahkan mesej bersama alamat bitcoin anda untuk menunjukkan alamat ini anda punya</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Sahkan mesej untuk memastikan mereka telah ditandatangani dengan alamat Bitcoin yang ditentukan</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>fail</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>tetapan</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>tolong</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Bar alat tab
-</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Request payments (generates QR codes and bitcoin: URIs)
-</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Tunjukkan senarai alamat dan label yang digunakan
-</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>(no label)</source>
- <translation>(tiada label)</translation>
- </message>
- </context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Alamat</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>Alamat</translation>
- </message>
- </context>
-<context>
- <name>FreespaceChecker</name>
- </context>
-<context>
- <name>HelpMessageDialog</name>
- </context>
-<context>
- <name>Intro</name>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- </context>
-<context>
- <name>OpenURIDialog</name>
- </context>
-<context>
- <name>OptionsDialog</name>
- </context>
-<context>
- <name>OverviewPage</name>
- </context>
-<context>
- <name>PaymentServer</name>
- </context>
-<context>
- <name>PeerTableModel</name>
- </context>
-<context>
- <name>QObject</name>
- </context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>default wallet</source>
- <translation>dompet lalai
-</translation>
- </message>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- </context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Salin Alamat</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Alamat</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>dompet</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(tiada label)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Balance:</source>
- <translation>Baki</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(tiada label)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- </context>
-<context>
- <name>SplashScreen</name>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(tiada label)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Fail dibahagi oleh koma(*.csv)</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Alamat</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Mengeksport Gagal</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>
-Alihkan fail data ke dalam tab semasa</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- </context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_my.ts b/src/qt/locale/bitcoin_my.ts
new file mode 100644
index 0000000000..1b5248ba1a
--- /dev/null
+++ b/src/qt/locale/bitcoin_my.ts
@@ -0,0 +1,166 @@
+<TS language="my" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>လိပ်စာ သို့မဟုတ် ခေါင်းစဉ်တပ်ရန် Right-click နှိပ်ပါ။</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>လိပ်စာအသစ်ယူမယ်။</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;အသစ်</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>လက်ရှိရွေးထားတဲ့ လိပ်စာကို clipboard ပေါ်တင်မယ်။</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;ကူးမယ်</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>လက်ရှိရွေးထားတဲ့ လိပ်စာကို ဖျက်မယ်။</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>လက်ရှိ tab မှာရှိတဲ့ဒေတာတွေကို ဖိုင်လ်မှာသိမ်းမယ်။</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;ထုတ်ယူသိမ်းဆည်း</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;ဖျက်</translation>
+ </message>
+ </context>
+<context>
+ <name>AddressTableModel</name>
+ </context>
+<context>
+ <name>AskPassphraseDialog</name>
+ </context>
+<context>
+ <name>BanTableModel</name>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ </context>
+<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ </context>
+<context>
+ <name>Intro</name>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ </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>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ </context>
+<context>
+ <name>TransactionView</name>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletController</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;ထုတ်ယူသိမ်းဆည်း</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>လက်ရှိ tab မှာရှိတဲ့ဒေတာတွေကို ဖိုင်လ်မှာသိမ်းမယ်။</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts
index a7d0cbbdb2..7119de29ae 100644
--- a/src/qt/locale/bitcoin_nb.ts
+++ b/src/qt/locale/bitcoin_nb.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Høyreklikk for å redigere adresse, eller beskrivelse</translation>
+ <translation>Høyreklikk for å redigere adressen eller beskrivelsen</translation>
</message>
<message>
<source>Create a new address</source>
@@ -338,14 +338,6 @@
<translation>Endre passordsetningen for kryptering av lommeboken</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Feilsøkingsvindu</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Åpne konsoll for feilsøking og diagnostisering</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verifiser meldingen...</translation>
</message>
@@ -406,10 +398,6 @@
<translation>Vis lista over brukte mottakeradresser og merkelapper</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Åpne en bitcoin: URI eller betalingsforespørsel</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Kommandolinjealternativer</translation>
</message>
@@ -832,10 +820,6 @@
<translation>versjon</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation> (%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Om %1</translation>
</message>
@@ -864,11 +848,11 @@
</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>Den initielle synkroniseringen er svært krevende, og kan forårsake problemer med maskinvaren i datamaskinen din som du tidligere ikke merket. Hver gang du kjører %1 vil den fortsette nedlastingen der den sluttet. </translation>
+ <translation>Den initielle synkroniseringen er svært krevende, og kan forårsake problemer med maskinvaren i datamaskinen din som du tidligere ikke merket. Hver gang du kjører %1 vil den fortsette nedlastingen der den sluttet.</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>Hvis du har valgt å begrense blokkjedelagring (beskjæring), må historiske data fortsatt lastes ned og behandles, men de vil bli slettet etterpå for å holde bruken av lagringsplass lav. </translation>
+ <translation>Hvis du har valgt å begrense blokkjedelagring (beskjæring), må historiske data fortsatt lastes ned og behandles, men de vil bli slettet etterpå for å holde bruken av lagringsplass lav.</translation>
</message>
<message>
<source>Use the default data directory</source>
@@ -965,25 +949,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Åpne URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Åpne betalingsetterspørring fra URI eller fil</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Velg fil for betalingsetterspørring</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Velg betalingsforespørselsfil å åpne</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1345,10 +1313,6 @@
<translation>URI-håndtering</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Nettadressen for betalingsforespørselshenting er ugyldig: %1</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>Ugyldig betalingsadresse %1</translation>
</message>
@@ -1360,66 +1324,6 @@
<source>Payment request file handling</source>
<translation>Håndtering av betalingsforespørselsfil</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Betalingsforespørselsfila kan ikke leses! Dette kan ha sitt opphav i at den er ugyldig.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Betalingsforespørsel avslått</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Betalingsforespørselsnettverket samsvarer ikke med klientnettverket.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Tidsavbrudd for betalingsforespørsel</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Betalingsforespørselen er ikke igangsatt.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Uverifiserte betalingsforespørsler til egentilpassede betalingsskript støttes ikke.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Ugyldig betalingsforespørsel.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Forespurt betalingsbeløp på %1 er for lite (betraktet som støv).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Tilbakebetaling fra %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Betalingsforespørsel %1 er for stor (%2 byte, %3 byte tillatt).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Feil under kommunikasjon med %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Betalingsforespørselen kan ikke tolkes!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Feilaktig svar fra tjeneren %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Nettverksforespørselsfeil</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Betaling anerkjent</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1589,10 +1493,6 @@
<translation>&amp;Informasjon</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Feilsøkingsvindu</translation>
- </message>
- <message>
<source>General</source>
<translation>Generelt</translation>
</message>
@@ -2101,10 +2001,6 @@
<translation>Advarsel: Gebyroverslag er ikke tilgjengelig for tiden.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>Legg ned gebyrinnstillinger</translation>
- </message>
- <message>
<source>per kilobyte</source>
<translation>per kilobyte</translation>
</message>
@@ -2150,7 +2046,7 @@
</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>Med Replace-By-Fee (BIP-125) kan du øke transaksjonens gebyr etter at den er sendt. Uten dette aktivert anbefales et høyere gebyr for å kompensere for risikoen for at transaksjonen blir forsinket. </translation>
+ <translation>Med Replace-By-Fee (BIP-125) kan du øke transaksjonens gebyr etter at den er sendt. Uten dette aktivert anbefales et høyere gebyr for å kompensere for risikoen for at transaksjonen blir forsinket.</translation>
</message>
<message>
<source>Clear &amp;All</source>
@@ -2261,10 +2157,6 @@
<translation>Opprettelse av transaksjon mislyktes!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Transaksjonen ble avslått av følgende grunn: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Et gebyr høyere enn %1 anses som absurd høyt.</translation>
</message>
@@ -2316,10 +2208,6 @@
<translation>Velg tidligere brukt adresse</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Dette er en normal betaling.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Bitcoin-adressen betalingen skal sendes til</translation>
</message>
@@ -2379,17 +2267,6 @@
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Skriv inn en merkelapp for denne adressen for å legge den til i din adressebok</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -3114,10 +2991,6 @@
<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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Omsøk er ikke mulig i beskjært modus. Du vil måtte bruke -reindex som vil laste nede hele blokkjeden på nytt.</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>
@@ -3139,7 +3012,7 @@
</message>
<message>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
- <translation>Kan ikke angi spesifikke tilkoblinger og ha addrman til å finne utgående tilkoblinger samtidig. </translation>
+ <translation>Kan ikke angi spesifikke tilkoblinger og ha addrman til å finne utgående tilkoblinger samtidig.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
@@ -3460,10 +3333,6 @@
<translation>Dette er transaksjonsgebyret du kan betale når gebyranslag ikke er tilgjengelige.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Dette produktet inneholder programmet utviklet av OpenSSL-prosjektet for bruk i OpenSSL-verktøyssettet %s og kryptografisk programvare skrevet av Eric Young og UPnP-programvare skrevet av Thomas Bernard.</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 lengde av nettverks-versionstreng (%i) er over maks lengde (%i). Reduser tallet eller størrelsen av uacomments.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ne.ts b/src/qt/locale/bitcoin_ne.ts
index f50d3069da..0a291dd95e 100644
--- a/src/qt/locale/bitcoin_ne.ts
+++ b/src/qt/locale/bitcoin_ne.ts
@@ -31,7 +31,7 @@
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>वर्तमान ट्याबको डाटालाई फाइलमा निर्यात गर्नुहोस् </translation>
+ <translation>वर्तमान ट्याबको डाटालाई फाइलमा निर्यात गर्नुहोस्</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -182,14 +182,6 @@
<source>Change the passphrase used for wallet encryption</source>
<translation>वालेट इन्क्रिप्सनमा प्रयोग हुने इन्क्रिप्सन पासफ्रेज परिवर्तन गर्नुहोस्</translation>
</message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;amp;डिबग विन्डो</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>डिबगिङ र डायाग्नोस्टिक कन्सोल खोल्नुहोस्</translation>
- </message>
</context>
<context>
<name>CoinControlDialog</name>
@@ -363,9 +355,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -442,10 +431,22 @@
<translation>ब्लक डाटाबेसमा भविष्यबाट आए जस्तो देखिने एउटा ब्लक हुन्छ । तपाईंको कम्प्युटरको मिति र समय गलत तरिकाले सेट गरिएकाले यस्तो हुन सक्छ । तपाईं आफ्नो कम्प्युटरको मिति र समय सही छ भनेर पक्का हुनुहुन्छ भने मात्र ब्लक डाटाबेस पुनर्निर्माण गर्नुहोस् ।</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>यो जारी गर्नु पूर्वको परीक्षण संस्करण हो - आफ्नै जोखिममा प्रयोग गर्नुहोस् - खनन वा व्यापारीक प्रयोगको लागि प्रयोग नगर्नुहोस</translation>
+ </message>
+ <message>
<source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
<translation>प्रि-फर्क अवस्थामा डाटाबेस रिवाइन्ड गर्न सकिएन । तपाईंले फेरि ब्लकचेन डाउनलोड गर्नु पर्ने हुन्छ</translation>
</message>
<message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>चेतावनी: नेटवर्क पूरै तरिकाले सहमत छैन जस्तो देखिन्छ! केही खननकर्ताहरूले समस्या भोगिरहेका छन् जस्तो देखिन्छ ।</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>चेतावनी: हामी हाम्रा सहकर्मीहरूसँग पूर्णतया सहमत छैनौं जस्तो देखिन्छ! तपाईंले अपग्रेड गर्नु पर्ने हुनसक्छ वा अरू नोडहरूले अपग्रेड गर्नु पर्ने हुनसक्छ ।</translation>
+ </message>
+ <message>
<source>%s corrupt, salvage failed</source>
<translation>%s मा क्षति, बचाव विफल भयो</translation>
</message>
diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts
index de4b719398..73c18cd4d8 100644
--- a/src/qt/locale/bitcoin_nl.ts
+++ b/src/qt/locale/bitcoin_nl.ts
@@ -180,6 +180,14 @@
<translation>Portemonnee versleuteld</translation>
</message>
<message>
+ <source>Enter the new passphrase for the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Voer de neuwe wachtwoordzin in voor de portemonnee.&lt;br/&gt;Gebruik a.u.b. een wachtwoordzin van &lt;b&gt;tien of meer willekeurige karakters&lt;/b&gt;, of &lt;b&gt;acht of meer woorden&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Voer de oude wachtwoordzin en de nieuwe wachtwoordzin in voor de portemonnee.</translation>
+ </message>
+ <message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
<translation>Onthoud dat het versleutelen van uw portemonnee uw bitcoins niet volledig kan beschermen tegen diefstal, bijvoorbeeld door malware die uw computer infecteert.</translation>
</message>
@@ -319,11 +327,11 @@
</message>
<message>
<source>Create Wallet...</source>
- <translation>Wallet creëren </translation>
+ <translation>Wallet creëren</translation>
</message>
<message>
<source>Create a new wallet</source>
- <translation>Nieuwe wallet creëren </translation>
+ <translation>Nieuwe wallet creëren</translation>
</message>
<message>
<source>Wallet:</source>
@@ -366,14 +374,6 @@
<translation>Wijzig het wachtwoord voor uw portemonneversleuteling</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Debugscherm</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Open debugging en diagnostische console</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verifiëer bericht...</translation>
</message>
@@ -434,10 +434,6 @@
<translation>Toon de lijst met gebruikte ontvangstadressen en labels</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Open een bitcoin: URI of betalingsverzoek</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Opdrachtregelopties</translation>
</message>
@@ -486,6 +482,14 @@
<translation>Bijgewerkt</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Nodevenster</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Open node debugging en diagnostische console</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>Verzendadressen</translation>
</message>
@@ -494,6 +498,10 @@
<translation>Ontvangstadressen</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Open een bitcoin: URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Portemonnee Openen</translation>
</message>
@@ -796,7 +804,7 @@
<name>CreateWalletDialog</name>
<message>
<source>Create Wallet</source>
- <translation>Creëer wallet </translation>
+ <translation>Creëer wallet</translation>
</message>
<message>
<source>Wallet Name</source>
@@ -811,12 +819,25 @@
<translation>Versleutel portemonnee</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>Schakel privésleutels uit voor deze portemonnee. Portommonees met privésleutels uitgeschakeld hebben deze niet en kunnen geen HD seed of geimporteerde privésleutels bevatten.
+Dit is ideaal voor alleen-lezen portommonees.</translation>
+ </message>
+ <message>
<source>Disable Private Keys</source>
<translation>Schakel privésleutels uit</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>Maak een blanco portemonnee. Blanco portemonnees hebben initieel geen privésleutel of scripts. Privésleutels en adressen kunnen later worden geimporteerd of een HD seed kan later ingesteld worden.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Maak een lege portemonnee</translation>
+ </message>
+ <message>
<source>Create</source>
- <translation>Creëer </translation>
+ <translation>Creëer</translation>
</message>
</context>
<context>
@@ -904,10 +925,6 @@
<translation>versie</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Over %1</translation>
</message>
@@ -935,6 +952,10 @@
<translation>Als u op OK klikt, dan zal %1 beginnen met downloaden en verwerken van de volledige %4 blokketen (%2GB) startend met de eerste transacties in %3 toen %4 initeel werd gestart.</translation>
</message>
<message>
+ <source>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>Om deze instelling weer ongedaan te maken moet de volledige blockchain opnieuw gedownload worden. Het is sneller om eerst de volledige blockchain te downloaden en deze later te prunen. Schakelt een aantal geavanceerde functies uit.</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>Deze initiële synchronisatie is heel veeleisend, en kan hardware problemen met uw computer blootleggen die voorheen onopgemerkt bleven. Elke keer dat %1 gebruikt word, zal verdergegaan worden waar gebleven is.</translation>
</message>
@@ -955,6 +976,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Verwijder blokken na verificatie, uitgezonderd de meest recente %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>Tenminste %1 GB aan data zal worden opgeslagen in deze map, en dit zal naarmate de tijd voortschrijdt groeien.</translation>
</message>
@@ -986,7 +1011,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(van %n GB nodig)</numerusform><numerusform>(van %n GB nodig)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB nodig voor volledige keten)</numerusform><numerusform>(%n GB nodig voor volledige keten)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -995,7 +1024,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>Recente transacties zijn mogelijk nog niet zichtbaar. De balans van de portemonnee is daarom mogelijk niet correct. Deze informatie is correct van zodra de synchronisatie met het Bitcoin-netwerk werd voltooid, zoals onderaan beschreven.</translation>
+ <translation>Recente transacties zijn mogelijk nog niet zichtbaar. De balans van de portemonnee is daarom mogelijk niet correct. Deze informatie is correct zodra de synchronisatie met het Bitcoin-netwerk is voltooid, zoals onderaan beschreven.</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
@@ -1027,39 +1056,35 @@
</message>
<message>
<source>Estimated time left until synced</source>
- <translation>Geschatte tijd tot volledig synchroon</translation>
+ <translation>Geschatte tijd tot synchronisatie voltooid</translation>
</message>
<message>
<source>Hide</source>
<translation>Verbergen</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 momenteel aan het synchroniseren. Het zal headers en blocks downloaden van peers en deze valideren tot de top van de block chain bereikt is. </translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
- <translation>Onbekend. Kopteksten synchroniseren (%1, %2%)...</translation>
+ <translation>Onbekend. Blockheaders synchroniseren (%1, %2%)...</translation>
</message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Open URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Open betalingsverzoek via URI of bestand</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Open bitcoin-URI</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Selecteer betalingsverzoek bestand</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Selecteer betalingsverzoekbestand om te openen</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1112,7 +1137,7 @@
</message>
<message>
<source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
- <translation>Toont aan of de aangeleverde standaard SOCKS5 proxy gebruikt word om peers te bereiken via dit netwerktype.</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>
@@ -1132,7 +1157,7 @@
</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>URL's van derden (bijvoorbeeld blokexplorer) die in de transacties tab verschijnen als contextmenuelementen. %s in de URL is vervangen door transactiehash. Verscheidene URL's zijn gescheiden door een verticale streep |. </translation>
+ <translation>URL's van derden (bijvoorbeeld blokexplorer) die in de transacties tab verschijnen als contextmenuelementen. %s in de URL is vervangen door transactiehash. Verscheidene URL's zijn gescheiden door een verticale streep |.</translation>
</message>
<message>
<source>Open the %1 configuration file from the working directory.</source>
@@ -1449,16 +1474,16 @@
<translation>'bitcoin://' is niet een geldige URI. Gebruik 'bitcoin:' in plaats daarvan.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Je gebruikt een BIP70 URL wat in de toekomst niet langer ondersteund zal worden.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>Kan het betalingsverzoek niet verwerken omdat BIP70 niet ondersteund is.</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL om betalingsverzoek te verkrijgen is ongeldig: %1</translation>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Gezien de wijdverspreide beveiligingsproblemen in BIP70 is het sterk aanbevolen dat iedere instructie om van portemonnee te wisselen wordt genegeerd.</translation>
</message>
<message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Kan het betalingsverzoek niet verwerken omdat BIP70 ondersteuning niet werd gecompileerd.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Als je deze fout krijgt, verzoek dan de verkoper om een BIP21 compatible URI.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1472,66 +1497,6 @@
<source>Payment request file handling</source>
<translation>Betalingsverzoek bestandsafhandeling</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Betalingsverzoekbestand kan niet gelezen of verwerkt worden! Dit kan veroorzaakt worden door een ongeldig betalingsverzoekbestand.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Betalingsverzoek geweigerd</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Betalingsaanvraagnetwerk komt niet overeen met klantennetwerk.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Betalingsverzoek verlopen.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Betalingsaanvraag is niet geïnitialiseerd.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Niet-geverifieerde betalingsverzoeken naar aangepaste betalingsscripts worden niet ondersteund.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Ongeldig betalingsverzoek.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Het gevraagde betalingsbedrag van %1 is te weinig (beschouwd als stof).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Restitutie van %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Betalingsverzoek %1 is te groot (%2 bytes, toegestaan ​​%3 bytes).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Fout bij communiceren met %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Betalingsverzoek kan niet worden verwerkt!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Ongeldige respons van server %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Fout bij netwerkverzoek</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Betaling bevestigd</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1709,10 +1674,6 @@
<translation>&amp;Informatie</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Debug venster</translation>
- </message>
- <message>
<source>General</source>
<translation>Algemeen</translation>
</message>
@@ -1833,6 +1794,10 @@
<translation>User Agent</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Nodevenster</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 het %1 debug-logbestand van de huidige gegevensmap. Dit kan een aantal seconden duren voor grote logbestanden.</translation>
</message>
@@ -2044,6 +2009,18 @@
<translation>Een optioneel te verzoeken bedrag. Laat dit leeg, of nul, om geen specifiek bedrag aan te vragen.</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>Een optioneel label om te associëren met het nieuwe ontvangstadres (door u gebruikt om een betalingsverzoek te identificeren). Dit wordt ook toegevoegd aan het betalingsverzoek.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Een optioneel bericht dat wordt toegevoegd aan het betalingsverzoek en dat aan de verzender getoond kan worden.</translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation>&amp;Creëer een nieuw ontvangstadres</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Wis alle velden op het formulier.</translation>
</message>
@@ -2249,10 +2226,6 @@
<translation>Waarschuwing: Schatting van de vergoeding is momenteel niet mogelijk.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>verberg vergoeding-instellingen</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>
@@ -2297,6 +2270,10 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Stof:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Verberg transactiekosteninstellingen</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>De minimale toeslag betalen is prima mits het transactievolume kleiner is dan de ruimte in de blokken. Let wel op dat dit tot gevolg kan hebben dat een transactie nooit wordt bevestigd als er meer vraag is naar bitcointransacties dan het netwerk kan verwerken.</translation>
</message>
@@ -2365,8 +2342,16 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>%1 (%2 blokken)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Cr&amp;eëer Ongetekend</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>Creëert een Partially Signed Bitcoin Transaction (PSBT) om te gebruiken met b.v. een offline %1 wallet, of een PSBT-compatibele hardware wallet.</translation>
+ </message>
+ <message>
<source> from wallet '%1'</source>
- <translation> van portemonnee '%1'</translation>
+ <translation>van portemonnee '%1'</translation>
</message>
<message>
<source>%1 to '%2'</source>
@@ -2377,10 +2362,18 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>%1 tot %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Wil je een transactievoorstel maken? </translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<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>
@@ -2405,10 +2398,34 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Totaalbedrag</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Om de lijst van ontvangers te vernieuwe klik "Bekijk details..."</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Bevestig versturen munten</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Het adres van de ontvanger is niet geldig. Gelieve opnieuw te controleren.</translation>
</message>
@@ -2433,10 +2450,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Transactiecreatie mislukt</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>De transactie werd afgewezen om de volgende reden: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Een vergoeding van meer dan %1 wordt beschouwd als een absurd hoge vergoeding.</translation>
</message>
@@ -2488,10 +2501,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Kies een eerder gebruikt adres</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Dit is een normale betaling.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Het Bitcoinadres om betaling aan te versturen</translation>
</message>
@@ -2512,6 +2521,10 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Verwijder deze toevoeging</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>Het te sturen bedrag in de geselecteerde eenheid</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>De transactiekosten zal worden afgetrokken van het bedrag dat verstuurd wordt. De ontvangers zullen minder bitcoins ontvangen dan ingevoerd is in het hoeveelheidsveld. Als er meerdere ontvangers geselecteerd zijn, dan worden de transactiekosten gelijk verdeeld.</translation>
</message>
@@ -2551,17 +2564,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Vul een label in voor dit adres om het toe te voegen aan uw adresboek</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2649,6 +2651,14 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Het Bitcoinadres waarmee het bericht ondertekend is</translation>
</message>
<message>
+ <source>The signed message to verify</source>
+ <translation>Het te controleren ondertekend bericht</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>De handtekening waarmee het bericht ondertekend werd</translation>
+ </message>
+ <message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
<translation>Controleer een bericht om te verifiëren dat het gespecificeerde Bitcoinadres het bericht heeft ondertekend.</translation>
</message>
@@ -2681,6 +2691,10 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Portemonnee-ontsleuteling is geannuleerd.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Geen fout</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>Geheime sleutel voor het ingevoerde adres is niet beschikbaar.</translation>
</message>
@@ -2855,6 +2869,10 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Output index</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(Certificaat kon niet worden geverifieerd)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Handelaar</translation>
</message>
@@ -3178,8 +3196,12 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Portemonnee Sluiten</translation>
</message>
<message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>Weet je zeker dat je portemonnee &lt;i&gt;%1&lt;/i&gt; wil sluiten?</translation>
+ </message>
+ <message>
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
- <translation>De portemonee te lang gesloten houden kan leiden tot het moeten hersynchroniseren van de hele keten als snoeien aktief is. </translation>
+ <translation>De portemonee te lang gesloten houden kan leiden tot het moeten hersynchroniseren van de hele keten als snoeien aktief is.</translation>
</message>
</context>
<context>
@@ -3208,6 +3230,10 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Wil je de vergoeding verhogen?</translation>
</message>
<message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Wil je een transactievoorstel met een hogere vergoeding maken?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Huidige vergoeding:</translation>
</message>
@@ -3224,6 +3250,14 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Bevestig vergoedingsaanpassing</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>Kan geen transactievoorstel aanmaken.</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT is gekopieerd</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Kan transactie niet ondertekenen.</translation>
</message>
@@ -3290,10 +3324,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Herscannen is niet mogelijk i.c.m. -prune. U moet -reindex gebruiken dat de hele blokketen opnieuw zal downloaden.</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>
@@ -3311,7 +3341,7 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
</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>
+ <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>
@@ -3394,6 +3424,14 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Corrupte blokkendatabase gedetecteerd</translation>
</message>
<message>
+ <source>Could not find asmap file %s</source>
+ <translation>Kan asmapbestand %s niet vinden</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>Kan asmapbestand %s niet lezen</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Wilt u de blokkendatabase nu herbouwen?</translation>
</message>
@@ -3567,7 +3605,7 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
</message>
<message>
<source>Error reading from database, shutting down.</source>
- <translation>Fout bij het lezen van de database, afsluiten. </translation>
+ <translation>Fout bij het lezen van de database, afsluiten.</translation>
</message>
<message>
<source>Error upgrading chainstate database</source>
@@ -3598,6 +3636,10 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Verplicht een poort met -whitebind op te geven: '%s'</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Prune-modus is niet compatible met -blockfilterindex.</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Verminder -maxconnections van %d naar %d, vanwege systeembeperkingen.</translation>
</message>
@@ -3649,13 +3691,17 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
</message>
<message>
<source>Unable to create the PID file '%s': %s</source>
- <translation>Kan de PID file niet creëren. '%s': %s </translation>
+ <translation>Kan de PID file niet creëren. '%s': %s</translation>
</message>
<message>
<source>Unable to generate initial keys</source>
<translation>Niet mogelijk initiële sleutels te genereren</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>Onbekende -blokfilterindexwaarde %s.</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>Portomenee(n) aan het verifiëren...</translation>
</message>
@@ -3676,10 +3722,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Dit is de transactievergoeding die je mogelijk betaalt indien geschatte tarief niet beschikbaar is</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Dit product bevat software dat ontwikkeld is door het OpenSSL Project voor gebruik in de OpenSSL Toolkit %s en cryptografische software geschreven door Eric Young en UPnP software geschreven door Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation>Totale lengte van netwerkversiestring (%i) overschrijdt maximale lengte (%i). Verminder het aantal of grootte van uacomments.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_nl_NL.ts b/src/qt/locale/bitcoin_nl_NL.ts
deleted file mode 100644
index e17b962eca..0000000000
--- a/src/qt/locale/bitcoin_nl_NL.ts
+++ /dev/null
@@ -1,1029 +0,0 @@
-<TS language="nl_NL" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Klik met de rechter muisknop om dit adres of label te veranderen</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Maak een nieuw adres aan</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Nieuw</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Kopieer het geselecteerde adres naar het klembord</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Kopieren</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>S&amp;luiten</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Verwijder het geselecteerde adres uit de lijst</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exporteer de data in dit tab naar een bestand</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exporteer</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Verwijderen</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Selecteer het adres om munten naar toe te sturen.</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Selecteer het adres om munten mee te ontvangen.</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>S&amp;electeren</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Verzendadres</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Ontvangstadres</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>Dit zijn uw Bitcoin adressen voor het versturen van betalingen. Controleer altijd het bedrag en het ontvangstadres voordat u munten verstuurd.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Dit zijn uw Bitcoin adressen voor het ontvangen van betalingen. Het wordt aanbevolen om voor elke transactie een nieuw ontvangstadres te gebruiken.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Adres Kopiëren</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>&amp;Label Kopieren</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Bewerken</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Adreslijst Exporteren</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Komma gescheiden bestand (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Exporteren Mislukt</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Er was een fout bij het opslaan van de adreslijst naar %1. Probeer het opnieuw.</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adres</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(geen label)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Wachtwoord scherm</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Voer wachtwoord in</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Nieuw wachtwoord</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Herhaal nieuw wachtwoord</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Voer je nieuwe wachtwoord in je portemonnee in.&lt;br/&gt;Gebruik een wachtwoord van &lt;b&gt;tien of meer willekeurige karakters&lt;/b&gt;, of &lt;b&gt;acht of meer woorden&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Versleutel portemonnee</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Deze actie heeft je wachtwoord nodig om je portemonnee te ontgrendelen</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Ontgrendel portemonnee</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Deze actie heeft je wachtwoord nodig om je portemonnee te decoderen.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Decodeer portemonnee</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Verander wachtwoord</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Voer het oude en nieuwe wachtwoord in voor de portemonnee.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Bevestig portemonnee versleuteling</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Waarschuwing: Als je je portemonnee versleutelt en je wachtwoord kwijtraakt, raak je &lt;b&gt;AL JE BITCOINS KWIJT&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Weet je zeker dat je je portemonnee wilt versleutelen?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Portemonnee versleuteld</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 zal nu sluiten om het versleutel proces te voltooien. Onthoudt dat het versleutelen van je portemonnee jouw bitcoins niet volledig van diefstal via malware kan beschermen.</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>BELANGRIJK: Alle vorige backups die je hebt gemaakt van het portemonnee bestand moeten vervangen worden door het nieuwe gemaakte versleutelde portemonnee bestand. Voor beveiligingsredenen zullen vorige backups van het niet versleutelde portemonnee bestand niet meer werken zodra je gebruik maakt van de nieuwe versleutelde portemonnee.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Portemonnee versleutelen mislukt</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Portemonnee versleutelen mislukt vanwege een interne fout. Je portemonnee is niet versleuteld.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>De opgegeven wachtwoorden zijn niet identiek.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Portemonnee ontgrendelen mislukt</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Het ingevulde wachtwoord voor het ontsleutelen van de portemonnee is niet correct.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Ontgrendelen van de portemonnee mislukt</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Portemonnee wachtwoord met succes veranderd.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Waarschuwing: Caps Lock staat aan!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmask</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Geblokkeerd Tot</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Signeer &amp;bericht</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Synchroniseren met het netwerk...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Overzicht</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Node</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Toon algemeen overzicht van portemonnee</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transacties</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Door transactiegeschiedenis bladeren</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>Exit</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Applicatie sluiten</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Over %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Toon informatie over %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Over &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Toon informatie over Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Opties...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Configuratieopties aanpassen voor%1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Portemonnee Versleutelen...</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Portemonnee Backuppen</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Wachtwoord Veranderen</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Verzendadressen</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>&amp;Ontvangadressen</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Open &amp;URL...</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Klik om netwerk activiteit uit te zetten.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Netwerk activiteit uitgeschakeld.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Klik om netwerk activiteit aan te zetten.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Headers synchroniseren (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Blokken op schijf herindexeren...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Verstuur coins naar een Bitcoin adres</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Back-up portemonnee naar een andere locatie</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Verander het wachtwoord die gebruikt wordt voor de portemonnee versleuteling</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Debug scherm</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Open debugging en diagnostisch console</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Bericht verifiëren</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Portemonnee</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Versturen</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Ontvangen</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Tonen / Verbergen</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Toon of verberg het hoofd scherm</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Versleutel de privé sleutels die bij je portemonnee horen</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Signeer berichten met je Bitcoin adres om te bewijzen dat ze van jou zijn</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Verifieer berichten om er zeker van te zijn dat ze met specifieke Bitcoin adressen ondertekent zijn</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Bestand</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Instellingen</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Help</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Tabs taakbalk</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Betalingen aanvragen (genereert QR codes en bitcoin: URI's)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Toon de lijst van gebruikte verzend adressen en labels</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Toon de lijst van gebruikte ontvangst adressen en labels</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Open een bitcoin: URI of betaalverzoek</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Commando-regel opties</translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Blokken op schijf indexeren</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Blokken op schijf verwerken</translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 achter</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Laatst ontvangen blok is gegenereert %1 geleden</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Transacties hierna zullen niet zichtbaar zijn.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Fout</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Waarschuwing</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informatie</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Up to date</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Open het %1 help bericht om een lijst met Bitcoin commando-regel opties te krijgen</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>%1 client</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Verbinding maken met peers...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Inhalen...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Datum: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Bedrag: %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>Adres: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Transactie verzonden</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Binnenkomende transactie</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>HD sleutel generatie &lt;b&gt;geactiveerd&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>HD sleutel generatie &lt;b&gt;gedeactiveerd&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>Portemonnee is &lt;b&gt;versleuteld&lt;/b&gt; en op dit moment &lt;b&gt;ontgrendeld&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>Portemonnee is &lt;b&gt;versleuteld&lt;/b&gt; op dit moment &lt;b&gt;vergrendeld&lt;/b&gt;</translation>
- </message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Een fatale error is voorgekomen. Bitcoin kan niet langer veilig verder gaan en sluit daardoor af.</translation>
- </message>
-</context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Coin Selectie</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Hoeveelheid:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Bedrag:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Fooi:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Dust:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Na Fooi:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Wisselgeld:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(de)selecteer alles</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Tree modus</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Lijst modus</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Bedrag</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Ontvangen met label</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Ontvangen met adres</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Bevestigingen</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Bevestigd</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Kopieer adres</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Kopieer label</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopieer bedrag</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Kopieer transactie ID</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Vergrendel niet uitgegeven</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Ontgrendel niet uitgegeven</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Kopieer hoeveelheid</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Kopieer fooi</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Kopieer na fooi</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Kopieer bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Kopieer dust</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Kopieer wisselgeld</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 vergrendeld)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>ja</translation>
- </message>
- <message>
- <source>no</source>
- <translation>nee</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(geen label)</translation>
- </message>
- </context>
-<context>
- <name>EditAddressDialog</name>
- </context>
-<context>
- <name>FreespaceChecker</name>
- </context>
-<context>
- <name>HelpMessageDialog</name>
- </context>
-<context>
- <name>Intro</name>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Fout</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- </context>
-<context>
- <name>OpenURIDialog</name>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Gebruike aparte SOCKS&amp;5 proxy om peers te bereiken via Tor hidden services</translation>
- </message>
- <message>
- <source>Hide the icon from the system tray.</source>
- <translation>Verberg het icoontje van de taakbalk</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Open Configuratie Bestand</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Expert</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Poort mappen met &amp;UPnP</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>Error</source>
- <translation>Fout</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Het ingegeven proxy adres is ongeldig</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Available:</source>
- <translation>Beschikbaar:</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Saldi</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Totaal:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Recente transacties</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- </context>
-<context>
- <name>PeerTableModel</name>
- </context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Bedrag</translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 en %2</translation>
- </message>
- </context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>Copy label</source>
- <translation>Kopieer label</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopieer bedrag</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <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>Wallet</source>
- <translation>Portemonnee</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(geen label)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Quantity:</source>
- <translation>Hoeveelheid:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Bedrag:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Fooi:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Na Fooi:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Wisselgeld:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Dust:</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Kopieer hoeveelheid</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopieer bedrag</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Kopieer fooi</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Kopieer na fooi</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Kopieer bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Kopieer dust</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Kopieer wisselgeld</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(geen label)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- </context>
-<context>
- <name>SplashScreen</name>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Bedrag</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(geen label)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Copy address</source>
- <translation>Kopieer adres</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Kopieer label</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopieer bedrag</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Kopieer transactie ID</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Komma gescheiden bestand (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Bevestigd</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adres</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Exporteren Mislukt</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exporteer</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exporteer de data in dit tab naar een bestand</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Information</source>
- <translation>Informatie</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Waarschuwing</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Fout</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts
index 198dcf7b52..585fa22226 100644
--- a/src/qt/locale/bitcoin_pam.ts
+++ b/src/qt/locale/bitcoin_pam.ts
@@ -37,10 +37,62 @@
<source>&amp;Delete</source>
<translation>&amp;Ilako</translation>
</message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Pilinan ing address a magpadalang coins kang</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Pilinan ing address a tumanggap coins a atin</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>P&amp;ilinan</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Address king pamag-Send</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Address king pamag-Tanggap</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>Reni reng kekang Bitcoin address king pamagpadalang kabayaran. Lawan mulang masalese reng alaga ampo ing address na ning tumanggap bayu ka magpadalang barya.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Kopyan ing address</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Kopyan ing &amp;Label</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Alilan</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Comma separated file (*.csv)</translation>
+ </message>
</context>
<context>
<name>AddressTableModel</name>
- </context>
+ <message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Address</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(alang label)</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
<message>
@@ -59,7 +111,83 @@
<source>Repeat new passphrase</source>
<translation>Pasibayuan ya ing bayung passphrase</translation>
</message>
- </context>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>I-encrypt ye ing wallet</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Ing operasyun a ini kailangan ne ing kekayung wallet passphrase, ban a-unlock ya ing wallet</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Unlock ya ing wallet</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Ing operasyun a ini kailangan ne ing kekang wallet passphrase ban a-decrypt ne ing wallet.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>I-decrypt ya ing wallet</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Alilan ya ing passphrase</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Kumpirman ya ing wallet encryption</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Kapabaluan: Istung in-encrypt me ing kekang wallet at meala ya ing passphrase na, ma-&lt;b&gt;ALA NO NGAN RING KEKANG BITCOINS&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Siguradu na kang buri meng i-encrypt ing kekang wallet?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Me-encrypt ne ing wallet</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>Mayalaga: Reng milabas a backups a gewa mu gamit ing wallet file mu dapat lamung mialilan bayung gawang encrypted wallet file. Para keng seguridad , reng milabas a backups dareng ali maka encrypt a wallet file ma-ala nala istung inumpisan mu nalang gamitan reng bayu, at me encrypt a wallet. </translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Memali ya ing pamag-encrypt king wallet </translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Memali ya ing encryption uli na ning ausan dang internal error. E ya me-encrypt ing wallet yu.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>E la mitutugma ring mibieng passphrase</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Memali ya ing pamag-unlock king wallet </translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>E ya istu ing passphrase a pepalub da para king wallet decryption</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Me-mali ya ing pamag-decrypt king wallet</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Mi-alilan ne ing passphrase na ning wallet.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Kapabaluan: Makabuklat ya ing Caps Lock key!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
</context>
@@ -134,14 +262,6 @@
<translation>Alilan ya ing passphrase a gagamitan para king wallet encryption</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>I-&amp;Debug ing awang</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Ibuklat ing debugging at diagnostic console</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Beripikan ing message...</translation>
</message>
@@ -221,7 +341,11 @@
<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>
- </context>
+ <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>
<name>CoinControlDialog</name>
<message>
@@ -240,6 +364,22 @@
<source>Confirmed</source>
<translation>Me-kumpirma</translation>
</message>
+ <message>
+ <source>Copy address</source>
+ <translation>Kopyan ing address</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopyan ing label</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopyan ing alaga</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(alang label)</translation>
+ </message>
</context>
<context>
<name>CreateWalletActivity</name>
@@ -261,7 +401,31 @@
<source>&amp;Address</source>
<translation>&amp;Address</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Bayung address king pamagpadala</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Alilan ya ing address king pamagpadala</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Alilan ya ing address king pamagpadala</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>Ing pepalub yung address "%1" ali ya katanggap-tanggap a Bitcoin address.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Ali ya bisang mag-unlock ing wallet</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Memali ya ing pamangaua king key</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
</context>
@@ -469,10 +633,6 @@
<translation>&amp;Impormasion</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>I-Debug ing awang</translation>
- </message>
- <message>
<source>Startup time</source>
<translation>Oras ning umpisa</translation>
</message>
@@ -523,7 +683,15 @@
<source>&amp;Label:</source>
<translation>&amp;Label:</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopyan ing label</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopyan ing alaga</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -531,10 +699,22 @@
<translation>&amp;Kopyan ing address</translation>
</message>
<message>
+ <source>Address</source>
+ <translation>Address</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Alaga</translation>
</message>
<message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mensayi</translation>
+ </message>
+ <message>
<source>Wallet</source>
<translation>Wallet</translation>
</message>
@@ -545,6 +725,18 @@
<source>Date</source>
<translation>Kaaldauan</translation>
</message>
+ <message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mensayi</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(alang label)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -589,10 +781,34 @@
<translation>&amp;Ipadala</translation>
</message>
<message>
+ <source>Copy amount</source>
+ <translation>Kopyan ing alaga</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Bayad king Transaksion</translation>
</message>
- </context>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Kumpirman ing pamagpadalang barya</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Ing alaga na ning bayaran dapat mung mas matas ya king 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Ing alaga mipasobra ya king kekang balanse.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>Ing kabuuan mipasobra ya king kekang balanse istung inabe ya ing %1 a bayad king transaksion </translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(alang label)</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
<message>
@@ -629,9 +845,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -700,29 +913,165 @@
<source>Reset all verify message fields</source>
<translation>Ibalik king dati reng ngan fields na ning pamag beripikang mensayi</translation>
</message>
- </context>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>I-click ing "Pirman ing Mensayi" ban agawa ya ing metung a pirma</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>Ing milub a address e ya katanggap-tanggap.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Maliaring pakilawe pasibayu ing address at pasibayuan ya iti.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>Ing milub a address ali ya mag-refer king metung a key.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>Me-kansela ya ing pamag-unlock king wallet.</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>Ing private key para king milub a address, ala ya.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Me-mali ya ing pamag-pirma king mensayi .</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Me-pirman ne ing mensayi.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>Ing pirma ali ya bisang ma-decode.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Maliaring pakilawe pasibayu ing pirma kaibat pasibayuan ya iti.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>Ing pirma ali ya makatugma king message digest.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Me-mali ya ing pamag-beripika king mensayi.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Me-beripika ne ing mensayi.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
</context>
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>Makabuklat anggang %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/ali me-kumpirma</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 kumpirmasion</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Kabilian</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Kaaldauan</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>Pikuanan</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Megawa</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>Menibat</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>e miya balu</translation>
</message>
<message>
+ <source>To</source>
+ <translation>Para kang</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>sariling address</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>label</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Credit</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>ali metanggap</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Debit</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Bayad king Transaksion</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>Alaga dareng eganagana</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mensayi</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Komentu</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Impormasion ning Debug</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transaksion</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Alaga</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>tutu</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>e tutu</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
@@ -736,10 +1085,150 @@
<source>Date</source>
<translation>Kaaldauan</translation>
</message>
- </context>
+ <message>
+ <source>Type</source>
+ <translation>Klase</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>Open until %1</source>
+ <translation>Makabuklat anggang %1</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Me-kumpirma(%1 kumpirmasion)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Me-generate ya oneng ali ya metanggap</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Atanggap kayabe ning</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Atanggap menibat kang</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Mipadala kang</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Kabayaran keka</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Me-mina</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n/a)</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(alang label)</translation>
+ </message>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Status ning Transaksion: Itapat me babo na ning field a ini ban ipakit dala reng bilang dareng me-kumpirma na</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Aldo at oras nung kapilan me tanggap ya ing transaksion</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Klase ning transaksion</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Alagang milako o miragdag king balanse.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Eganagana</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Aldo iti</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Paruminggung iti</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Bulan a iti</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Milabas a bulan</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Banuang iti</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Angganan...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Atanggap kayabe ning</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Mipadala kang</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Keng sarili mu</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Me-mina</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Aliwa</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Pekaditak a alaga</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Kopyan ing address</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopyan ing label</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopyan ing alaga</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Alilan ing label</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Ipakit ing detalye ning transaksion</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Comma separated file (*.csv)</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation>Me-kumpirma</translation>
</message>
@@ -747,7 +1236,31 @@
<source>Date</source>
<translation>Kaaldauan</translation>
</message>
- </context>
+ <message>
+ <source>Type</source>
+ <translation>Klase</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Address</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Angga:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>para kang</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts
index 8fdccce4ef..c09e0d41ac 100644
--- a/src/qt/locale/bitcoin_pl.ts
+++ b/src/qt/locale/bitcoin_pl.ts
@@ -374,14 +374,6 @@
<translation>Zmień hasło użyte do szyfrowania portfela</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Okno debugowania</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Otwórz konsolę debugowania i diagnostyki</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Zweryfikuj wiadomość...</translation>
</message>
@@ -442,10 +434,6 @@
<translation>Pokaż listę adresów i etykiet użytych do odbierania</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Otwórz URI bitcoin: lub żądanie zapłaty</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Opcje linii komend</translation>
</message>
@@ -924,10 +912,6 @@
<translation>wersja</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Informacje o %1</translation>
</message>
@@ -952,7 +936,7 @@
</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>Gdy naciśniesz OK, %1 zacznie się pobieranie i przetwarzanie całego %4 łańcucha bloków (%2GB) zaczynając od najwcześniejszych transakcji w %3 gdy %4 został uruchomiony. </translation>
+ <translation>Gdy naciśniesz OK, %1 zacznie się pobieranie i przetwarzanie całego %4 łańcucha bloków (%2GB) zaczynając od najwcześniejszych transakcji w %3 gdy %4 został uruchomiony.</translation>
</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>
@@ -1031,7 +1015,7 @@
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation>Próba wydania bitcoinów które nie są jeszcze wyświetlone jako transakcja zostanie odrzucona przez sieć. </translation>
+ <translation>Próba wydania bitcoinów które nie są jeszcze wyświetlone jako transakcja zostanie odrzucona przez sieć.</translation>
</message>
<message>
<source>Number of blocks left</source>
@@ -1073,25 +1057,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Otwórz URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Otwórz żądanie zapłaty z URI lub pliku</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Otwórz żądanie zapłaty z pliku</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Wybierz plik żądania zapłaty do otwarcia</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1256,7 +1224,7 @@
</message>
<message>
<source>Proxy &amp;IP:</source>
- <translation>&amp;IP proxy: </translation>
+ <translation>&amp;IP proxy:</translation>
</message>
<message>
<source>&amp;Port:</source>
@@ -1419,7 +1387,7 @@
</message>
<message>
<source>Immature:</source>
- <translation>Niedojrzały: </translation>
+ <translation>Niedojrzały:</translation>
</message>
<message>
<source>Mined balance that has not yet matured</source>
@@ -1439,7 +1407,7 @@
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>Twoje obecne saldo na podglądanym adresie </translation>
+ <translation>Twoje obecne saldo na podglądanym adresie</translation>
</message>
<message>
<source>Spendable:</source>
@@ -1481,18 +1449,6 @@
<translation>'bitcoin://' nie jest poprawnym URI. Użyj 'bitcoin:'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Używasz URL w formacie BIP70, który wkrótce nie będzie wspierany.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL pobrania żądania zapłaty jest nieprawidłowy: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Nie mogę obsłużyć żądania zapłaty ponieważ wsparcie dla BIP70 nie zostało skompilowane. </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>Z powodu znanych błędów bezpieczeństwa w BIP70 zaleca się ignorować wszelkie polecenie od sprzedawcy dotyczące zmiany portfela.</translation>
</message>
@@ -1512,66 +1468,6 @@
<source>Payment request file handling</source>
<translation>Przechwytywanie plików żądania płatności</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Plik z żądaniem płatności nie mógł zostać otwarty. Może być to spowodowane nieprawidłowym plikiem.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Żądanie płatności odrzucone</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Sieć żądania zapłaty nie odpowiada sieci klienta.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Żądanie płatności upłynęło.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Żądanie płatności nie jest zainicjowane.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Niezweryfikowane żądania płatności do własnych skryptów płatności są niewspierane.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Nieprawidłowe żądanie płatności</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Żądana kwota %1 jest za niska (uznano za kurz).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Zwrot z %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Żądanie płatności %1 jest zbyt duże (%2 bajtów, dozwolone %3 bajtów).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Błąd komunikacji z %1 : %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Żądanie płatności nie może zostać przetworzone.</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Błędna odpowiedź z serwera %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Błąd żądania sieci</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Płatność potwierdzona</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1749,16 +1645,12 @@
<translation>&amp;Informacje</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Okno debugowania</translation>
- </message>
- <message>
<source>General</source>
<translation>Ogólne</translation>
</message>
<message>
<source>Using BerkeleyDB version</source>
- <translation>Używana wersja BerkeleyDB </translation>
+ <translation>Używana wersja BerkeleyDB</translation>
</message>
<message>
<source>Datadir</source>
@@ -2270,7 +2162,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>Kiedy ta opcja jest wybrana, to jeżeli adres reszty jest pusty lub nieprawidłowy, to reszta będzie wysyłana na nowo wygenerowany adres, </translation>
+ <translation>Kiedy ta opcja jest wybrana, to jeżeli adres reszty jest pusty lub nieprawidłowy, to reszta będzie wysyłana na nowo wygenerowany adres,</translation>
</message>
<message>
<source>Custom change address</source>
@@ -2294,10 +2186,6 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
<translation>Uwaga: Oszacowanie opłaty za transakcje jest aktualnie niemożliwe.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>zwiń opcje opłaty</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>
@@ -2482,10 +2370,6 @@ Uwaga: Ponieważ opłata jest naliczana za każdy bajt, opłata "100 satoshi za
<translation>Utworzenie transakcji nie powiodło się!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Transakcja została odrzucona z następującym powodem: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Opłata wyższa niż %1 jest uznawana za absurdalnie dużą.</translation>
</message>
@@ -2537,10 +2421,6 @@ Uwaga: Ponieważ opłata jest naliczana za każdy bajt, opłata "100 satoshi za
<translation>Wybierz wcześniej użyty adres</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>To jest standardowa płatność</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Adres Bitcoin gdzie wysłać płatność</translation>
</message>
@@ -2600,17 +2480,6 @@ Uwaga: Ponieważ opłata jest naliczana za każdy bajt, opłata "100 satoshi za
<source>Memo:</source>
<translation>Notatka:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Wprowadź etykietę dla tego adresu by dodać go do książki adresowej</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Tak</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2692,7 +2561,7 @@ Uwaga: Ponieważ opłata jest naliczana za każdy bajt, opłata "100 satoshi za
<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>Wpisz adres, wiadomość oraz sygnaturę (podpis) odbiorcy (upewnij się, że dokładnie skopiujesz wszystkie zakończenia linii, spacje, tabulacje itp.). Uważaj by nie dodać więcej do podpisu niż do samej podpisywanej wiadomości by uniknąć ataku man-in-the-middle.
-Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadawca posiada klucz do adresu, natomiast nie potwierdza to, że poprawne wysłanie jakiejkolwiek transakcji! </translation>
+Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadawca posiada klucz do adresu, natomiast nie potwierdza to, że poprawne wysłanie jakiejkolwiek transakcji!</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
@@ -2905,6 +2774,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Indeks wyjściowy</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(Certyfikat nie został zweryfikowany)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Kupiec</translation>
</message>
@@ -3344,10 +3217,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Ponowne skanowanie nie jest możliwe w trybie przycinania. Będzie trzeba użyć -reindex, co pobierze ponownie cały łańcuch bloków.</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>
@@ -3550,7 +3419,7 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
</message>
<message>
<source>Not enough file descriptors available.</source>
- <translation>Brak wystarczającej liczby deskryptorów plików. </translation>
+ <translation>Brak wystarczającej liczby deskryptorów plików.</translation>
</message>
<message>
<source>Prune cannot be configured with a negative value.</source>
@@ -3696,7 +3565,7 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
</message>
<message>
<source>Transaction amount too small</source>
- <translation>Zbyt niska kwota transakcji </translation>
+ <translation>Zbyt niska kwota transakcji</translation>
</message>
<message>
<source>Transaction too large</source>
@@ -3739,10 +3608,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>To jest opłata transakcyjna którą zapłacisz, gdy mechanizmy estymacji opłaty nie są dostępne.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Produkt zawiera oprogramowanie stworzone przez OpenSSL Project do użycia w OpensSSL Toolkit %s, oprogramowanie kryptograficzne napisane przez Eric Young oraz oprogramowanie UPnP napisane przez Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation>Całkowita długość łańcucha wersji (%i) przekracza maksymalną dopuszczalną długość (%i). Zmniejsz ilość lub rozmiar parametru uacomment.</translation>
</message>
@@ -3772,7 +3637,7 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
</message>
<message>
<source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>To jest opłata transakcyjna którą zapłacisz jeśli wyślesz transakcję. </translation>
+ <translation>To jest opłata transakcyjna którą zapłacisz jeśli wyślesz transakcję.</translation>
</message>
<message>
<source>Transaction amounts must not be negative</source>
diff --git a/src/qt/locale/bitcoin_pt.ts b/src/qt/locale/bitcoin_pt.ts
index 3dceb77124..9fc9170501 100644
--- a/src/qt/locale/bitcoin_pt.ts
+++ b/src/qt/locale/bitcoin_pt.ts
@@ -70,6 +70,10 @@
<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>
@@ -132,6 +136,10 @@
<translation>Repita a nova frase de frase de segurança</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Mostrar Password</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Encriptar carteira</translation>
</message>
@@ -172,6 +180,30 @@
<translation>Carteira 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>Insira nova password para a carteira.&lt;br/&gt;Por favor use uma password de &lt;b&gt;dez ou mais caracteres&lt;/b&gt;, ou &lt;b&gt;oito ou mais palavras&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Insira a password antiga e a nova para a carteira.</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>Lembra se que encrostar a sua carteira não o pode defender na totalidade os seus bitcoins de serem roubados por um malware que possa infectar o seu computador.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Carteira a ser encriptada</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>A sua carteira vai agora ser encriptada.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>A sua carteira está agora encriptada</translation>
+ </message>
+ <message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
<translation>IMPORTANTE: qualquer cópia de segurança da carteira anterior deverá ser substituída com o novo ficheiro de carteira, agora encriptado. Por razões de segurança, as cópias de segurança não encriptadas tornar-se-ão inúteis assim que começar a usar a nova carteira encriptada.</translation>
</message>
@@ -294,6 +326,14 @@
<translation>Abrir &amp;URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Criar Carteira...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Criar novo carteira</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Carteira:</translation>
</message>
@@ -334,14 +374,6 @@
<translation>Alterar a frase de segurança utilizada na encriptação da carteira</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Janela de &amp;Depuração</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abrir consola de diagnóstico e depuração</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verificar mensagem...</translation>
</message>
@@ -402,10 +434,6 @@
<translation>Mostrar a lista de etiquetas e endereços de receção usados</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abrir URI bitcoin: ou pedido de pagamento</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Opções da linha de &amp;comando</translation>
</message>
@@ -454,6 +482,14 @@
<translation>Atualizado</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Janela do nó</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Abrir o depurador de nó e o console de diagnóstico</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>&amp;Endereço de envio</translation>
</message>
@@ -462,6 +498,10 @@
<translation>&amp;Endereços de receção</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Abrir um bitcoin URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Abrir Carteira</translation>
</message>
@@ -522,6 +562,10 @@
<translation>Erro: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Aviso: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Data: %1
@@ -743,10 +787,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>A criar carteira &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Falha a criar carteira</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Aviso ao criar carteira</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Criar Carteira</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Nome da Carteira</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>Encriptar carteira. A carteira vai ser encriptada com uma password de sua escolha.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Encriptar Carteira</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>Desative chaves privadas para esta carteira. As carteiras com chaves privadas desativadas não terão chaves privadas e não poderão ter uma semente em HD ou chaves privadas importadas. Isso é ideal para carteiras sem movimentos.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>Desactivar Chaves 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>Faça uma carteira em branco. As carteiras em branco não possuem inicialmente chaves ou scripts privados. Chaves e endereços privados podem ser importados ou uma semente HD pode ser configurada posteriormente.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Fazer Carteira em Branco</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Criar</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -832,10 +924,6 @@
<translation>versão</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Sobre o %1</translation>
</message>
@@ -863,8 +951,12 @@
<translation>Quando clicar OK, %1 vai começar a descarregar e processar a cadeia de blocos %4 completa (%2GB) começando com as transações mais antigas em %3 quando a %4 foi inicialmente lançada.</translation>
</message>
<message>
+ <source>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>Para reverter essa configuração, é necessário o download de todo o blockchain novamente. É mais rápido fazer o download da blockchain completa primeiro e removê-la mais tarde. Desativa alguns recursos avançados.</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>Esta sincronização inicial é muito exigente, e pode expor problemas com o seu computador que previamente podem ter passado despercebidos. Cada vez que corre %1, este vai continuar a descarregar de onde deixou. </translation>
+ <translation>Esta sincronização inicial é muito exigente, e pode expor problemas com o seu computador que previamente podem ter passado despercebidos. Cada vez que corre %1, este vai continuar a descarregar de onde deixou.</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>
@@ -883,12 +975,16 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Descartar blocos após a verificação, excepto os mais recentes %1 GB (apagar)</translation>
+ </message>
+ <message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation>No mínimo %1 GB de dados irão ser armazenados nesta pasta. </translation>
+ <translation>No mínimo %1 GB de dados irão ser armazenados nesta pasta.</translation>
</message>
<message>
<source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>Aproximadamente %1 GB de dados irão ser guardados nesta pasta. </translation>
+ <translation>Aproximadamente %1 GB de dados irão ser guardados nesta pasta.</translation>
</message>
<message>
<source>%1 will download and store a copy of the Bitcoin block chain.</source>
@@ -914,7 +1010,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(de %n GB necessários)</numerusform><numerusform>(de %n GB necessário)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB precisos para a cadeia completa)</numerusform><numerusform>(%n GB precisos para a cadeia completa)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -962,6 +1062,14 @@
<translation>Ocultar</translation>
</message>
<message>
+ <source>Esc</source>
+ <translation>Sair</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 está no momento sincronizando. Ela irá baixar os cabecários e blocos dos pares e validá-los até atingir a ponta da cadeia de blocos.</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>Desconhecido. A sincronizar cabeçalhos (%1, %2%)...</translation>
</message>
@@ -969,28 +1077,24 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Abir URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Abrir pedido de pagamento de um URI ou ficheiro</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Abrir um bitcoin URI</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Selecione o ficheiro de pedido de pagamento</translation>
+ <source>Open wallet failed</source>
+ <translation>Falha ao abrir a carteira</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Selecione o ficheiro de pedido de pagamento para abrir</translation>
+ <source>Open wallet warning</source>
+ <translation>Aviso abertura carteira</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>carteira predefinida</translation>
@@ -1032,7 +1136,7 @@
</message>
<message>
<source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
- <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>
+ <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>
@@ -1105,7 +1209,7 @@
</message>
<message>
<source>Expert</source>
- <translation> Técnicos</translation>
+ <translation>Técnicos</translation>
</message>
<message>
<source>Enable coin &amp;control features</source>
@@ -1257,7 +1361,7 @@
</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>O ficheiro de configuração é usado para especificar opções de utilizador avançado, que sobrescrevem as configurações do interface gráfico. Adicionalmente, qualquer opção da linha de comandos vai sobrescrever este ficheiro de configuração. </translation>
+ <translation>O ficheiro de configuração é usado para especificar opções de utilizador avançado, que sobrescrevem as configurações do interface gráfico. Adicionalmente, qualquer opção da linha de comandos vai sobrescrever este ficheiro de configuração.</translation>
</message>
<message>
<source>Error</source>
@@ -1273,7 +1377,7 @@
</message>
<message>
<source>The supplied proxy address is invalid.</source>
- <translation>O endereço de proxy introduzido é inválido. </translation>
+ <translation>O endereço de proxy introduzido é inválido.</translation>
</message>
</context>
<context>
@@ -1370,16 +1474,16 @@
<translation>'bitcoin://' não é um URI válido. Utilize 'bitcoin:'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Está a usar uma URL do BIP70 que será desativado no futuro.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>O pagamento requerido não pode ser processado porque BIP70 não é suportado.</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>O URL do pedido de pagamento é inválido: %1</translation>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Devido a falhas de segurança generalizadas no BIP70, é altamente recomendável que todas as instruções do comerciante para trocar carteiras sejam ignoradas.</translation>
</message>
<message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>O pagamento não pode ser processado porque o suporte ao BIP70 foi desativado.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Se está a receber este erro, deve pedir ao comerciante que lhe de um ULR compatível com BIP21.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1393,66 +1497,6 @@
<source>Payment request file handling</source>
<translation>Controlo de pedidos de pagamento.</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>O ficheiro de pedido de pagamento não pôde ser lido! Isto pode ter sido causado por um ficheiro de pedido de pagamento inválido.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Pedido de pagamento rejeitado</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Rede de requisição de pagamento não corresponde com a rede do cliente.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Pedido de pagamento expirado.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>O pedido de pagamento não foi inicializado.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Pedidos de pagamento não-verificados para scripts de pagamento personalizados não são suportados.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Pedido de pagamento inválido.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Quantia solicitada para pagamento de %1 é muito pequena (considerada "pó").</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Reembolso de %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Pedido de pagamento %1 é demasiado grande (%2 bytes, permitido %3 bytes).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Erro ao comunicar com %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>O pedido de pagamento não pode ser lido ou processado!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Má resposta do servidor %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Erro de pedido de rede</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Pagamento confirmado</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1603,6 +1647,10 @@
<translation>Erro ao codificar URI em Código QR.</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>Suporte códigos QR não disponível</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>Guardar o código QR</translation>
</message>
@@ -1626,10 +1674,6 @@
<translation>&amp;Informação</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Janela de depuração</translation>
- </message>
- <message>
<source>General</source>
<translation>Geral</translation>
</message>
@@ -1750,6 +1794,10 @@
<translation>User Agent</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Janela do nó</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 ficheiro de registo de depuração %1 da pasta de dados atual. Isto pode demorar alguns segundos para ficheiros de registo maiores.</translation>
</message>
@@ -1961,6 +2009,18 @@
<translation>Uma quantia opcional a solicitar. Deixe em branco ou zero para não solicitar uma quantidade específica.</translation>
</message>
<message>
+ <source>An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</source>
+ <translation>Um legenda opcional para associar com o novo endereço de recebimento (usado por você para identificar uma fatura). Ela é também anexada ao pedido de pagamento.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Uma mensagem opicional que é anexada ao pedido de pagamento e pode ser mostrada para o remetente.</translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation>&amp;Criar novo endereço para receber</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Limpar todos os campos do formulário.</translation>
</message>
@@ -2076,7 +2136,7 @@
</message>
<message>
<source>Message</source>
- <translation>Mensagem </translation>
+ <translation>Mensagem</translation>
</message>
<message>
<source>(no label)</source>
@@ -2166,10 +2226,6 @@
<translation>Aviso: atualmente, não é possível a estimativa da taxa.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>ocultar configurações de taxa</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>
@@ -2214,6 +2270,10 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Lixo:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Esconder configurações de taxas de transação</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>Quando o volume de transações é maior que o espaço nos blocos, os mineradores, bem como os nós de retransmissão, podem impor uma taxa mínima. Pagar apenas esta taxa mínima é muito bom, mas esteja ciente que isso pode resultar numa transação nunca confirmada, uma vez que há mais pedidos para transações do que a rede pode processar.</translation>
</message>
@@ -2282,14 +2342,38 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>%1 (%2 blocos)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Criar não assinado</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>Cria uma transação de Bitcoin parcialmente assinada (PSBT)(sigla em inglês) para ser usada por exemplo com uma carteira %1 offline ou uma carteira de hardware compatível com PSBT.</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation>da carteira '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 a '%2'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 para %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Você quer simular esta transação?</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<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>
+ </message>
+ <message>
<source>or</source>
<translation>ou</translation>
</message>
@@ -2314,10 +2398,34 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Valor Total</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Para rever a lista de destinatários clique "Mostrar Detalhes..."</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirme envio de moedas</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>O endereço do destinatário é inválido. Por favor, reverifique.</translation>
</message>
@@ -2342,11 +2450,6 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>A criação da transação falhou!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>A transação foi rejeitada pelo seguinte motivo: %1
-</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Uma taxa superior a %1 é considerada uma taxa altamente absurda.</translation>
</message>
@@ -2398,10 +2501,6 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Escolha o endereço utilizado anteriormente</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Este é um pagamento normal.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>O endereço Bitcoin para enviar o pagamento</translation>
</message>
@@ -2422,6 +2521,10 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Remover esta entrada</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>A quantidade para enviar na unidade selecionada</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>A taxa será deduzida ao valor que está a ser enviado. O destinatário irá receber menos bitcoins do que as que inseridas no campo do valor. Se estiverem selecionados múltiplos destinatários, a taxa será repartida equitativamente.</translation>
</message>
@@ -2461,17 +2564,6 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<source>Memo:</source>
<translation>Memorando:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Digite uma etiqueta para este endereço para adicioná-lo ao seu livro de endereços.</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Sim</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2559,6 +2651,14 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>O endereço Bitcoin com que a mensagem foi designada</translation>
</message>
<message>
+ <source>The signed message to verify</source>
+ <translation>A mensagem assinada para verificar</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>A assinatura dada quando a mensagem foi assinada</translation>
+ </message>
+ <message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
<translation>Verifique a mensagem para assegurar que foi assinada com o endereço Bitcoin especificado</translation>
</message>
@@ -2591,6 +2691,10 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>O desbloqueio da carteira foi cancelado.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Sem erro</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>A chave privada para o endereço introduzido não está disponível.</translation>
</message>
@@ -2765,6 +2869,10 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Índex de saída</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation> (O certificado não foi verificado)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Comerciante</translation>
</message>
@@ -3088,6 +3196,10 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Fechar a carteira</translation>
</message>
<message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>Tem a certeza que deseja fechar esta carteira &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>Fechar a carteira durante demasiado tempo pode resultar em ter de resincronizar a cadeia inteira se pruning estiver ativado.</translation>
</message>
@@ -3118,6 +3230,10 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Quer aumentar a taxa?</translation>
</message>
<message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Você quer simular uma transação com aumento da taxa?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Taxa atual:</translation>
</message>
@@ -3134,6 +3250,14 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Confirme aumento de taxa</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>Não foi possível simular a transação.</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT copiado</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Não é possível assinar a transação.</translation>
</message>
@@ -3200,10 +3324,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Reanálises não são possíveis em modo poda. Terá de utilizar -reindex que irá descarregar novamente a cadeia de blocos completa</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>
@@ -3261,7 +3381,7 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
</message>
<message>
<source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
- <translation>Não é possível rebobinar a base de dados para um estado antes da divisão da cadeia de blocos. Necessita descarregar novamente a cadeia de blocos </translation>
+ <translation>Não é possível rebobinar a base de dados para um estado antes da divisão da cadeia de blocos. Necessita descarregar novamente a cadeia de blocos</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -3304,6 +3424,14 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Detetada cadeia de blocos corrompida</translation>
</message>
<message>
+ <source>Could not find asmap file %s</source>
+ <translation>Não foi possível achar o arquivo asmap %s</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>Não foi possível analisar o arquivo asmap %s.</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Deseja reconstruir agora a base de dados de blocos.</translation>
</message>
@@ -3360,6 +3488,10 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Verificação de integridade inicial falhou. O %s está a desligar-se.</translation>
</message>
<message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Permissões P2P inválidas : '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
<translation>Valor inválido para -%s=&lt;amount&gt;: '%s'</translation>
</message>
@@ -3377,6 +3509,14 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
A pasta de blocos especificados "%s" não existe.</translation>
</message>
<message>
+ <source>Unknown address type '%s'</source>
+ <translation>Tipo de endereço desconhecido '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation>Tipo de mudança desconhecido '%s'</translation>
+ </message>
+ <message>
<source>Upgrading txindex database</source>
<translation>A atualizar a base de dados txindex</translation>
</message>
@@ -3385,6 +3525,10 @@ 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>
@@ -3493,6 +3637,10 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>Necessário especificar uma porta com -whitebind: '%s'</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>O modo de remoção é incompatível com -blockfilterindex.</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reduzindo -maxconnections de %d para %d, devido a limitações no sistema.</translation>
</message>
@@ -3551,6 +3699,10 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>Incapaz de gerar as chaves iniciais</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>Desconhecido -blockfilterindex valor %s.</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>A verificar a(s) carteira(s)...</translation>
</message>
@@ -3571,10 +3723,6 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>Esta é a taxa de transação que poderá pagar quando as estimativas da taxa não estão disponíveis.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Este produto inclui software desenvolvido pelo Projeto de OpenSSL para utilização no OpenSSL Toolkit %s e software criptográfico escrito por Eric Young e software UPnP escrito por Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts
index 8974c4148c..b4ae9eeee5 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>Clique com o botão direito para editar o endereço ou rótulo</translation>
</message>
<message>
<source>Create a new address</source>
@@ -70,6 +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>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;Copiar endereço</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Repita a nova frase de segurança</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Exibir senha</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Criptografar carteira</translation>
</message>
@@ -172,10 +180,30 @@
<translation>Carteira criptografada</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>Digite a nova senha para a carteira.&lt;br/&gt;Use uma senha de &lt;b&gt;10 ou mais caracteres randômicos&lt;/b&gt;, ou &lt;b&gt;8 ou mais palavras&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Digite a senha antiga e a nova senha para a carteira</translation>
+ </message>
+ <message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
<translation>Lembre-se que sua carteira criptografada não poderá proteger totalmente os seus bitcoins de serem roubados por softwares maldosos que infectem seu computador.</translation>
</message>
<message>
+ <source>Wallet to be encrypted</source>
+ <translation>Carteira para ser criptografada</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Sua carteira está prestes a ser encriptada.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Sua carteira agora está criptografada.</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: Qualquer backup prévio que você tenha feito da sua carteira deve ser substituído pelo novo e encriptado arquivo gerado. Por razões de segurança, qualquer backup do arquivo não criptografado se tornará inútil assim que você começar a usar uma nova carteira criptografada.</translation>
</message>
@@ -298,6 +326,14 @@
<translation>Abrir &amp;URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Criar Carteira...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Criar uma nova carteira</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Carteira:</translation>
</message>
@@ -338,14 +374,6 @@
<translation>Mudar a frase de segurança utilizada na criptografia da carteira</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Janela de &amp;depuração</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abrir console de depuração e diagnóstico</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verificar mensagem...</translation>
</message>
@@ -406,10 +434,6 @@
<translation>Mostrar a lista de endereços de recebimento usados ​​e rótulos</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abrir um bitcoin: URI ou cobrança</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Opções de linha de &amp;comando</translation>
</message>
@@ -458,6 +482,14 @@
<translation>Atualizado</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Janela do Nó</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Abrir console de diagnóstico e depuração de Nó</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>Endereços de &amp;envio</translation>
</message>
@@ -466,6 +498,10 @@
<translation>Endereço de &amp;recebimento</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Abrir um bitcoin: URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Abrir carteira</translation>
</message>
@@ -526,6 +562,10 @@
<translation>Erro: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Alerta: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Data: %1
@@ -650,7 +690,7 @@
</message>
<message>
<source>Received with address</source>
- <translation>Endereço </translation>
+ <translation>Endereço</translation>
</message>
<message>
<source>Date</source>
@@ -747,10 +787,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Criando Carteira &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Criar carteira falhou</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Criar carteira alerta</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Criar Carteira</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Nome da Carteira</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>Criptografar a carteira. A carteira será criptografada com uma senha de sua escolha.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Criptografar Carteira</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>Desabilitar chaves privadas para esta carteira. Carteiras com chaves privadas desabilitadas não terão chaves privadas e não podem receber importação de palavras "seed" HD ou importação de chaves privadas. Isso é ideal para carteiras apenas de consulta.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>Desabilitar Chaves 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>Criar uma carteira vazia. Carteiras vazias não possuem inicialmente chaves privadas ou scripts. Chaves privadas ou endereços podem ser importados, ou um conjunto de palavras "seed HD" pode ser definidos, posteriormente.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Criar Carteira Vazia</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Criar</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -836,10 +924,6 @@
<translation>versão</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Sobre %1</translation>
</message>
@@ -867,6 +951,10 @@
<translation>Quando você clica OK, %1 vai começar a baixar e processar todos os %4 da block chain (%2GB) começando com a mais recente transação em %3 quando %4 inicialmente foi lançado.</translation>
</message>
<message>
+ <source>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>Reverter essa configuração requer o re-download de todo o blockchain. É mais rápido fazer o download de todo o blockchain primeiro e depois fazer prune. Essa opção desabilita algumas funcionalidades avançadas.</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>Esta sincronização inicial é muito exigente e pode expor problemas de hardware com o computador que passaram despercebidos anteriormente. Cada vez que você executar o %1, irá continuar baixando de onde parou.</translation>
</message>
@@ -887,6 +975,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Descartar os blocos após verificação, exceto os mais recentes %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>No mínimo %1 GB de dados serão armazenados neste diretório, e isso irá crescer com o tempo.</translation>
</message>
@@ -918,7 +1010,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(de %n GB necessário)</numerusform><numerusform>(de %n GB necessário)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB necessário para o blockchain completo)</numerusform><numerusform>(%n GB necessário para o blockchain completo)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -966,6 +1062,14 @@
<translation>Ocultar</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 esta sincronizando. irá baixar e validar uma cópia dos Cabeçalhos e Blocos dos Pares até que alcance o final do block chain.</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>Desconhecido. Sincronizando cabeçalhos (%1, %2%)...</translation>
</message>
@@ -973,28 +1077,24 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Abrir URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Abrir requisição de cobrança por URI ou arquivo</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Abrir um bitcoin URI</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Selecione o arquivo de cobrança</translation>
+ <source>Open wallet failed</source>
+ <translation>Abrir carteira falhou</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Selecione o arquivo de cobrança para ser aberto</translation>
+ <source>Open wallet warning</source>
+ <translation>Abrir carteira alerta</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>carteira padrão</translation>
@@ -1040,7 +1140,7 @@
</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>
+ <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>
@@ -1335,7 +1435,7 @@
</message>
<message>
<source>Spendable:</source>
- <translation>Disponível: </translation>
+ <translation>Disponível:</translation>
</message>
<message>
<source>Recent transactions</source>
@@ -1373,16 +1473,16 @@
<translation>'bitcoin://' não é um URI válido. Use 'bitcoin:'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Você está usando uma URL do BIP70 que será desativado no futuro.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>O pagamento não pode ser processado porque a BIP70 não é suportada.</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL de cobrança é inválida: %1</translation>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Devido a falha de segurança divulgada no BIP70 é fortemente recomendado que qualquer instrução para comerciantes para mudar de carteira seja ignorado</translation>
</message>
<message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>O pagamento não pode ser processado porque o suporte ao BIP70 foi desativado.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Se você está recebendo este erro você deve requisitar ao comerciante oferecer uma URI compatível com o BIP21.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1396,66 +1496,6 @@
<source>Payment request file handling</source>
<translation>Manipulação de arquivo de cobrança</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Arquivo de pedido de pagamento não pode ser lido! Isto pode ser causado por uma requisição de pagamento inválida.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Pedido de pagamento rejeitado</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Rede do pedido de pagamento não corresponde à rede do cliente.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Pedido de pagamento expirado.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Pedido de pagamento não inicializado.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Pedidos de pagamento não verificados para scripts de pagamento personalizados não são suportados.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Pedido de pagamento inválido</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Valor do pagamento solicitado de %1 é muito pequeno (considerado poeira).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Reembolso de %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Pedido de pagamento %1 é muito grande (%2 bytes, permitido %3 bytes).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Erro na comunicação com %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Pedido de pagamento não pode ser analisado!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Erro na resposta do servidor: %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Erro de solicitação de rede</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Pagamento reconhecido</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1606,6 +1646,10 @@
<translation>Erro ao codificar o URI em código QR</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>Suporte a QR code não disponível</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>Salvar código QR</translation>
</message>
@@ -1629,10 +1673,6 @@
<translation>&amp;Informação</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Janela de depuração</translation>
- </message>
- <message>
<source>General</source>
<translation>Geral</translation>
</message>
@@ -1753,6 +1793,10 @@
<translation>User Agent</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Janela do Nó</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>
@@ -1774,7 +1818,7 @@
</message>
<message>
<source>Connection Time</source>
- <translation>Tempo de conexão </translation>
+ <translation>Tempo de conexão</translation>
</message>
<message>
<source>Last Send</source>
@@ -1964,6 +2008,18 @@
<translation>Uma quantia opcional para cobrar. Deixe vazio ou zero para não cobrar uma quantia específica.</translation>
</message>
<message>
+ <source>An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</source>
+ <translation>Um rótulo opcional para associar ao novo endereço de recebimento (usado por você para identificar uma solicitação de pagamento). Que também será adicionado a solicitação de pagamento.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Uma mensagem opcional que será anexada na cobrança e será mostrada ao remetente. </translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation>&amp;Criar novo endereço de recebimento</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Limpa todos os campos do formulário.</translation>
</message>
@@ -2154,7 +2210,7 @@
</message>
<message>
<source>Transaction Fee:</source>
- <translation>Taxa de transação: </translation>
+ <translation>Taxa de transação:</translation>
</message>
<message>
<source>Choose...</source>
@@ -2169,10 +2225,6 @@
<translation>Atenção: Estimativa de taxa não disponível no momento</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>Ocultar painel</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>
@@ -2217,6 +2269,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Poeira:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Ocultar preferências para Taxas de Transação</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>Quando o volume de transações é maior que o espaço nos blocos, os mineradores, bem como os nós de retransmissão, podem impor uma taxa mínima. Pagando apenas esta taxa mínima é muito bom, mas esteja ciente de que isso pode resultar em uma transação nunca confirmada, uma vez que há mais demanda por transações do que a rede pode processar.</translation>
</message>
@@ -2285,14 +2341,38 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>%1 (%2 blocos)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Cr&amp;iar Não Assinado</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>Cria uma Transação de Bitcoin Parcialmente Assinada (PSBT) para usar com ex: uma carteira %1 offline, ou uma PSBT-compatível hardware wallet.</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation>da carteira '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 para '%2'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 a %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Você quer um rascunho dessa transação?</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<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>
+ </message>
+ <message>
<source>or</source>
<translation>ou</translation>
</message>
@@ -2317,10 +2397,34 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Valor total</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Para revisar a lista de destinatários click "Exibir Detalhes..."</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirme o envio de moedas</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Endereço de envio inváido. Favor checar.</translation>
</message>
@@ -2345,10 +2449,6 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Falha na criação da transação!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>A transação foi rejeitada com a seguinte razão: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Uma taxa maior que %1 é considerada uma taxa absurdamente alta.</translation>
</message>
@@ -2400,10 +2500,6 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Escolher endereço usado anteriormente</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Este é um pagamento normal.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>O endereço Bitcoin para enviar o pagamento</translation>
</message>
@@ -2424,6 +2520,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Remover esta entrada</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>A quantia a ser enviada na unidade selecionada</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>A taxa será deduzida da quantia que está sendo enviada. O destinatário receberá menos bitcoins do que você colocou no campo de quantidade. Se vários destinatários estão selecionados, a taxa é dividida igualmente.</translation>
</message>
@@ -2463,17 +2563,6 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<source>Memo:</source>
<translation>Memorizar:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Digite um rótulo para este endereço para adicioná-lo ao catálogo de endereços</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Sim</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2561,6 +2650,14 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>O endereço Bitcoin que foi usado para assinar a mensagem</translation>
</message>
<message>
+ <source>The signed message to verify</source>
+ <translation>A mensagem assinada para verificação</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>A assinatura fornecida quando a mensagem foi assinada</translation>
+ </message>
+ <message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
<translation>Verificar mensagem para se assegurar que ela foi assinada pelo dono de um endereço Bitcoin específico</translation>
</message>
@@ -2593,6 +2690,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>O desbloqueio da carteira foi cancelado.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Sem erro</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>A chave privada do endereço inserido não está disponível.</translation>
</message>
@@ -2767,6 +2868,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Index da saída</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(O certificado não foi verificado)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Mercador</translation>
</message>
@@ -3069,7 +3174,7 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
</message>
<message>
<source>Range:</source>
- <translation>Intervalo: </translation>
+ <translation>Intervalo:</translation>
</message>
<message>
<source>to</source>
@@ -3090,6 +3195,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Fechar carteira</translation>
</message>
<message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>Tem certeza que deseja fechar a carteira &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>Manter a carteira fechada por muito tempo pode resultar na necessidade de ressincronizar a block chain se prune está ativado.</translation>
</message>
@@ -3120,6 +3229,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Deseja aumentar a taxa?</translation>
</message>
<message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Você quer um rascunho da transação com o aumento das taxas?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Taxa atual:</translation>
</message>
@@ -3136,6 +3249,14 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Confirmação no aumento de taxa</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>Não foi possível criar o rascunho da transação.</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT copiado</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Não é possível assinar a transação.</translation>
</message>
@@ -3202,10 +3323,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Rescans não são possíveis no modo prune. Você precisa usar -reindex, que irá fazer o download de toda a blockchain novamente.</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>
@@ -3231,7 +3348,7 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
</message>
<message>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
- <translation>Não é possível fornecer conexões específicas e ter addrman procurando conexões ao mesmo tempo. </translation>
+ <translation>Não é possível fornecer conexões específicas e ter addrman procurando conexões ao mesmo tempo.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
@@ -3306,6 +3423,14 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Detectado Banco de dados de blocos corrompido</translation>
</message>
<message>
+ <source>Could not find asmap file %s</source>
+ <translation>O arquivo asmap %s não pode ser encontrado </translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>O arquivo asmap %s não pode ser analisado</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Você quer reconstruir o banco de dados de blocos agora?</translation>
</message>
@@ -3362,6 +3487,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>O teste de integridade de inicialização falhou. O %s está sendo desligado.</translation>
</message>
<message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Permissão P2P inválida: '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
<translation>Quantidade inválida para -%s=&lt;amount&gt;: '%s'</translation>
</message>
@@ -3383,6 +3512,10 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>Tipo de endereço desconhecido '%s'</translation>
</message>
<message>
+ <source>Unknown change type '%s'</source>
+ <translation>Tipo de troco desconhecido '%s'</translation>
+ </message>
+ <message>
<source>Upgrading txindex database</source>
<translation>Atualizando banco de dados txindex</translation>
</message>
@@ -3391,6 +3524,10 @@ 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>
@@ -3499,6 +3636,10 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>Necessário informar uma porta com -whitebind: '%s'</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Modo prune é incompatível com o parâmetro -blockfilterindex.</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reduzindo -maxconnections de %d para %d, devido a limitações do sistema.</translation>
</message>
@@ -3557,6 +3698,10 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>Não foi possível gerar as chaves iniciais</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>Valor do parâmetro -blockfilterindex desconhecido %s.</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>Verificando carteira(s)...</translation>
</message>
@@ -3577,10 +3722,6 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>Esta é a taxa que você deve pagar quando a taxa estimada não está disponível.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Esse produto inclui um software desenvolvido pelo OpenSSL Project para uso na OpenSSL Toolkit %s e software criptográfico escrito por Eric Young e software UPnP escrito por Thomas Bernard. </translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts
deleted file mode 100644
index d203c490e9..0000000000
--- a/src/qt/locale/bitcoin_pt_PT.ts
+++ /dev/null
@@ -1,3502 +0,0 @@
-<TS language="pt_PT" version="2.1">
-<context>
- <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 etiqueta</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Criar um novo endereço</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Novo</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Copiar o endereço selecionado para a área de transferência do sistema</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Copiar</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>F&amp;echar</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Eliminar o endereço selecionado da lista</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Digite o endereço ou o rótulo para pesquisar</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportar os dados no separador atual para um ficheiro</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportar</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Eliminar</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Escolha o endereço para enviar as moedas</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Escolha o endereço para receber as moedas</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>Escol&amp;her</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>A enviar endereços</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>A receber endereços</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>Estes são os seus endereços Bitcoin para enviar pagamentos. Verifique sempre o valor e o endereço de envio antes de enviar moedas.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Estes são os seus endereços Bitcoin para receber pagamentos. É recomendado que utilize um endereço novo para cada transação.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Copiar Endereço</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Copiar &amp;Etiqueta</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Editar</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Exportar Lista de Endereços</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Ficheiro separado por vírgulas (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Exportação Falhou</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Ocorreu um erro ao tentar guardar a lista de endereços para %1. Por favor, tente novamente.</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Endereço</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sem etiqueta)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Janela da Frase de Segurança</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Insira a frase de segurança</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Nova frase de frase de segurança</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Repita a nova frase de frase de segurança</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Mostrar palavra-passe</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Insira a nova frase de segurança para a carteira. &lt;br/&gt; Por favor, utilize uma frase de segurança de &lt;b&gt;10 ou mais carateres aleatórios,&lt;/b&gt; ou &lt;b&gt;oito ou mais palavras&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Encriptar carteira</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Esta operação precisa da sua frase de segurança da carteira para desbloquear a mesma.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Desbloquear carteira</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Esta operação precisa da sua frase de segurança da carteira para desencriptar a mesma.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Desencriptar carteira</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Alterar frase de segurança</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Insira a frase de segurança antiga e a nova frase de segurança para a carteira.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Confirmar encriptação da carteira</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Aviso: se encriptar a sua carteira e perder a sua frase de segurnça, &lt;b&gt;PERDERÁ TODOS OS SEUS BITCOINS&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Tem a certeza que deseja encriptar a sua carteira?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Carteira encriptada</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 irá agora ser fechado para terminar o processo de encriptação. Recorde que a encriptação da sua carteira não protegerá totalmente os seus bitcoins de serem roubados por programas maliciosos que infetem o seu computador.</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: Qualquer cópia de segurança da carteira anterior deverá ser substituída com o novo ficheiro de carteira, agora encriptado. Por razões de segurança, cópias de segurança não encriptadas tornar-se-ão inúteis assim que começar a usar a nova carteira encriptada.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Encriptação da carteira falhou</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>A encriptação da carteira falhou devido a um erro interno. A carteira não foi encriptada.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>As frases de segurança fornecidas não coincidem.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Desbloqueio da carteira falhou</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>A frase de segurança introduzida para a desencriptação da carteira estava incorreta.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Desencriptação da carteira falhou</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>A frase de segurança da carteira foi alterada com sucesso.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Aviso: a tecla Caps Lock está ligada!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Máscara de Rede</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Banido Até</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Assinar &amp;mensagem...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>A sincronizar com a rede...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Resumo</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Nó</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Mostrar resumo geral da carteira</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transações</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Explorar histórico das transações</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>Fec&amp;har</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Sair da aplicação</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Sobre o %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Mostrar informação sobre o %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Sobre o &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Mostrar informação sobre o Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Opções...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Modificar opções de configuração para %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>E&amp;ncriptar Carteira...</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>Efetuar &amp;Cópia de Segurança da Carteira...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>Alterar &amp;Frase de Segurança...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>A &amp;enviar os endereços...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>A &amp;receber os endereços...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Abrir &amp;URI...</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>Carteira:</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>carteira predefinida</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Clique para desativar a atividade de rede.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Atividade de rede desativada.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Clique para ativar novamente a atividade de rede.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>A sincronizar cabeçalhos (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>A reindexar os blocos no disco...</translation>
- </message>
- <message>
- <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>Proxy está &lt;b&gt;ativado&lt;/b&gt;: %1</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Enviar moedas para um endereço Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Efetue uma cópia de segurança da carteira para outra localização</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Alterar a frase de segurança utilizada na encriptação da carteira</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>Janela de &amp;Depuração</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Abrir consola de diagnóstico e depuração</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Verificar mensagem...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Carteira</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Enviar</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Receber</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>Mo&amp;strar / Ocultar</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Mostrar ou ocultar a janela principal</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Encriptar as chaves privadas que pertencem à sua carteira</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Assine as mensagens com os seus endereços Bitcoin para provar que é o proprietário dos mesmos</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Verifique mensagens para assegurar que foram assinadas com o endereço Bitcoin especificado</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Ficheiro</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Configurações</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Ajuda</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Barra de ferramentas dos separadores</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Solicitar pagamentos (gera códigos QR e bitcoin: URIs)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Mostrar a lista de rótulos e endereços de envio usados</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Mostrar a lista de rótulos e endereços de receção usados</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Abrir URI bitcoin: ou pedido de pagamento</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Opções da linha de &amp;comando</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n ligação ativa à rede Bitcoin</numerusform><numerusform>%n ligações ativas à rede Bitcoin</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>A indexar blocos no disco...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>A processar blocos no disco...</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>Processado %n bloco do histórico de transações.</numerusform><numerusform>Processados %n blocos do histórico de transações.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 em atraso</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>O último bloco recebido foi gerado há %1.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>As transações depois de isto ainda não serão visíveis.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erro</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Aviso</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informação</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Atualizado</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>
- <message>
- <source>%1 client</source>
- <translation>Cliente %1</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>A ligar aos pontos...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Recuperando o atraso...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Data: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Valor: %1
-</translation>
- </message>
- <message>
- <source>Wallet: %1
-</source>
- <translation>Carteira: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Tipo: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Etiqueta: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Endereço: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Transação enviada</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Transação recebida</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>Criação de chave HD está &lt;b&gt;ativada&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>Criação de chave HD está &lt;b&gt;desativada&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>A carteira está &lt;b&gt;encriptada&lt;/b&gt; e atualmente &lt;b&gt;desbloqueada&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>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>
- </message>
-</context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Seleção de Moeda</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Quantidade:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Valor:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Taxa:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Lixo:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Depois da taxa:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Troco:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(des)selecionar todos</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Modo de árvore</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Modo de lista</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Valor</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Recebido com etiqueta</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Recebido com endereço</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Confirmações</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmada</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Copiar endereço</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copiar etiqueta</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiar valor</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copiar Id. da transação</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Bloquear não gasto</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Desbloquear não gasto</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copiar quantidade</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copiar taxa</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Copiar depois da taxa</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copiar bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copiar poeira</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copiar troco</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 bloqueado)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>sim</translation>
- </message>
- <message>
- <source>no</source>
- <translation>não</translation>
- </message>
- <message>
- <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Esta etiqueta fica vermelha se qualquer destinatário recebe um valor menor que o limite de dinheiro.</translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Pode variar +/- %1 satoshi(s) por input.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sem etiqueta)</translation>
- </message>
- <message>
- <source>change from %1 (%2)</source>
- <translation>troco de %1 (%2)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation>(troco)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Editar Endereço</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Etiqueta</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>A etiqueta associada com esta entrada da lista de endereços</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>O endereço associado com o esta entrada da lista de endereços. Isto só pode ser modificado para os endereços de envio.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>E&amp;ndereço</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Novo endereço de envio</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Editar o endereço de depósito</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Editar o endereço de envio</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>O endereço introduzido "%1" não é um endereço bitcoin válido.</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Não foi possível desbloquear a carteira.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>A criação da nova chave falhou.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Será criada uma nova pasta de dados.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>nome</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>A pasta já existe. Adicione %1 se pretender criar aqui uma nova pasta.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>O caminho já existe, e não é uma pasta.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Não é possível criar aqui uma pasta de dados.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>versão</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>Sobre o %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Opções da linha de comando</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Bem-vindo</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Bem-vindo ao %1.</translation>
- </message>
- <message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation>Quando clicar OK, %1 vai começar a descarregar e processar a cadeia de blocos %4 completa (%2GB) começando com as transações mais antigas em %3 quando a %4 foi inicialmente lançada.</translation>
- </message>
- <message>
- <source>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>Esta sincronização inicial é muito exigente, e pode expor problemas com o seu computador que previamente podem ter passado despercebidos. Cada vez que corre %1, este vai continuar a descarregar de onde deixou. </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>Se escolheu limitar o armazenamento da cadeia de blocos (poda), a data histórica ainda tem de ser descarregada e processada, mas irá ser apagada no final para manter uma utilização baixa do espaço de disco.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Utilizar a pasta de dados predefinida</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Utilizar uma pasta de dados personalizada:</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation>No mínimo %1 GB de dados irão ser armazenados nesta pasta. </translation>
- </message>
- <message>
- <source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>Aproximadamente %1 GB de dados irão ser guardados nesta pasta. </translation>
- </message>
- <message>
- <source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 irá descarregar e armazenar uma cópia da cadeia de blocos da Bitcoin.</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation>A carteira também será guardada nesta pasta.</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Erro: não pode ser criada a pasta de dados especificada como "%1.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erro</translation>
- </message>
- <message numerus="yes">
- <source>%n GB of free space available</source>
- <translation><numerusform>%n GB de espaço livre disponível</numerusform><numerusform>%n GB de espaço livre disponível</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>(of %n GB needed)</source>
- <translation><numerusform>(de %n GB necessários)</numerusform><numerusform>(de %n GB necessário)</numerusform></translation>
- </message>
-</context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Formulário</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>Transações recentes podem não ser visíveis por agora, portanto o saldo da sua carteira pode estar incorreto. Esta informação será corrigida quando a sua carteira acabar de sincronizar com a rede, como está explicado em baixo.</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>Tentar enviar bitcoins que estão afetadas por transações ainda não exibidas não será aceite pela rede.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Número de blocos restantes</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Desconhecido...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Data do último bloco</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation>Progresso</translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation>Aumento horário do progresso</translation>
- </message>
- <message>
- <source>calculating...</source>
- <translation>a calcular...</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation>tempo restante estimado até à sincronização</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Ocultar</translation>
- </message>
- <message>
- <source>Unknown. Syncing Headers (%1)...</source>
- <translation>Desconhecido. Sincronização de Cabeçalhos (%1)...</translation>
- </message>
-</context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Abir URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Abrir pedido de pagamento de um URI ou ficheiro</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Selecione o ficheiro de pedido de pagamento</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Selecione o ficheiro de pedido de pagamento para abrir</translation>
- </message>
-</context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Opções</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Principal</translation>
- </message>
- <message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation>Iniciar automaticamente o %1 depois de iniciar a sessão no sistema.</translation>
- </message>
- <message>
- <source>&amp;Start %1 on system login</source>
- <translation>&amp;Iniciar o %1 no início de sessão do sistema</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Tamanho da cache da base de &amp;dados</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>Número de processos de &amp;verificação de scripts</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Endereço de IP do proxy (exemplo, 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>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>
- <message>
- <source>&amp;Hide tray icon</source>
- <translation>&amp;Ocultar ícone da 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>
- <translation>Minimize ao invés de sair da aplicação quando a janela é fechada. Com esta opção selecionada, a aplicação apenas será encerrada quando escolher Sair da aplicação no 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>URLs de outrem (ex. um explorador de blocos) que aparece no separador de transações como itens do menu de contexto.
-%s do URL é substituído por hash de transação. Vários URLs são separados por barra vertical |.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Ativar as opções da linha de comando que se sobrepõem às opções acima:</translation>
- </message>
- <message>
- <source>Open the %1 configuration file from the working directory.</source>
- <translation>Abrir o ficheiro de configuração %1 da pasta aberta.</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Abrir Ficheiro de Configuração</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Repor todas as opções de cliente para a predefinição.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Repor Opções</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Rede</translation>
- </message>
- <message>
- <source>GB</source>
- <translation>PT</translation>
- </message>
- <message>
- <source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = automático, &lt;0 = deixar essa quantidade de núcleos livre)</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>C&amp;arteira</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation> Técnicos</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Ativar as funcionalidades de &amp;controlo de moedas</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>Se desativar o gasto de troco não confirmado, o troco de uma transação não pode ser utilizado até que essa transação tenha pelo menos uma confirmação. Isto também afeta o cálculo do seu saldo.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>&amp;Gastar troco não 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>Abrir a porta do cliente bitcoin automaticamente no seu router. Isto apenas funciona se o seu router suportar UPnP e este se encontrar ligado.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Mapear porta, utilizando &amp;UPnP</translation>
- </message>
- <message>
- <source>Accept connections from outside.</source>
- <translation>Aceitar ligações externas.</translation>
- </message>
- <message>
- <source>Allow incomin&amp;g connections</source>
- <translation>Permitir ligações de "a receber"</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Conectar à rede da Bitcoin através dum proxy SOCLS5.</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Ligar através dum proxy SOCKS5 (proxy por defeito):</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>&amp;IP do proxy:</translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>&amp;Porta:</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Porta do proxy (por ex. 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation>Utilizado para alcançar pontos 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>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>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Apenas mostrar o ícone da bandeja de sistema após minimizar a janela.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimizar para a bandeja de sistema e não para a barra de ferramentas</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>M&amp;inimizar ao fechar</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Visualização</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>&amp;Linguagem da interface de utilizador:</translation>
- </message>
- <message>
- <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation>A linguagem da interface do utilizador pode ser definida aqui. Esta definição entrará em efeito após reiniciar %1.</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Unidade para mostrar quantias:</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Escolha a unidade da subdivisão predefinida para ser mostrada na interface e quando enviar as moedas.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Escolha se deve mostrar as funcionalidades de controlo de moedas ou não.</translation>
- </message>
- <message>
- <source>&amp;Third party transaction URLs</source>
- <translation>URLs de transação de &amp;terceiros</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;OK</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Cancelar</translation>
- </message>
- <message>
- <source>default</source>
- <translation>predefinição</translation>
- </message>
- <message>
- <source>none</source>
- <translation>nenhum</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Confirme a reposição das opções</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>É necessário reiniciar o cliente para ativar as alterações.</translation>
- </message>
- <message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation>O cliente será desligado. Deseja continuar?</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Opções da configuração</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>O ficheiro de configuração é usado para especificar opções de utilizador avançado, que sobrescrevem as configurações do interface gráfico. Adicionalmente, qualquer opção da linha de comandos vai sobrescrever este ficheiro de configuração. </translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erro</translation>
- </message>
- <message>
- <source>The configuration file could not be opened.</source>
- <translation>Não foi possível abrir o ficheiro de configuração.</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Esta alteração obrigará a um reinício do cliente.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>O endereço de proxy introduzido é inválido. </translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Formulário</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>A informação mostrada poderá estar desatualizada. A sua carteira sincroniza automaticamente com a rede Bitcoin depois de estabelecer ligação, mas este processo ainda não está completo.</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Apenas vigiar:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Disponível:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>O seu saldo (gastável) disponível</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Pendente:</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 de transações por confirmar, que ainda não estão contabilizadas no seu saldo gastável</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Imaturo:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>O saldo minado ainda não amadureceu</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Saldos</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Total:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>O seu saldo total atual</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>O seu balanço atual em endereços de apenas vigiar</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Dispensável:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>transações recentes</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Transações não confirmadas para endereços de apenas vigiar</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Saldo minado ainda não disponível de endereços de apenas vigiar</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>Saldo disponível em endereços de apenas vigiar</translation>
- </message>
-</context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Erro do pedido de pagamento</translation>
- </message>
- <message>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>Impossível iniciar o controlador de bitcoin: click-to-pay</translation>
- </message>
- <message>
- <source>URI handling</source>
- <translation>Manuseamento de URI</translation>
- </message>
- <message>
- <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
- <translation>'bitcoin://' não é um URI válido. Utilize 'bitcoin:'.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>O URL do pedido de pagamento é inválido: %1</translation>
- </message>
- <message>
- <source>Invalid payment address %1</source>
- <translation>Endereço de pagamento inválido %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 não foi lido corretamente! Isto pode ser causado por um endereço Bitcoin inválido ou por parâmetros URI malformados.</translation>
- </message>
- <message>
- <source>Payment request file handling</source>
- <translation>Controlo de pedidos de pagamento.</translation>
- </message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>O ficheiro de pedido de pagamento não pôde ser lido! Isto pode ter sido causado por um ficheiro de pedido de pagamento inválido.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Pedido de pagamento rejeitado</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Rede de requisição de pagamento não corresponde com a rede do cliente.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Pedido de pagamento expirado.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>O pedido de pagamento não foi inicializado.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Pedidos de pagamento não-verificados para scripts de pagamento personalizados não são suportados.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Pedido de pagamento inválido.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Quantia solicitada para pagamento de %1 é muito pequena (considerada "pó").</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Reembolso de %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Pedido de pagamento %1 é demasiado grande (%2 bytes, permitido %3 bytes).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Erro ao comunicar com %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>O pedido de pagamento não pode ser lido ou processado!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Má resposta do servidor %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Erro de pedido de rede</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Pagamento confirmado</translation>
- </message>
-</context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>Agente Usuário</translation>
- </message>
- <message>
- <source>Node/Service</source>
- <translation>Nó/Serviço</translation>
- </message>
- <message>
- <source>NodeId</source>
- <translation>NodeId</translation>
- </message>
- <message>
- <source>Ping</source>
- <translation>Latência</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Enviado</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Recebido</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Quantia</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Introduza um endereço Bitcoin (ex. %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>Nenhum</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>N/D</translation>
- </message>
- <message>
- <source>%1 ms</source>
- <translation>%1 ms</translation>
- </message>
- <message numerus="yes">
- <source>%n second(s)</source>
- <translation><numerusform>%n segundo</numerusform><numerusform>%n segundos</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n minute(s)</source>
- <translation><numerusform>%n minuto</numerusform><numerusform>%n minutos</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n hour(s)</source>
- <translation><numerusform>%n hora</numerusform><numerusform>%n horas</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n day(s)</source>
- <translation><numerusform>%n dia</numerusform><numerusform>%n dias</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n week(s)</source>
- <translation><numerusform>%n semana</numerusform><numerusform>%n semanas</numerusform></translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 e %2</translation>
- </message>
- <message numerus="yes">
- <source>%n year(s)</source>
- <translation><numerusform>%n anos</numerusform><numerusform>%n anos</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>%1 didn't yet exit safely...</source>
- <translation>%1 ainda não foi fechado em segurança...</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>desconhecido</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- <message>
- <source>Error parsing command line arguments: %1.</source>
- <translation>Erro ao analisar os argumentos da linha de comando: %1.</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Erro: a pasta de dados especificada "%1" não existe.</translation>
- </message>
- <message>
- <source>Error: Cannot parse configuration file: %1.</source>
- <translation>Erro: não é possível analisar o ficheiro de configuração: %1.</translation>
- </message>
- <message>
- <source>Error: %1</source>
- <translation>Erro: %1</translation>
- </message>
-</context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Guardar Imagem...</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>&amp;Copiar Imagem</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>Guardar o código QR</translation>
- </message>
- <message>
- <source>PNG Image (*.png)</source>
- <translation>Imagem PNG (*.png)</translation>
- </message>
-</context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>N/D</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Versão do Cliente</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Informação</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Janela de depuração</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Geral</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>Versão BerkeleyDB em uso</translation>
- </message>
- <message>
- <source>Datadir</source>
- <translation>Datadir</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Hora de Arranque</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Rede</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Nome</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Número de ligações</translation>
- </message>
- <message>
- <source>Block chain</source>
- <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>
- <message>
- <source>Current number of transactions</source>
- <translation>Número atual de transações</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Utilização de memória</translation>
- </message>
- <message>
- <source>Wallet: </source>
- <translation>Carteira:</translation>
- </message>
- <message>
- <source>(none)</source>
- <translation>(nenhuma)</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Reiniciar</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Recebido</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Enviado</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Pontos</translation>
- </message>
- <message>
- <source>Banned peers</source>
- <translation>Pontos banidos</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <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>
- <message>
- <source>Version</source>
- <translation>Versão</translation>
- </message>
- <message>
- <source>Starting Block</source>
- <translation>Bloco Inicial</translation>
- </message>
- <message>
- <source>Synced Headers</source>
- <translation>Cabeçalhos Sincronizados</translation>
- </message>
- <message>
- <source>Synced Blocks</source>
- <translation>Blocos Sincronizados</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>Agente Usuário</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 ficheiro de registo de depuração %1 da pasta de dados atual. Isto pode demorar alguns segundos para ficheiros de registo maiores.</translation>
- </message>
- <message>
- <source>Decrease font size</source>
- <translation>Diminuir tamanho da letra</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation>Aumentar tamanho da letra</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Serviços</translation>
- </message>
- <message>
- <source>Ban Score</source>
- <translation>Resultado da Suspensão</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Tempo de Ligação</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Último Envio</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Último Recebimento</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Tempo de Latência</translation>
- </message>
- <message>
- <source>The duration of a currently outstanding ping.</source>
- <translation>A duração de um ping atualmente pendente.</translation>
- </message>
- <message>
- <source>Ping Wait</source>
- <translation>Espera do Ping</translation>
- </message>
- <message>
- <source>Min Ping</source>
- <translation>Latência mínima</translation>
- </message>
- <message>
- <source>Time Offset</source>
- <translation>Fuso Horário</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Data do último bloco</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Abrir</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Consola</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Tráfego de Rede</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Totais</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Entrada:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Saída:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Ficheiro de registo de depuração</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Limpar consola</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;hora</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;dia</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;semana</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;ano</translation>
- </message>
- <message>
- <source>Ban for</source>
- <translation>Banir para</translation>
- </message>
- <message>
- <source>&amp;Unban</source>
- <translation>&amp;Desbanir</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>carteira predefinida</translation>
- </message>
- <message>
- <source>Welcome to the %1 RPC console.</source>
- <translation>Bem-vindo à consola RPC da %1.</translation>
- </message>
- <message>
- <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
- <translation>Use as setas para cima e para baixo para navegar a história e %1 para limpar o ecrã.</translation>
- </message>
- <message>
- <source>Type %1 for an overview of available commands.</source>
- <translation>Digite %1 para uma visão geral dos comandos disponíveis.</translation>
- </message>
- <message>
- <source>For more information on using this console type %1.</source>
- <translation>Para mais informação em como utilizar esta consola, digite %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>AVISO: alguns burlões têm estado ativos, dizendo a utilizadores para digitarem comandos aqui, roubando assim os conteúdos das suas carteiras. Não utilize esta consola sem perceber perfeitamente as ramificações de um comando.</translation>
- </message>
- <message>
- <source>Network activity disabled</source>
- <translation>Atividade de rede desativada</translation>
- </message>
- <message>
- <source>Executing command without any wallet</source>
- <translation>A executar o comando sem qualquer carteira</translation>
- </message>
- <message>
- <source>Executing command using "%1" wallet</source>
- <translation>A executar o comando utilizando a carteira "%1"</translation>
- </message>
- <message>
- <source>(node id: %1)</source>
- <translation>(id nó: %1)</translation>
- </message>
- <message>
- <source>via %1</source>
- <translation>via %1</translation>
- </message>
- <message>
- <source>never</source>
- <translation>nunca</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Entrada</translation>
- </message>
- <message>
- <source>Outbound</source>
- <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>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>&amp;Quantia:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Rótulo:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Mensagem:</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>Uma mensagem opcional para anexar ao pedido de pagamento, que será exibida quando o pedido for aberto. Nota: A mensagem não será enviada com o pagamento através da rede Bitcoin.</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation>Um rótulo opcional a associar ao novo endereço de receção.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Utilize este formulário para solicitar pagamentos. Todos os campos são &lt;b&gt;opcionais&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>Uma quantia opcional a solicitar. Deixe em branco ou zero para não solicitar uma quantidade específica.</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Limpar todos os campos do formulário.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Limpar</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>Endereços nativos SegWit (também conhecidos como Bech32 ou BIP-173) reduzem as taxas da sua transação mais tarde e oferecem melhor proteção contra erros, mas carteiras antigas não os suportam. Quando não selecionado, um endereço compatível com carteiras antigas irá ser criado em vez.</translation>
- </message>
- <message>
- <source>Generate native segwit (Bech32) address</source>
- <translation>Gerar endereço nativo SegWit (Bech32)</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>Histórico de pagamentos solicitados</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Requisitar Pagamento</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Mostrar o pedido selecionado (faz o mesmo que clicar 2 vezes numa entrada)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Mostrar</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Remover as entradas selecionadas da lista</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Remover</translation>
- </message>
- <message>
- <source>Copy URI</source>
- <translation>Copiar URI</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copiar etiqueta</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Copiar mensagem</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiar valor</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>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Copi&amp;ar Endereço</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Salvar Imagem...</translation>
- </message>
- <message>
- <source>Request payment to %1</source>
- <translation>Requisitar Pagamento para %1</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation>Informação de Pagamento</translation>
- </message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Endereço</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Valor</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mensagem</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Carteira</translation>
- </message>
- <message>
- <source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation>URI resultante muito longo. Tente reduzir o texto do rótulo / mensagem.</translation>
- </message>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation>Erro ao codificar URI em Código QR.</translation>
- </message>
-</context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mensagem </translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sem etiqueta)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation>(sem mensagem)</translation>
- </message>
- <message>
- <source>(no amount requested)</source>
- <translation>(sem quantia pedida)</translation>
- </message>
- <message>
- <source>Requested</source>
- <translation>Solicitado</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Enviar Moedas</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Funcionalidades do Controlo de Moedas:</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Entradas...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>selecionadas automáticamente</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Fundos insuficientes!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Quantidade:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Quantia:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Taxa:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Depois da taxa:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Troco:</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>Se isto estiver ativo, mas o endereço de troco estiver vazio ou for inválido, o troco será enviado para um novo endereço gerado.</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Endereço de troco personalizado</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Taxa da transação:</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Escolher...</translation>
- </message>
- <message>
- <source>Warning: Fee estimation is currently not possible.</source>
- <translation>Aviso: atualmente, não é possível a estimativa da taxa.</translation>
- </message>
- <message>
- <source>collapse fee-settings</source>
- <translation>ocultar definições de taxa</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>por kilobyte</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Esconder</translation>
- </message>
- <message>
- <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
- <translation>Pode pagar somente a taxa mínima desde que haja um volume de transações inferior ao espaço nos blocos. No entanto tenha em atenção que esta opção poderá acabar em uma transação nunca confirmada assim que os pedidos de transações excedam a capacidade de processamento da rede.</translation>
- </message>
- <message>
- <source>(read the tooltip)</source>
- <translation>(leia a dica)</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Recomendado:</translation>
- </message>
- <message>
- <source>Custom:</source>
- <translation>Personalizado:</translation>
- </message>
- <message>
- <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(A taxa inteligente ainda não foi inicializada. Isto normalmente demora alguns blocos...)</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Enviar para múltiplos destinatários de uma vez</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>Adicionar &amp;Destinatário</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Limpar todos os campos do formulário.</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Lixo:</translation>
- </message>
- <message>
- <source>Confirmation time target:</source>
- <translation>Tempo de confirmação:</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Limpar &amp;Tudo</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Saldo:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Confirme ação de envio</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>E&amp;nviar</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copiar quantidade</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiar valor</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copiar taxa</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Copiar depois da taxa</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copiar bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copiar pó</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copiar troco</translation>
- </message>
- <message>
- <source>%1 (%2 blocks)</source>
- <translation>%1 (%2 blocos)</translation>
- </message>
- <message>
- <source>%1 to %2</source>
- <translation>%1 para %2</translation>
- </message>
- <message>
- <source>Are you sure you want to send?</source>
- <translation>Tem a certeza que deseja enviar?</translation>
- </message>
- <message>
- <source>or</source>
- <translation>ou</translation>
- </message>
- <message>
- <source>from wallet %1</source>
- <translation>da carteira %1</translation>
- </message>
- <message>
- <source>Please, review your transaction.</source>
- <translation>Por favor, reveja a sua transação.</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Taxa de transação</translation>
- </message>
- <message>
- <source>Total Amount</source>
- <translation>Valor Total</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation>Confirme envio de moedas</translation>
- </message>
- <message>
- <source>The recipient address is not valid. Please recheck.</source>
- <translation>O endereço do destinatário é inválido. Por favor, reverifique.</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation>O valor a pagar dever maior que 0.</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation>O valor excede o seu saldo.</translation>
- </message>
- <message>
- <source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>O total excede o seu saldo quando a taxa de transação %1 está incluída.</translation>
- </message>
- <message>
- <source>Duplicate address found: addresses should only be used once each.</source>
- <translation>Endereço duplicado encontrado: os endereços devem ser usados ​​apenas uma vez.</translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation>A criação da transação falhou!</translation>
- </message>
- <message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>A transação foi rejeitada pelo seguinte motivo: %1
-</translation>
- </message>
- <message>
- <source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation>Uma taxa superior a %1 é considerada uma taxa altamente absurda.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Pedido de pagamento expirado.</translation>
- </message>
- <message>
- <source>Pay only the required fee of %1</source>
- <translation>Pague apenas a taxa obrigatória de %1</translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation>Aviso: endereço Bitcoin inválido</translation>
- </message>
- <message>
- <source>Warning: Unknown change address</source>
- <translation>Aviso: endereço de troco desconhecido</translation>
- </message>
- <message>
- <source>Confirm custom change address</source>
- <translation>Confirmar endereço de troco personalizado</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>O endereço que você selecionou para alterar não faz parte desta carteira. Qualquer ou todos os fundos em sua carteira podem ser enviados para este endereço. Você tem certeza?</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sem etiqueta)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>Qu&amp;antia:</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>&amp;Pagar A:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>Rótu&amp;lo:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Escolha o endereço utilizado anteriormente</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Este é um pagamento normal.</translation>
- </message>
- <message>
- <source>The Bitcoin address to send the payment to</source>
- <translation>O endereço Bitcoin para enviar o pagamento</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Cole endereço da área de transferência</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Remover esta entrada</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>A taxa será deduzida ao valor que está a ser enviado. O destinatário irá receber menos bitcoins do que as que inseridas no campo do valor. Se estiverem selecionados múltiplos destinatários, a taxa será repartida equitativamente.</translation>
- </message>
- <message>
- <source>S&amp;ubtract fee from amount</source>
- <translation>S&amp;ubtrair a taxa ao montante</translation>
- </message>
- <message>
- <source>Use available balance</source>
- <translation>Utilizar saldo disponível</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Mensagem:</translation>
- </message>
- <message>
- <source>This is an unauthenticated payment request.</source>
- <translation>Pedido de pagamento não autenticado.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation>Pedido de pagamento autenticado.</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Introduza um rótulo para este endereço para o adicionar à sua lista de endereços usados</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>Uma mensagem que estava anexada ao URI bitcoin: que será armazenada com a transação para sua referência. Nota: Esta mensagem não será enviada através da rede Bitcoin.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Pagar a:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Memorando:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Digite um rótulo para este endereço para adicioná-lo ao seu catálogo de endereços</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Sim</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>%1 is shutting down...</source>
- <translation>%1 está a encerrar...</translation>
- </message>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>Não desligue o computador enquanto esta janela não desaparecer.</translation>
- </message>
-</context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Assinaturas - Assinar / Verificar uma Mensagem</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Assinar Mensagem</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>Pode assinar mensagens com os seus endereços para provar que são seus. Tenha atenção ao assinar mensagens ambíguas, pois ataques de phishing podem tentar enganá-lo de modo a assinar a sua identidade para os atacantes. Apenas assine declarações detalhadas com as quais concorde.</translation>
- </message>
- <message>
- <source>The Bitcoin address to sign the message with</source>
- <translation>O endereço Bitcoin para designar a mensagem</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Escolha o endereço utilizado anteriormente</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Colar endereço da área de transferência</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Escreva aqui a mensagem que deseja assinar</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Assinatura</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Copiar a assinatura atual para a área de transferência</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Assine uma mensagem para provar que é dono deste endereço Bitcoin</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Assinar &amp;Mensagem</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Repor todos os campos de assinatura de mensagem</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Limpar &amp;Tudo</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Verificar Mensagem</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>Introduza o endereço de assinatura, mensagem (assegure-se que copia quebras de linha, espaços, tabulações, etc. exatamente) e assinatura abaixo para verificar a mensagem. Tenha atenção para não ler mais na assinatura do que o que estiver na mensagem assinada, para evitar ser enganado por um atacante que se encontre entre si e quem assinou a mensagem.</translation>
- </message>
- <message>
- <source>The Bitcoin address the message was signed with</source>
- <translation>O endereço Bitcoin com que a mensagem foi designada</translation>
- </message>
- <message>
- <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Verifique a mensagem para assegurar que foi assinada com o endereço Bitcoin especificado</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Verificar &amp;Mensagem</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Repor todos os campos de verificação de mensagem</translation>
- </message>
- <message>
- <source>Click "Sign Message" to generate signature</source>
- <translation>Clique "Assinar Mensagem" para gerar a assinatura</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation>O endereço introduzido é inválido.</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Por favor, verifique o endereço e tente novamente.</translation>
- </message>
- <message>
- <source>The entered address does not refer to a key.</source>
- <translation>O endereço introduzido não refere-se a nenhuma chave.</translation>
- </message>
- <message>
- <source>Wallet unlock was cancelled.</source>
- <translation>O desbloqueio da carteira foi cancelado.</translation>
- </message>
- <message>
- <source>Private key for the entered address is not available.</source>
- <translation>A chave privada para o endereço introduzido não está disponível.</translation>
- </message>
- <message>
- <source>Message signing failed.</source>
- <translation>Assinatura da mensagem falhou.</translation>
- </message>
- <message>
- <source>Message signed.</source>
- <translation>Mensagem assinada.</translation>
- </message>
- <message>
- <source>The signature could not be decoded.</source>
- <translation>Não foi possível descodificar a assinatura.</translation>
- </message>
- <message>
- <source>Please check the signature and try again.</source>
- <translation>Por favor, verifique a assinatura e tente novamente.</translation>
- </message>
- <message>
- <source>The signature did not match the message digest.</source>
- <translation>A assinatura não corresponde com o conteúdo da mensagem.</translation>
- </message>
- <message>
- <source>Message verification failed.</source>
- <translation>Verificação da mensagem falhou.</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation>Mensagem verificada.</translation>
- </message>
-</context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[rede de testes]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KB/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Open until %1</source>
- <translation>Aberto até %1</translation>
- </message>
- <message>
- <source>0/unconfirmed, %1</source>
- <translation>0/não confirmada, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation>no banco de memória</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation>não está no banco de memória</translation>
- </message>
- <message>
- <source>abandoned</source>
- <translation>abandonada</translation>
- </message>
- <message>
- <source>%1/unconfirmed</source>
- <translation>%1/não confirmada</translation>
- </message>
- <message>
- <source>%1 confirmations</source>
- <translation>%1 confirmações</translation>
- </message>
- <message>
- <source>Status</source>
- <translation>Estado</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Origem</translation>
- </message>
- <message>
- <source>Generated</source>
- <translation>Gerado</translation>
- </message>
- <message>
- <source>From</source>
- <translation>De</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>desconhecido</translation>
- </message>
- <message>
- <source>To</source>
- <translation>Para</translation>
- </message>
- <message>
- <source>own address</source>
- <translation>endereço próprio</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>apenas vigiar</translation>
- </message>
- <message>
- <source>label</source>
- <translation>etiqueta</translation>
- </message>
- <message>
- <source>Credit</source>
- <translation>Crédito</translation>
- </message>
- <message numerus="yes">
- <source>matures in %n more block(s)</source>
- <translation><numerusform>matura em %n bloco</numerusform><numerusform>matura em %n blocos</numerusform></translation>
- </message>
- <message>
- <source>not accepted</source>
- <translation>não aceite</translation>
- </message>
- <message>
- <source>Debit</source>
- <translation>Débito</translation>
- </message>
- <message>
- <source>Total debit</source>
- <translation>Débito total</translation>
- </message>
- <message>
- <source>Total credit</source>
- <translation>Crédito total</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Taxa de transação</translation>
- </message>
- <message>
- <source>Net amount</source>
- <translation>Valor líquido</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mensagem</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Comentário</translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation>Id. da Transação</translation>
- </message>
- <message>
- <source>Transaction total size</source>
- <translation>Tamanho total da transição</translation>
- </message>
- <message>
- <source>Transaction virtual size</source>
- <translation>Tamanho da transação virtual</translation>
- </message>
- <message>
- <source>Output index</source>
- <translation>Índex de saída</translation>
- </message>
- <message>
- <source>Merchant</source>
- <translation>Comerciante</translation>
- </message>
- <message>
- <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <translation>As moedas geradas precisam amadurecer %1 blocos antes que possam ser gastas. Quando gerou este bloco, ele foi transmitido para a rede para ser adicionado à cadeia de blocos. Se este não conseguir entrar na cadeia, seu estado mudará para "não aceite" e não poderá ser gasto. Isto pode acontecer ocasionalmente se outro nó gerar um bloco dentro de alguns segundos do seu.</translation>
- </message>
- <message>
- <source>Debug information</source>
- <translation>Informação de depuração</translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation>Transação</translation>
- </message>
- <message>
- <source>Inputs</source>
- <translation>Entradas</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Valor</translation>
- </message>
- <message>
- <source>true</source>
- <translation>verdadeiro</translation>
- </message>
- <message>
- <source>false</source>
- <translation>falso</translation>
- </message>
-</context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Esta janela mostra uma descrição detalhada da transação</translation>
- </message>
- <message>
- <source>Details for %1</source>
- <translation>Detalhes para %1</translation>
- </message>
-</context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tipo</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message numerus="yes">
- <source>Open for %n more block(s)</source>
- <translation><numerusform>Aberto para mais %n bloco</numerusform><numerusform>Aberto para mais %n blocos</numerusform></translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Aberto até %1</translation>
- </message>
- <message>
- <source>Unconfirmed</source>
- <translation>Não confirmado</translation>
- </message>
- <message>
- <source>Abandoned</source>
- <translation>Abandonada</translation>
- </message>
- <message>
- <source>Confirming (%1 of %2 recommended confirmations)</source>
- <translation>Confirmando (%1 de %2 confirmações recomendadas)</translation>
- </message>
- <message>
- <source>Confirmed (%1 confirmations)</source>
- <translation>Confirmada (%1 confirmações)</translation>
- </message>
- <message>
- <source>Conflicted</source>
- <translation>Incompatível</translation>
- </message>
- <message>
- <source>Immature (%1 confirmations, will be available after %2)</source>
- <translation>Imaturo (%1 confirmações, estarão disponível após %2)</translation>
- </message>
- <message>
- <source>Generated but not accepted</source>
- <translation>Gerada mas não aceite</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Recebido com</translation>
- </message>
- <message>
- <source>Received from</source>
- <translation>Recebido de</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Enviado para</translation>
- </message>
- <message>
- <source>Payment to yourself</source>
- <translation>Pagamento para si mesmo</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Minada</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>apenas vigiar</translation>
- </message>
- <message>
- <source>(n/a)</source>
- <translation>(n/d)</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(sem etiqueta)</translation>
- </message>
- <message>
- <source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>Estado da transação. Passar o cursor por cima deste campo para mostrar o número de confirmações.</translation>
- </message>
- <message>
- <source>Date and time that the transaction was received.</source>
- <translation>Data e hora em que a transação foi recebida.</translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation>Tipo de transação.</translation>
- </message>
- <message>
- <source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation>Se um endereço de apenas vigiar está ou não envolvido nesta transação.</translation>
- </message>
- <message>
- <source>User-defined intent/purpose of the transaction.</source>
- <translation>Intenção do utilizador/motivo da transação</translation>
- </message>
- <message>
- <source>Amount removed from or added to balance.</source>
- <translation>Montante retirado ou adicionado ao saldo</translation>
- </message>
-</context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Todas</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Hoje</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>Esta semana</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>Este mês</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Mês passado</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Este ano</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Período...</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Recebido com</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Enviado para</translation>
- </message>
- <message>
- <source>To yourself</source>
- <translation>Para si mesmo</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Minada</translation>
- </message>
- <message>
- <source>Other</source>
- <translation>Outras</translation>
- </message>
- <message>
- <source>Enter address, transaction id, or label to search</source>
- <translation>Escreva endereço, identificação de transação ou rótulo para procurar</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation>Valor mín.</translation>
- </message>
- <message>
- <source>Abandon transaction</source>
- <translation>Abandonar transação</translation>
- </message>
- <message>
- <source>Increase transaction fee</source>
- <translation>Aumentar taxa da transação</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Copiar endereço</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copiar etiqueta</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiar valor</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copiar Id. da transação</translation>
- </message>
- <message>
- <source>Copy raw transaction</source>
- <translation>Copiar transação em bruto</translation>
- </message>
- <message>
- <source>Copy full transaction details</source>
- <translation>Copiar detalhes completos da transação</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Editar etiqueta</translation>
- </message>
- <message>
- <source>Show transaction details</source>
- <translation>Mostrar detalhes da transação</translation>
- </message>
- <message>
- <source>Export Transaction History</source>
- <translation>Exportar Histórico de Transações</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Ficheiro separado por vírgulas (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmada</translation>
- </message>
- <message>
- <source>Watch-only</source>
- <translation>Apenas vigiar</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tipo</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Endereço</translation>
- </message>
- <message>
- <source>ID</source>
- <translation>Id.</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Exportação Falhou</translation>
- </message>
- <message>
- <source>There was an error trying to save the transaction history to %1.</source>
- <translation>Ocorreu um erro ao tentar guardar o histórico de transações em %1.</translation>
- </message>
- <message>
- <source>Exporting Successful</source>
- <translation>Exportação Bem Sucedida</translation>
- </message>
- <message>
- <source>Range:</source>
- <translation>Período:</translation>
- </message>
- <message>
- <source>to</source>
- <translation>até</translation>
- </message>
-</context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- <message>
- <source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Unidade de valores recebidos. Clique para selecionar outra unidade.</translation>
- </message>
-</context>
-<context>
- <name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>Nenhuma carteira foi carregada</translation>
- </message>
-</context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Enviar Moedas</translation>
- </message>
- <message>
- <source>Fee bump error</source>
- <translation>Erro no aumento de taxa</translation>
- </message>
- <message>
- <source>Increasing transaction fee failed</source>
- <translation>Aumento da taxa de transação falhou</translation>
- </message>
- <message>
- <source>Do you want to increase the fee?</source>
- <translation>Quer aumentar a taxa?</translation>
- </message>
- <message>
- <source>Current fee:</source>
- <translation>Taxa atual:</translation>
- </message>
- <message>
- <source>Increase:</source>
- <translation>Aumentar:</translation>
- </message>
- <message>
- <source>New fee:</source>
- <translation>Nova taxa:</translation>
- </message>
- <message>
- <source>Confirm fee bump</source>
- <translation>Confirme aumento de taxa</translation>
- </message>
- <message>
- <source>Can't sign transaction.</source>
- <translation>Não é possível assinar a transação.</translation>
- </message>
- <message>
- <source>Could not commit transaction</source>
- <translation>Não foi possível cometer a transação</translation>
- </message>
-</context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportar</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportar os dados no separador atual para um ficheiro</translation>
- </message>
- <message>
- <source>Backup Wallet</source>
- <translation>Cópia de Segurança da Carteira</translation>
- </message>
- <message>
- <source>Wallet Data (*.dat)</source>
- <translation>Dados da Carteira (*.dat)</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>Cópia de Segurança Falhou</translation>
- </message>
- <message>
- <source>There was an error trying to save the wallet data to %1.</source>
- <translation>Ocorreu um erro ao tentar guardar os dados da carteira em %1.</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Cópia de Segurança Bem Sucedida</translation>
- </message>
- <message>
- <source>The wallet data was successfully saved to %1.</source>
- <translation>Os dados da carteira foram guardados com sucesso em %1.</translation>
- </message>
- <message>
- <source>Cancel</source>
- <translation>Cancelar</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>Distribuído sob licença de software MIT, veja o ficheiro %s ou %s</translation>
- </message>
- <message>
- <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation>Poda configurada abaixo do mínimo de %d MiB. Por favor, utilize um valor mais elevado.</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>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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Reanálises não são possíveis em modo poda. Terá de utilizar -reindex que irá descarregar novamente a cadeia de blocos completa</translation>
- </message>
- <message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Erro: Um erro fatal interno ocorreu, verificar debug.log para mais informação</translation>
- </message>
- <message>
- <source>Pruning blockstore...</source>
- <translation>A podar a blockstore...</translation>
- </message>
- <message>
- <source>Unable to start HTTP server. See debug log for details.</source>
- <translation>Não é possível iniciar o servidor HTTP. Verifique o debug.log para detalhes.</translation>
- </message>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>The %s developers</source>
- <translation>Os programadores de %s</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>
- <message>
- <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
- <translation>Não é possível fornecer conexões específicas e ter o addrman a procurar conexões de saída ao mesmo tempo.</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 que a data e hora do seu computador estão certos! Se o relógio não estiver certo, o %s não funcionará corretamente.</translation>
- </message>
- <message>
- <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <translation>Por favor, contribua se achar que %s é útil. Visite %s para mais informação sobre o 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>A base de dados de blocos contém um bloco que aparenta ser do futuro. Isto pode ser causado por uma data incorreta definida no seu computador. Reconstrua apenas a base de dados de blocos caso tenha a certeza de que a data e hora do seu computador estão corretos.</translation>
- </message>
- <message>
- <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>Esta é a taxa de transação que poderá descartar, se o troco for menor que o pó a este nível</translation>
- </message>
- <message>
- <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
- <translation>Não é possível rebobinar a base de dados para um estado antes da divisão da cadeia de blocos. Necessita descarregar novamente a cadeia de blocos </translation>
- </message>
- <message>
- <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>Aviso: a rede não parece estar completamente de acordo! Parece que alguns mineiros estão com dificuldades técnicas.</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>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>-maxmempool must be at least %d MB</source>
- <translation>- máximo do banco de memória deverá ser pelo menos %d MB</translation>
- </message>
- <message>
- <source>Cannot resolve -%s address: '%s'</source>
- <translation>Não é possível resolver -%s endereço '%s'</translation>
- </message>
- <message>
- <source>Copyright (C) %i-%i</source>
- <translation>Direitos de Autor (C) %i-%i</translation>
- </message>
- <message>
- <source>Corrupted block database detected</source>
- <translation>Detetada cadeia de blocos corrompida</translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Deseja reconstruir agora a base de dados de blocos.</translation>
- </message>
- <message>
- <source>Error initializing block database</source>
- <translation>Erro ao inicializar a cadeia de blocos</translation>
- </message>
- <message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Erro ao inicializar o ambiente %s da base de dados da carteira</translation>
- </message>
- <message>
- <source>Error loading %s</source>
- <translation>Erro ao carregar %s</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet corrupted</source>
- <translation>Erro ao carregar %s: carteira corrompida</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet requires newer version of %s</source>
- <translation>Erro ao carregar %s: a carteira requer a nova versão de %s</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Erro ao carregar base de dados de blocos</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Erro ao abrir a base de dados de blocos</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Erro: Pouco espaço em disco!</translation>
- </message>
- <message>
- <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>Falhou a escutar em qualquer porta. Use -listen=0 se quiser isto.</translation>
- </message>
- <message>
- <source>Failed to rescan the wallet during initialization</source>
- <translation>Reexaminação da carteira falhou durante a inicialização</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>A importar...</translation>
- </message>
- <message>
- <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>Bloco génese incorreto ou nenhum bloco génese encontrado. Pasta de dados errada para a rede?</translation>
- </message>
- <message>
- <source>Initialization sanity check failed. %s is shutting down.</source>
- <translation>Verificação de integridade inicial falhou. O %s está a desligar-se.</translation>
- </message>
- <message>
- <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>Valor inválido para -%s=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>Valor inválido para -fallbackfee=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Specified blocks directory "%s" does not exist.</source>
- <translation>
-A pasta de blocos especificados "%s" não existe.</translation>
- </message>
- <message>
- <source>Loading P2P addresses...</source>
- <translation>A carregar endereços de P2P...</translation>
- </message>
- <message>
- <source>Loading banlist...</source>
- <translation>A carregar a lista de banir...</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>Os descritores de ficheiros disponíveis são insuficientes.</translation>
- </message>
- <message>
- <source>Prune cannot be configured with a negative value.</source>
- <translation>Poda não pode ser configurada com um valor negativo.</translation>
- </message>
- <message>
- <source>Prune mode is incompatible with -txindex.</source>
- <translation>Modo poda é incompatível com -txindex.</translation>
- </message>
- <message>
- <source>Replaying blocks...</source>
- <translation>Repetindo blocos...</translation>
- </message>
- <message>
- <source>Rewinding blocks...</source>
- <translation>A rebobinar blocos...</translation>
- </message>
- <message>
- <source>The source code is available from %s.</source>
- <translation>O código fonte está disponível pelo %s.</translation>
- </message>
- <message>
- <source>Transaction fee and change calculation failed</source>
- <translation>Cálculo da taxa de transação e de troco falhou</translation>
- </message>
- <message>
- <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
- <translation>Argumento não suportado -benchmark ignorado, use -debug=bench.</translation>
- </message>
- <message>
- <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
- <translation>Argumento não suportado -debugnet ignorado, use -debug=net.</translation>
- </message>
- <message>
- <source>Unsupported argument -tor found, use -onion.</source>
- <translation>Argumento não suportado -tor encontrado, use -onion.</translation>
- </message>
- <message>
- <source>Upgrading UTXO database</source>
- <translation>A atualizar a base de dados UTXO</translation>
- </message>
- <message>
- <source>User Agent comment (%s) contains unsafe characters.</source>
- <translation>Comentário no User Agent (%s) contém caracteres inseguros.</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>A verificar blocos...</translation>
- </message>
- <message>
- <source>Wallet needed to be rewritten: restart %s to complete</source>
- <translation>A carteira precisou de ser reescrita: reinicie %s para completar</translation>
- </message>
- <message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Erro: A escuta de ligações de entrada falhou (escuta devolveu erro %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>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>
- <message>
- <source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>O montante da transação é demasiado baixo após a dedução da taxa</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>Error reading from database, shutting down.</source>
- <translation>Erro ao ler da base de dados, encerrando.</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informação</translation>
- </message>
- <message>
- <source>Invalid -onion address or hostname: '%s'</source>
- <translation>Endereço -onion ou hostname inválido: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation>Montante inválido para -paytxfee=&lt;amount&gt;: '%s' (deverá ser no mínimo %s)</translation>
- </message>
- <message>
- <source>Invalid netmask specified in -whitelist: '%s'</source>
- <translation>Máscara de rede inválida especificada em -whitelist: '%s'</translation>
- </message>
- <message>
- <source>Need to specify a port with -whitebind: '%s'</source>
- <translation>Necessário especificar uma porta com -whitebind: '%s'</translation>
- </message>
- <message>
- <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <translation>Reduzindo -maxconnections de %d para %d, devido a limitações no sistema.</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Falhou assinatura da transação</translation>
- </message>
- <message>
- <source>Specified -walletdir "%s" is not a directory</source>
- <translation>O -walletdir "%s" especificado não é uma pasta</translation>
- </message>
- <message>
- <source>The transaction amount is too small to pay the fee</source>
- <translation>O montante da transação é demasiado baixo para pagar a taxa</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>Isto é software experimental.</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Quantia da transação é muito baixa</translation>
- </message>
- <message>
- <source>Transaction too large for fee policy</source>
- <translation>Transação demasiado grande para a política de taxas</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Transação grande demais</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation>Incapaz de vincular à porta %s neste computador (vínculo retornou erro %s)</translation>
- </message>
- <message>
- <source>Unable to generate initial keys</source>
- <translation>Incapaz de gerar as chaves iniciais</translation>
- </message>
- <message>
- <source>Verifying wallet(s)...</source>
- <translation>A verificar a(s) carteira(s)...</translation>
- </message>
- <message>
- <source>Wallet %s resides outside wallet directory %s</source>
- <translation>A carteira %s reside fora da pasta da carteira %s</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Aviso</translation>
- </message>
- <message>
- <source>Warning: unknown new rules activated (versionbit %i)</source>
- <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>
- <message>
- <source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation>Esta é a taxa de transação que poderá pagar quando as estimativas da taxa não estão disponíveis.</translation>
- </message>
- <message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Este produto inclui software desenvolvido pelo Projeto de OpenSSL para utilização no OpenSSL Toolkit %s e software criptográfico escrito por Eric Young e software UPnP escrito por Thomas Bernard.</translation>
- </message>
- <message>
- <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <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>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
- <translation>Encontrado um argumento não suportado -socks. Definir a versão do SOCKS já não é possível, apenas proxies SOCKS5 são suportados.</translation>
- </message>
- <message>
- <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
- <translation>Argumento não suportado -whitelistalwaysrelay ignorado, utilize -whitelistrelay e/ou -whitelistforcerelay.</translation>
- </message>
- <message>
- <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
- <translation>Atenção: Versões desconhecidas de blocos estão a ser mineradas! É possível que regras desconhecias estão a ser efetuadas</translation>
- </message>
- <message>
- <source>%s is set very high!</source>
- <translation>%s está demasiado elevado!</translation>
- </message>
- <message>
- <source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation>A carteira evitará pagar menos que a taxa minima de propagação.</translation>
- </message>
- <message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Esta é a taxa minima de transação que paga em cada transação.</translation>
- </message>
- <message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Esta é a taxa de transação que irá pagar se enviar uma transação.</translation>
- </message>
- <message>
- <source>Transaction amounts must not be negative</source>
- <translation>Os valores da transação não devem ser negativos</translation>
- </message>
- <message>
- <source>Transaction has too long of a mempool chain</source>
- <translation>A transação é muito grande de uma cadeia do banco de memória</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>A transação dever pelo menos um destinatário</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Rede desconhecida especificada em -onlynet: '%s'</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Fundos insuficientes</translation>
- </message>
- <message>
- <source>Cannot write to data directory '%s'; check permissions.</source>
- <translation>Não foi possível escrever na pasta de dados '%s': verifique as permissões.</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>A carregar o índice de blocos...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>A carregar a carteira...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Impossível mudar a carteira para uma versão anterior</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Reexaminando...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Carregamento concluído</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Erro</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ro.ts b/src/qt/locale/bitcoin_ro.ts
index 74f9504fba..333a191ed3 100644
--- a/src/qt/locale/bitcoin_ro.ts
+++ b/src/qt/locale/bitcoin_ro.ts
@@ -334,14 +334,6 @@
<translation>Schimbă fraza de acces folosită pentru criptarea portofelului</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Fereastra de &amp;depanare</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Deschide consola de depanare şi diagnosticare</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verifică mesaj...</translation>
</message>
@@ -402,10 +394,6 @@
<translation>Arată lista de adrese pentru primire şi etichetele</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Deschidere bitcoin: o adresa URI sau o cerere de plată</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Opţiuni linie de &amp;comandă</translation>
</message>
@@ -792,10 +780,6 @@
<translation>versiunea</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Despre %1</translation>
</message>
@@ -925,25 +909,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Deschide URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Deschideţi cerere de plată prin intermediul adresei URI sau a fişierului</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Selectaţi fişierul cerere de plată</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Selectati care fisier de cerere de plata va fi deschis</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1032,7 +1000,7 @@
</message>
<message>
<source>Prune &amp;block storage to</source>
- <translation>Reductie &amp;block storage la </translation>
+ <translation>Reductie &amp;block storage la</translation>
</message>
<message>
<source>GB</source>
@@ -1040,7 +1008,7 @@
</message>
<message>
<source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation> Inversarea acestei setari necesita re-descarcarea intregului blockchain.</translation>
+ <translation>Inversarea acestei setari necesita re-descarcarea intregului blockchain.</translation>
</message>
<message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
@@ -1200,7 +1168,7 @@
</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>Fisierul de configurare e folosit pentru a specifica optiuni utilizator avansate care modifica setarile din GUI. In plus orice optiune din linia de comanda va modifica acest fisier de configurare. </translation>
+ <translation>Fisierul de configurare e folosit pentru a specifica optiuni utilizator avansate care modifica setarile din GUI. In plus orice optiune din linia de comanda va modifica acest fisier de configurare.</translation>
</message>
<message>
<source>Error</source>
@@ -1313,10 +1281,6 @@
<translation>'bitcoin://' nu este un URI valid. Folositi 'bitcoin:' in loc.</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL-ul cererii de plată preluat nu este valid: %1</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>Adresă pentru plată invalidă %1</translation>
</message>
@@ -1328,66 +1292,6 @@
<source>Payment request file handling</source>
<translation>Manipulare fişier cerere de plată</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Fişierul cerere de plată nu poate fi citit! Cauza poate fi un fişier cerere de plată nevalid.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Cerere de plată refuzată</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Cererea de plată din reţea nu se potriveşte cu clientul din reţea</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Cerere de plată expirata</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Cererea de plată nu este iniţializată.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Cererile nesecurizate către scripturi personalizate de plăți nu sunt suportate</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Cerere de plată invalidă.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Suma cerută de plată de %1 este prea mică (considerată praf).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Rambursare de la %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Cererea de plată %1 este prea mare (%2 octeţi, permis %3 octeţi).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Eroare la comunicarea cu %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Cererea de plată nu poate fi analizată!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Răspuns greşit de la server %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Eroare în cererea de reţea</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Plată acceptată</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1561,10 +1465,6 @@
<translation>&amp;Informaţii</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Fereastra de depanare</translation>
- </message>
- <message>
<source>General</source>
<translation>General</translation>
</message>
@@ -2089,10 +1989,6 @@
<translation>Avertisment: Estimarea comisionului nu s-a putut efectua.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>inchide setarile de taxare</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>
@@ -2257,12 +2153,8 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<translation>Creare tranzacţie nereuşită!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Tranzactia a fost refuzata pentru urmatorul motiv: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation> O taxă mai mare de %1 este considerată o taxă absurd de mare </translation>
+ <translation>O taxă mai mare de %1 este considerată o taxă absurd de mare</translation>
</message>
<message>
<source>Payment request expired.</source>
@@ -2312,10 +2204,6 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<translation>Alegeţi adrese folosite anterior</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Aceasta este o tranzacţie normală.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Adresa bitcoin către care se face plata</translation>
</message>
@@ -2375,17 +2263,6 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<source>Memo:</source>
<translation>Memo:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Introduceţi o etichetă pentru această adresă pentru a fi adăugată în lista dvs. de adrese</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Da</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2534,7 +2411,7 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
</message>
<message>
<source>Message verified.</source>
- <translation>Mesaj verificat. </translation>
+ <translation>Mesaj verificat.</translation>
</message>
</context>
<context>
@@ -3106,10 +2983,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Rescanarile nu sunt posibile in modul redus. Va trebui sa folositi -reindex, ceea ce va descarca din nou intregul blockchain.</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>
@@ -3450,12 +3323,8 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<translation>Aceasta este taxa de tranzactie pe care este posibil sa o platiti daca estimarile de taxe nu sunt disponibile.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Acest produs include software dezvoltat de OpenSSL Project pentru a fi folosit in Toolkitul OpenSSL %s, software criptografic scris de Eric Young si software UPnP scris de Thomas Bernard. </translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <translation>Lungimea totala a sirului versiunii retelei (%i) depaseste lungimea maxima (%i). Reduceti numarul sa dimensiunea uacomments. </translation>
+ <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>
diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts
deleted file mode 100644
index 79c7d12a5c..0000000000
--- a/src/qt/locale/bitcoin_ro_RO.ts
+++ /dev/null
@@ -1,3659 +0,0 @@
-<TS language="ro_RO" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Click-dreapta pentru a edita adresa sau eticheta</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Creează o adresă nouă</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Nou</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Copiază adresa selectată în clipboard</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Copiază</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>Î&amp;nchide</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Şterge adresa selectată din listă</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Introduceţi adresa sau eticheta pentru căutare</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportă datele din tab-ul curent într-un fişier</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportă</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Şterge</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Alege $adresa unde să trimiteţi monede</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Alege adresa la care sa primesti monedele cu</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>A&amp;lege</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Adresa de trimitere</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Adresa de primire</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>Acestea sunt adresele tale Bitcoin pentru efectuarea platilor. Intotdeauna verifica atent suma de plata si adresa beneficiarului inainte de a trimite monede.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Acestea sunt adresele tale Bitcoin pentru receptionarea platilor. Este recomandat sa folosesti mereu o adresa noua pentru primirea platilor.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Copiază Adresa</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Copiaza si eticheteaza</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Editare</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Exportă listă de adrese</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Fisier cu separator virgulă (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Export nereusit</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>A apărut o eroare la salvarea listei de adrese la %1. Vă rugăm să încercaţi din nou.</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Etichetă</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresă</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(fără etichetă)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Dialogul pentru fraza de acces</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Introduceţi fraza de acces</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Frază de acces nouă</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Repetaţi noua frază de acces</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Arata parola</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Introduceţi noua parolă a portofelului electronic.&lt;br/&gt;Vă rugăm să folosiţi o parolă de&lt;b&gt;minimum 10 caractere aleatoare&lt;/b&gt;, sau &lt;b&gt;minimum 8 cuvinte&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Criptare portofel</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Această acţiune necesită introducerea parolei de acces pentru deblocarea portofelului.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Deblocare portofel</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Această acţiune necesită introducerea parolei de acces pentru decriptarea portofelului.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Decriptare portofel</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Schimbă parola</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Introduceţi vechea şi noua parolă pentru portofel.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Confirmaţi criptarea portofelului</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Atenţie: Dacă va criptati portofelul si ulterior pierdeti parola, &lt;b&gt;VEŢI PIERDE TOTI BITCOINII&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Sigur doriţi să criptaţi portofelul dvs.?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Portofel criptat</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 se va închide acum pentru a termina procesul de criptare. Ţineţi minte că criptarea portofelului nu vă poate proteja în totalitate de furtul monedelor de către programe malware care vă infectează calculatorul.</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>IMPORTANT: Orice copie de siguranţă făcută anterior portofelului dumneavoastră ar trebui înlocuită cu cea generată cel mai recent, fişier criptat al portofelului. Pentru siguranţă, copiile de siguranţă vechi ale portofelului ne-criptat vor deveni inutile imediat ce veţi începe folosirea noului fişier criptat al portofelului.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Criptarea portofelului a eşuat.</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Criptarea portofelului nu a reuşit din cauza unei erori interne. Portofelul dvs. nu a fost criptat.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Parolele furnizate nu se potrivesc.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Deblocarea portofelului a esuat.</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Parola introdusă pentru decriptarea portofelului a fost incorectă.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Decriptarea portofelului a esuat.</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Parola portofelului a fost schimbata.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Atenţie! Caps Lock este pornit!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmask</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Banat până la</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Semnează &amp;mesaj...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Se sincronizează cu reţeaua...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Imagine de ansamblu</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Nod</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Arată o stare generală de ansamblu a portofelului</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Tranzacţii</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Răsfoire istoric tranzacţii</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>Ieşire</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Închide aplicaţia</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Despre %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Arată informaţii despre %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Despre &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Arată informaţii despre Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Opţiuni...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Modifică opţiunile de configurare pentru %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>Cript&amp;ează portofelul...</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>Face o copie de siguranţă a portofelului...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>S&amp;chimbă parola...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>Adrese de trimitere...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Adrese de p&amp;rimire...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Deschide &amp;URI...</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>Portofel:</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>portofel implicit</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Click pentru a opri activitatea retelei.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Activitatea retelei a fost oprita.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Click pentu a porni activitatea retelei.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Se sincronizeaza Header-ele (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Se reindexează blocurile pe disc...</translation>
- </message>
- <message>
- <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>Proxy este&lt;b&gt;activat&lt;/b&gt;:%1</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Trimite monede către o adresă Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Creează o copie de rezervă a portofelului într-o locaţie diferită</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Schimbă fraza de acces folosită pentru criptarea portofelului</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>Fereastra de &amp;depanare</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Deschide consola de depanare şi diagnosticare</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Verifică mesaj...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Portofel</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>Trimite</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>P&amp;rimeşte</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>Arată/Ascunde</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Arată sau ascunde fereastra principală</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Criptează cheile private ale portofelului dvs.</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Semnaţi mesaje cu adresa dvs. Bitcoin pentru a dovedi că vă aparţin</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Verificaţi mesaje pentru a vă asigura că au fost semnate cu adresa Bitcoin specificată</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Fişier</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Setări</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>A&amp;jutor</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Bara de unelte</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Cereţi plăţi (generează coduri QR şi bitcoin-uri: URls)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Arată lista de adrese trimise şi etichetele folosite.</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Arată lista de adrese pentru primire şi etichetele</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Deschidere bitcoin: o adresa URI sau o cerere de plată</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>Opţiuni linie de &amp;comandă</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n conexiune activă către reţeaua Bitcoin</numerusform><numerusform>%n conexiuni active către reţeaua Bitcoin</numerusform><numerusform>%n de conexiuni active către reţeaua Bitcoin</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Se indexează blocurile pe disc...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Se proceseaza blocurile pe disc...</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>S-a procesat %n bloc din istoricul tranzacţiilor.</numerusform><numerusform>S-au procesat %n blocuri din istoricul tranzacţiilor.</numerusform><numerusform>S-au procesat %n de blocuri din istoricul tranzacţiilor.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 în urmă</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Ultimul bloc recepţionat a fost generat acum %1.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Tranzacţiile după aceasta nu vor fi vizibile încă.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Eroare</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Avertisment</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informaţie</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Actualizat</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Arată mesajul de ajutor %1 pentru a obţine o listă cu opţiunile posibile de linii de comandă Bitcoin</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>Client %1</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Se conecteaza cu alte noduri...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Se actualizează...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Data: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Sumă: %1
-</translation>
- </message>
- <message>
- <source>Wallet: %1
-</source>
- <translation>Portofel: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Tip: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Etichetă: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Adresă: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Tranzacţie expediată</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Tranzacţie recepţionată</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>Generarea de chei HD este &lt;b&gt;activata&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>Generarea de chei HD este &lt;b&gt;dezactivata&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>Portofelul este &lt;b&gt;criptat&lt;/b&gt; iar în momentul de faţă este &lt;b&gt;deblocat&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>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>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Selectarea monedei</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Cantitate:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Octeţi:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Sumă:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Taxă:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Praf:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>După taxă:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Schimb:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(de)selectare tot</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Mod arbore</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Mod listă</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Sumă</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Primite cu eticheta</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Primite cu adresa</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Confirmări</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmat</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Copiază adresa</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copiază eticheta</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiază suma</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copiază ID tranzacţie</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Blocare necheltuiţi</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Deblocare necheltuiţi</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copiază cantitea</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copiază taxa</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Copiază după taxă</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copiază octeţi</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copiază praf</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copiază rest</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>da</translation>
- </message>
- <message>
- <source>no</source>
- <translation>nu</translation>
- </message>
- <message>
- <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Această etichetă devine roşie, dacă orice beneficiar primeşte o sumă mai mică decât pragul curent pentru praf.</translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Poate varia +/- %1 satoshi pentru fiecare intrare.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(fără etichetă)</translation>
- </message>
- <message>
- <source>change from %1 (%2)</source>
- <translation>restul de la %1 (%2)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation>(rest)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Editează adresa</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Etichetă</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>Eticheta asociată cu această intrare din listă.</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>Adresa asociată cu această adresă din listă. Aceasta poate fi modificată doar pentru adresele de trimitere.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Adresă</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Noua adresă de trimitere</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Editează adresa de primire</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Editează adresa de trimitere</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>Adresa introdusă "%1" nu este o adresă Bitcoin validă.</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>Adresa "%1" exista deja ca si adresa de primire cu eticheta "%2" si deci nu poate fi folosita ca si adresa de trimitere.</translation>
- </message>
- <message>
- <source>The entered address "%1" is already in the address book with label "%2".</source>
- <translation>Adresa introdusa "%1" este deja in lista de adrese cu eticheta "%2"</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Portofelul nu a putut fi deblocat.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Generarea noii chei nu a reuşit.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Va fi creat un nou dosar de date.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>nume</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>Dosarul deja există. Adaugă %1 dacă intenţionaţi să creaţi un nou dosar aici.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Calea deja există şi nu este un dosar.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Nu se poate crea un dosar de date aici.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>versiunea</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>Despre %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Opţiuni linie de comandă</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Bun venit</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Bun venit la %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>Deoarece este prima lansare a programului poți alege unde %1 va stoca datele sale.</translation>
- </message>
- <message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation>Cand apasati OK, %1 va incepe descarcarea si procesarea intregului %4 blockchain (%2GB) incepand cu cele mai vechi tranzactii din %3 de la lansarea initiala a %4.</translation>
- </message>
- <message>
- <source>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>Sincronizarea initiala necesita foarte multe resurse, si poate releva probleme de hardware ale computerului care anterior au trecut neobservate. De fiecare data cand rulati %1, descarcarea va continua de unde a fost intrerupta.</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>Daca ati ales o limita pentru capacitatea de stocare a blockchainului (pruning), datele mai vechi tot trebuie sa fie descarcate si procesate, insa vor fi sterse ulterior pentru a reduce utilizarea harddiskului.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Foloseşte dosarul de date implicit</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Foloseşte un dosar de date personalizat:</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation>Cel putin %1GB de date vor fi stocate in acest director, si aceasta valoare va creste in timp.</translation>
- </message>
- <message>
- <source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>Aproximativ %1 GB de date vor fi stocate in acest director.</translation>
- </message>
- <message>
- <source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 va descarca si stoca o copie a blockchainului Bitcoin</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation>Portofelul va fi de asemeni stocat in acest director.</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Eroare: Directorul datelor specificate "%1" nu poate fi creat.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Eroare</translation>
- </message>
- <message numerus="yes">
- <source>%n GB of free space available</source>
- <translation><numerusform>%n GB de spaţiu liber disponibil</numerusform><numerusform>%n GB de spaţiu liber disponibil</numerusform><numerusform>%n GB de spaţiu liber disponibil</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>(of %n GB needed)</source>
- <translation><numerusform>(din %n GB necesar)</numerusform><numerusform>(din %n GB necesari)</numerusform><numerusform>(din %n GB necesari)</numerusform></translation>
- </message>
-</context>
-<context>
- <name>ModalOverlay</name>
- <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>Tranzactiile recente pot sa nu fie inca vizibile, de aceea balanta portofelului poate fi incorecta. Aceasta informatie va fi corecta de indata ce portofelul va fi complet sincronizat cu reteaua Bitcoin, asa cum este detaliat mai jos.</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>Incercarea de a cheltui bitcoini care sunt afectati de tranzactii ce inca nu sunt afisate nu va fi acceptata de retea.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Numarul de blocuri ramase</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Necunoscut...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Data ultimului bloc</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation>Progres</translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation>Cresterea progresului per ora</translation>
- </message>
- <message>
- <source>calculating...</source>
- <translation>calculeaza...</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation>Timp estimat pana la sincronizare</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Ascunde</translation>
- </message>
- <message>
- <source>Unknown. Syncing Headers (%1)...</source>
- <translation>Necunoscut. Se sincronizeaza headerele (%1)...</translation>
- </message>
-</context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Deschide URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Deschideţi cerere de plată prin intermediul adresei URI sau a fişierului</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Selectaţi fişierul cerere de plată</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Selectati care fisier de cerere de plata va fi deschis</translation>
- </message>
-</context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Opţiuni</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>Principal</translation>
- </message>
- <message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation>Porneşte automat %1 după logarea in sistem.</translation>
- </message>
- <message>
- <source>&amp;Start %1 on system login</source>
- <translation>&amp;Porneste %1 la logarea in sistem.</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Mărimea bazei de &amp;date cache</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>Numărul de thread-uri de &amp;verificare</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Adresa IP a serverului proxy (de exemplu: 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>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>
- <message>
- <source>&amp;Hide tray icon</source>
- <translation>&amp;Ascunde icon-ul din system tray.</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>Minimizează fereastra în locul părăsirii programului în momentul închiderii ferestrei. Cînd acestă opţiune e activă, aplicaţia se va opri doar în momentul selectării comenzii 'Închide aplicaţia' din 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>URL-uri terţe părţi (de exemplu, un explorator de bloc), care apar în tab-ul tranzacţiilor ca elemente de meniu contextual. %s în URL este înlocuit cu hash de tranzacţie. URL-urile multiple sînt separate prin bară verticală |.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Opţiuni linie de comandă active care oprimă opţiunile de mai sus:</translation>
- </message>
- <message>
- <source>Open the %1 configuration file from the working directory.</source>
- <translation>Deschide fisierul de configurare %1 din directorul curent.</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Deschide fisierul de configurare.</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Resetează toate setările clientului la valorile implicite.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Resetează opţiunile</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>Reţea</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>Dezactiveaza unele caracteristici avansate insa toate blocurile vor fi validate pe deplin. Inversarea acestei setari necesita re-descarcarea intregului blockchain. Utilizarea reala a discului poate fi ceva mai mare.</translation>
- </message>
- <message>
- <source>Prune &amp;block storage to</source>
- <translation>Reductie &amp;block storage la </translation>
- </message>
- <message>
- <source>GB</source>
- <translation>GB</translation>
- </message>
- <message>
- <source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation> Inversarea acestei setari necesita re-descarcarea intregului blockchain.</translation>
- </message>
- <message>
- <source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = automat, &lt;0 = lasă atîtea nuclee libere)</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>Portofel</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Expert</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Activare caracteristici de control ale monedei</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>Dacă dezactivaţi cheltuirea restului neconfirmat, restul dintr-o tranzacţie nu poate fi folosit pînă cînd tranzacţia are cel puţin o confirmare. Aceasta afectează de asemenea calcularea soldului.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>Cheltuire rest neconfirmat</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>Deschide automat în router portul aferent clientului Bitcoin. Funcţionează doar dacă routerul duportă UPnP şi e activat.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Mapare port folosind &amp;UPnP</translation>
- </message>
- <message>
- <source>Accept connections from outside.</source>
- <translation>Acceptă conexiuni din exterior</translation>
- </message>
- <message>
- <source>Allow incomin&amp;g connections</source>
- <translation>Permite conexiuni de intrar&amp;e</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Conectare la reţeaua Bitcoin printr-un proxy SOCKS.</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Conectare printr-un proxy SOCKS (implicit 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>Portul proxy (de exemplu: 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation>Folosit pentru a gasi parteneri 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>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>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Arată doar un icon în tray la ascunderea ferestrei</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimizare în tray în loc de taskbar</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>M&amp;inimizare fereastră în locul închiderii programului</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Afişare</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>&amp;Limbă interfaţă utilizator</translation>
- </message>
- <message>
- <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation>Limba interfeţei utilizatorului poate fi setată aici. Această setare va avea efect după repornirea %1.</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Unitatea de măsură pentru afişarea sumelor:</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Alegeţi subdiviziunea folosită la afişarea interfeţei şi la trimiterea de bitcoin.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Arată controlul caracteristicilor monedei sau nu.</translation>
- </message>
- <message>
- <source>&amp;Third party transaction URLs</source>
- <translation>URL-uri tranzacţii &amp;terţe părţi</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;OK</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>Renunţă</translation>
- </message>
- <message>
- <source>default</source>
- <translation>iniţial</translation>
- </message>
- <message>
- <source>none</source>
- <translation>nimic</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Confirmă resetarea opţiunilor</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Este necesară repornirea clientului pentru a activa schimbările.</translation>
- </message>
- <message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation>Clientul va fi închis. Doriţi să continuaţi?</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Optiuni de configurare</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>Fisierul de configurare e folosit pentru a specifica optiuni utilizator avansate care modifica setarile din GUI. In plus orice optiune din linia de comanda va modifica acest fisier de configurare. </translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Eroare</translation>
- </message>
- <message>
- <source>The configuration file could not be opened.</source>
- <translation>Fisierul de configurare nu a putut fi deschis.</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Această schimbare necesită o repornire a clientului.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Adresa bitcoin pe care aţi specificat-o nu este validă.</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>Informaţiile afişate pot fi neactualizate. Portofelul dvs. se sincronizează automat cu reţeaua Bitcoin după ce o conexiune este stabilită, dar acest proces nu a fost finalizat încă.</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Doar-supraveghere:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Disponibil:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Balanţa dvs. curentă de cheltuieli</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>În aşteptare:</translation>
- </message>
- <message>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Totalul tranzacţiilor care nu sunt confirmate încă şi care nu sunt încă adunate la balanţa de cheltuieli</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Nematurizat:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>Balanţa minata ce nu s-a maturizat încă</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Balanţă</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Total:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Balanţa totală curentă</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>Soldul dvs. curent în adresele doar-supraveghere</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Cheltuibil:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Tranzacţii recente</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Tranzacţii neconfirmate la adresele doar-supraveghere</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Balanţă minată în adresele doar-supraveghere care nu s-a maturizat încă</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>Soldul dvs. total în adresele doar-supraveghere</translation>
- </message>
-</context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Eroare la cererea de plată</translation>
- </message>
- <message>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>Bitcoin nu poate porni: click-to-pay handler</translation>
- </message>
- <message>
- <source>URI handling</source>
- <translation>Gestionare URI</translation>
- </message>
- <message>
- <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
- <translation>'bitcoin://' nu este un URI valid. Folositi 'bitcoin:' in loc.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL-ul cererii de plată preluat nu este valid: %1</translation>
- </message>
- <message>
- <source>Invalid payment address %1</source>
- <translation>Adresă pentru plată invalidă %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 nu poate fi analizat! Acest lucru poate fi cauzat de o adresă Bitcoin invalidă sau parametri URI deformaţi.</translation>
- </message>
- <message>
- <source>Payment request file handling</source>
- <translation>Manipulare fişier cerere de plată</translation>
- </message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Fişierul cerere de plată nu poate fi citit! Cauza poate fi un fişier cerere de plată nevalid.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Cerere de plată refuzată</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Cererea de plată din reţea nu se potriveşte cu clientul din reţea</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Cerere de plată expirata</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Cererea de plată nu este iniţializată.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Cererile nesecurizate către scripturi personalizate de plăți nu sunt suportate</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Cerere de plată invalidă.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Suma cerută de plată de %1 este prea mică (considerată praf).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Rambursare de la %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Cererea de plată %1 este prea mare (%2 octeţi, permis %3 octeţi).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Eroare la comunicarea cu %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Cererea de plată nu poate fi analizată!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Răspuns greşit de la server %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Eroare în cererea de reţea</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Plată acceptată</translation>
- </message>
-</context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>Agent utilizator</translation>
- </message>
- <message>
- <source>Node/Service</source>
- <translation>Nod/Serviciu</translation>
- </message>
- <message>
- <source>NodeId</source>
- <translation>NodeID</translation>
- </message>
- <message>
- <source>Ping</source>
- <translation>Ping</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Expediat</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Recepţionat</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Cantitate</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Introduceţi o adresă Bitcoin (de exemplu %1)</translation>
- </message>
- <message>
- <source>%1 d</source>
- <translation>%1 z</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>Niciuna</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 secunda</numerusform><numerusform>%n secunde</numerusform><numerusform>%n secunde</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n minute(s)</source>
- <translation><numerusform>%n minut</numerusform><numerusform>%n minute</numerusform><numerusform>%n minute</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n hour(s)</source>
- <translation><numerusform>%n ora</numerusform><numerusform>%n ore</numerusform><numerusform>%n ore</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n day(s)</source>
- <translation><numerusform>%n zi</numerusform><numerusform>%n zile</numerusform><numerusform>%n zile</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n week(s)</source>
- <translation><numerusform>%n saptamana</numerusform><numerusform>%n saptamani</numerusform><numerusform>%n saptamani</numerusform></translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 şi %2</translation>
- </message>
- <message numerus="yes">
- <source>%n year(s)</source>
- <translation><numerusform>%n an</numerusform><numerusform>%n ani</numerusform><numerusform>%n ani</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>%1 didn't yet exit safely...</source>
- <translation>%1 nu a fost inchis in siguranta...</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>necunoscut</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- <message>
- <source>Error parsing command line arguments: %1.</source>
- <translation>Eroare la analiza argumentelor linie de comanda: %1</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Eroare: Directorul de date specificat "%1" nu există.</translation>
- </message>
- <message>
- <source>Error: Cannot parse configuration file: %1.</source>
- <translation>Eroare: Nu se poate analiza fişierul de configuraţie: %1.</translation>
- </message>
- <message>
- <source>Error: %1</source>
- <translation>Eroare: %1</translation>
- </message>
-</context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Salvează Imaginea...</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>&amp;Copiaza Imaginea</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>Salvează codul QR</translation>
- </message>
- <message>
- <source>PNG Image (*.png)</source>
- <translation>Imagine de tip PNG (*.png)</translation>
- </message>
-</context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>Nespecificat</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Versiune client</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Informaţii</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Fereastra de depanare</translation>
- </message>
- <message>
- <source>General</source>
- <translation>General</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>Foloseşte BerkeleyDB versiunea</translation>
- </message>
- <message>
- <source>Datadir</source>
- <translation>Dirdate</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Ora de pornire</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Reţea</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Nume</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Numărul de conexiuni</translation>
- </message>
- <message>
- <source>Block chain</source>
- <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>
- <message>
- <source>Current number of transactions</source>
- <translation>Numărul curent de tranzacţii</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Memorie folosită</translation>
- </message>
- <message>
- <source>Wallet: </source>
- <translation>Portofel:</translation>
- </message>
- <message>
- <source>(none)</source>
- <translation>(nimic)</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Resetare</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Recepţionat</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Expediat</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Parteneri</translation>
- </message>
- <message>
- <source>Banned peers</source>
- <translation>Terti banati</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <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>
- <message>
- <source>Version</source>
- <translation>Versiune</translation>
- </message>
- <message>
- <source>Starting Block</source>
- <translation>Bloc de început</translation>
- </message>
- <message>
- <source>Synced Headers</source>
- <translation>Headere Sincronizate</translation>
- </message>
- <message>
- <source>Synced Blocks</source>
- <translation>Blocuri Sincronizate</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>Agent utilizator</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>Deschide fişierul jurnal depanare %1 din directorul curent. Aceasta poate dura cateva secunde pentru fişierele mai mari.</translation>
- </message>
- <message>
- <source>Decrease font size</source>
- <translation>Micsoreaza fontul</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation>Mareste fontul</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Servicii</translation>
- </message>
- <message>
- <source>Ban Score</source>
- <translation>Scor Ban</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Timp conexiune</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Ultima trimitere</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Ultima primire</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Timp ping</translation>
- </message>
- <message>
- <source>The duration of a currently outstanding ping.</source>
- <translation>Durata ping-ului intarziat.</translation>
- </message>
- <message>
- <source>Ping Wait</source>
- <translation>Asteptare ping</translation>
- </message>
- <message>
- <source>Min Ping</source>
- <translation>Min Ping</translation>
- </message>
- <message>
- <source>Time Offset</source>
- <translation>Diferenta timp</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Data ultimului bloc</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Deschide</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Consolă</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>Trafic reţea</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Totaluri</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Intrare:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Ieşire:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Fişier jurnal depanare</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Curăţă consola</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;oră</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;zi</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;săptămână</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;an</translation>
- </message>
- <message>
- <source>&amp;Disconnect</source>
- <translation>&amp;Deconectare</translation>
- </message>
- <message>
- <source>Ban for</source>
- <translation>Interzicere pentru</translation>
- </message>
- <message>
- <source>&amp;Unban</source>
- <translation>&amp;Unban</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>portofel implicit</translation>
- </message>
- <message>
- <source>Welcome to the %1 RPC console.</source>
- <translation>Bun venit la consola %1 RPC.</translation>
- </message>
- <message>
- <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
- <translation>Folosiţi săgetile sus şi jos pentru a naviga în istoric şi %1 pentru a curăţa ecranul.</translation>
- </message>
- <message>
- <source>Type %1 for an overview of available commands.</source>
- <translation>Tastati %1 pentru o recapitulare a comenzilor disponibile.</translation>
- </message>
- <message>
- <source>For more information on using this console type %1.</source>
- <translation>Pentru mai multe informatii despre folosirea acestei console tastati %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>ATENTIONARE: Sunt excroci care instruiesc userii sa introduca aici comenzi, pentru a le fura continutul portofelelor. Nu folositi aceasta consolă fara a intelege pe deplin ramificatiile unei comenzi.</translation>
- </message>
- <message>
- <source>Network activity disabled</source>
- <translation>Activitatea retelei a fost oprita.</translation>
- </message>
- <message>
- <source>Executing command without any wallet</source>
- <translation>Executarea comenzii fara nici un portofel.</translation>
- </message>
- <message>
- <source>Executing command using "%1" wallet</source>
- <translation>Executarea comenzii folosind portofelul "%1"</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>niciodată</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Intrare</translation>
- </message>
- <message>
- <source>Outbound</source>
- <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>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>Sum&amp;a:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Etichetă:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Mesaj:</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 mesaj opţional de ataşat la cererea de plată, care va fi afişat cînd cererea este deschisă. Notă: Acest mesaj nu va fi trimis cu plata către reţeaua Bitcoin.</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation>O etichetă opţională de asociat cu adresa de primire.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Foloseşte acest formular pentru a solicita plăţi. Toate cîmpurile sînt &lt;b&gt;opţionale&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>O sumă opţională de cerut. Lăsaţi gol sau zero pentru a nu cere o sumă anume.</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Curăţă toate cîmpurile formularului.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Curăţă</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>Adresele native segwit (aka Bech32 sau BIP-173) vor reduce mai tarziu comisioanele de tranzactionare si vor oferi o mai buna protectie impotriva introducerii gresite, dar portofelele vechi nu sunt compatibile. Daca optiunea nu e bifata, se va crea o adresa compatibila cu portofelele vechi.</translation>
- </message>
- <message>
- <source>Generate native segwit (Bech32) address</source>
- <translation>Genereaza adresa nativa segwit (Bech32)</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>Istoricul plăţilor cerute</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Cerere plată</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Arată cererea selectată (acelaşi lucru ca şi dublu-clic pe o înregistrare)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Arată</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Înlătură intrările selectate din listă</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Înlătură</translation>
- </message>
- <message>
- <source>Copy URI</source>
- <translation>Copiază URl</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copiază eticheta</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Copiază mesajul</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiază suma</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>Cod QR</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Copiază &amp;URl</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Copiază &amp;adresa</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Salvează imaginea...</translation>
- </message>
- <message>
- <source>Request payment to %1</source>
- <translation>Cere plata pentru %1</translation>
- </message>
- <message>
- <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>
- <message>
- <source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation>URI rezultat este prea lung, încearcă să reduci textul pentru etichetă / mesaj.</translation>
- </message>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation>Eroare la codarea URl-ului în cod QR.</translation>
- </message>
-</context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etichetă</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mesaj</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(fără etichetă)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation>(nici un mesaj)</translation>
- </message>
- <message>
- <source>(no amount requested)</source>
- <translation>(nici o sumă solicitată)</translation>
- </message>
- <message>
- <source>Requested</source>
- <translation>Ceruta</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Trimite monede</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Caracteristici de control ale monedei</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Intrări...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>selecţie automată</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Fonduri insuficiente!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Cantitate:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Octeţi:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Sumă:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Comision:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>După taxă:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Rest:</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>Dacă este activat, dar adresa de rest este goală sau nevalidă, restul va fi trimis la o adresă nou generată.</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Adresă personalizată de rest</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Taxă tranzacţie:</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Alegeţi...</translation>
- </message>
- <message>
- <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
- <translation>Folosirea taxei implicite poate rezulta in trimiterea unei tranzactii care va dura cateva ore sau zile (sau niciodata) pentru a fi confirmata. Luati in considerare sa setati manual taxa sau asteptati pana ati validat complet lantul.</translation>
- </message>
- <message>
- <source>Warning: Fee estimation is currently not possible.</source>
- <translation>Avertisment: Estimarea comisionului nu s-a putut efectua.</translation>
- </message>
- <message>
- <source>collapse fee-settings</source>
- <translation>inchide setarile de taxare</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>Specificati o taxa anume pe kB (1000 byte) din marimea virtuala a tranzactiei.
-
-Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o tranzactie de 500 byte (jumatate de kB) va produce o taxa de doar 50 satoshi.</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>per kilooctet</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Ascunde</translation>
- </message>
- <message>
- <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
- <translation>Plata unei taxe minime de tranzactie este in regula atata timp cat exista mai mult spatiu in blocuri dacat sunt tranzactii. Insa trebuie sa fiti constienti ca acest lucru poate conduce la tranzactii care nu vor fi niciodata confirmate in cazul in care exista cerere de tranzactii mai mare decat poate procesa reteaua.</translation>
- </message>
- <message>
- <source>(read the tooltip)</source>
- <translation>(citeste tooltip)</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Recomandat:</translation>
- </message>
- <message>
- <source>Custom:</source>
- <translation>Personalizat:</translation>
- </message>
- <message>
- <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(Taxa smart nu este inca initializata. Aceasta poate dura cateva blocuri...)</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Trimite simultan către mai mulţi destinatari</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>Adaugă destinata&amp;r</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Şterge toate câmpurile formularului.</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Praf:</translation>
- </message>
- <message>
- <source>Confirmation time target:</source>
- <translation>Timp confirmare tinta:</translation>
- </message>
- <message>
- <source>Enable Replace-By-Fee</source>
- <translation>Autorizeaza 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>Cu Replace-By-Fee (BIP-125) se poate creste taxa unei tranzactii dupa ce a fost trimisa. Fara aceasta optiune, o taxa mai mare e posibil sa fie recomandata pentru a compensa riscul crescut de intarziere a tranzactiei.</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Curăţă to&amp;ate</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Balanţă:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Confirmă operaţiunea de trimitere</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>Trimit&amp;e</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Copiază cantitea</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiază suma</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Copiază taxa</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Copiază după taxă</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Copiază octeţi</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Copiază praf</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Copiază rest</translation>
- </message>
- <message>
- <source>%1 (%2 blocks)</source>
- <translation>%1(%2 blocuri)</translation>
- </message>
- <message>
- <source>%1 to %2</source>
- <translation>%1 la %2</translation>
- </message>
- <message>
- <source>Are you sure you want to send?</source>
- <translation>Sigur doriţi să trimiteţi?</translation>
- </message>
- <message>
- <source>or</source>
- <translation>sau</translation>
- </message>
- <message>
- <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
- <translation>Puteti creste taxa mai tarziu (semnaleaza Replace-By-Fee, BIP-125).</translation>
- </message>
- <message>
- <source>from wallet %1</source>
- <translation>de la portofelul %1</translation>
- </message>
- <message>
- <source>Please, review your transaction.</source>
- <translation>Va rugam sa revizuiti tranzactia.</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Taxă tranzacţie</translation>
- </message>
- <message>
- <source>Not signalling Replace-By-Fee, BIP-125.</source>
- <translation>Nu se semnalizeaza Replace-By-Fee, BIP-125</translation>
- </message>
- <message>
- <source>Total Amount</source>
- <translation>Suma totală</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation>Confirmă trimiterea monedelor</translation>
- </message>
- <message>
- <source>The recipient address is not valid. Please recheck.</source>
- <translation>Adresa destinatarului nu este validă. Rugăm să reverificaţi.</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation>Suma de plată trebuie să fie mai mare decît 0.</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation>Suma depăşeşte soldul contului.</translation>
- </message>
- <message>
- <source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>Totalul depăşeşte soldul contului dacă se include şi plata taxei de %1.</translation>
- </message>
- <message>
- <source>Duplicate address found: addresses should only be used once each.</source>
- <translation>Adresă duplicat găsită: fiecare adresă ar trebui folosită o singură dată.</translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation>Creare tranzacţie nereuşită!</translation>
- </message>
- <message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Tranzactia a fost refuzata pentru urmatorul motiv: %1</translation>
- </message>
- <message>
- <source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation> O taxă mai mare de %1 este considerată o taxă absurd de mare </translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Cerere de plată expirata</translation>
- </message>
- <message>
- <source>Pay only the required fee of %1</source>
- <translation>Plăteşte doar taxa solicitata de %1</translation>
- </message>
- <message numerus="yes">
- <source>Estimated to begin confirmation within %n block(s).</source>
- <translation><numerusform>Se estimeaza inceperea confirmarii in %n bloc.</numerusform><numerusform>Se estimeaza inceperea confirmarii in %n blocuri.</numerusform><numerusform>Se estimeaza inceperea confirmarii in %n blocuri.</numerusform></translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation>Atenţie: Adresa bitcoin nevalidă!</translation>
- </message>
- <message>
- <source>Warning: Unknown change address</source>
- <translation>Atenţie: Adresă de rest necunoscută</translation>
- </message>
- <message>
- <source>Confirm custom change address</source>
- <translation>Confirmati adresa personalizata de rest</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>Adresa selectata pentru rest nu face parte din acest portofel. Orice suma, sau intreaga suma din portofel poate fi trimisa la aceasta adresa. Sunteti sigur?</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(fără etichetă)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>Su&amp;mă:</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>Plăteşte că&amp;tre:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Etichetă:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Alegeţi adrese folosite anterior</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Aceasta este o tranzacţie normală.</translation>
- </message>
- <message>
- <source>The Bitcoin address to send the payment to</source>
- <translation>Adresa bitcoin către care se face plata</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Lipeşte adresa din clipboard</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Înlătură această intrare</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>Taxa va fi scazuta in suma trimisa. Destinatarul va primi mai putini bitcoin decat ati specificat in campul sumei trimise. Daca au fost selectati mai multi destinatari, taxa se va imparti in mod egal.</translation>
- </message>
- <message>
- <source>S&amp;ubtract fee from amount</source>
- <translation>S&amp;cade taxa din suma</translation>
- </message>
- <message>
- <source>Use available balance</source>
- <translation>Folosește balanța disponibilă</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Mesaj:</translation>
- </message>
- <message>
- <source>This is an unauthenticated payment request.</source>
- <translation>Aceasta este o cerere de plata neautentificata.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation>Aceasta este o cerere de plata autentificata.</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Introduceţi eticheta pentru ca această adresa să fie introdusă în lista de adrese folosite</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 mesaj a fost ataşat la bitcoin: URI care va fi stocat cu tranzacţia pentru referinţa dvs. Notă: Acest mesaj nu va fi trimis către reţeaua bitcoin.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Plăteşte către:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Memo:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Introduceţi o etichetă pentru această adresă pentru a fi adăugată în lista dvs. de adrese</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Da</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>%1 is shutting down...</source>
- <translation>%1 se închide</translation>
- </message>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>Nu închide calculatorul pînă ce această fereastră nu dispare.</translation>
- </message>
-</context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Semnaturi - Semnează/verifică un mesaj</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Semnează mesaj</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>Puteţi semna mesaje/contracte cu adresele dvs. pentru a demostra ca puteti primi bitcoini trimisi la ele. Aveţi grijă să nu semnaţi nimic vag sau aleator, deoarece atacurile de tip phishing vă pot păcăli să le transferaţi identitatea. Semnaţi numai declaraţiile detaliate cu care sînteti de acord.</translation>
- </message>
- <message>
- <source>The Bitcoin address to sign the message with</source>
- <translation>Adresa cu care semnaţi mesajul</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Alegeţi adrese folosite anterior</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Lipeşte adresa copiată din 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>Introduceţi mesajul pe care vreţi să-l semnaţi, aici</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Semnătură</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Copiază semnatura curentă în clipboard-ul sistemului</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Semnează mesajul pentru a dovedi ca deţineţi acestă adresă Bitcoin</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Semnează &amp;mesaj</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Resetează toate cîmpurile mesajelor semnate</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Curăţă to&amp;ate</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Verifică mesaj</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>Introduceţi adresa de semnatură, mesajul (asiguraţi-vă că aţi copiat spaţiile, taburile etc. exact) şi semnatura dedesubt pentru a verifica mesajul. Aveţi grijă să nu citiţi mai mult în semnatură decît mesajul în sine, pentru a evita să fiţi păcăliţi de un atac de tip man-in-the-middle. De notat ca aceasta dovedeste doar ca semnatarul primeste odata cu adresa, nu dovedesta insa trimiterea vreunei tranzactii.</translation>
- </message>
- <message>
- <source>The Bitcoin address the message was signed with</source>
- <translation>Introduceţi o adresă Bitcoin</translation>
- </message>
- <message>
- <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Verificaţi mesajul pentru a vă asigura că a fost semnat cu adresa Bitcoin specificată</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Verifică &amp;mesaj</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Resetează toate cîmpurile mesajelor semnate</translation>
- </message>
- <message>
- <source>Click "Sign Message" to generate signature</source>
- <translation>Faceţi clic pe "Semneaza msaj" pentru a genera semnătura</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation>Adresa introdusă este invalidă.</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Vă rugăm verificaţi adresa şi încercaţi din nou.</translation>
- </message>
- <message>
- <source>The entered address does not refer to a key.</source>
- <translation>Adresa introdusă nu se referă la o cheie.</translation>
- </message>
- <message>
- <source>Wallet unlock was cancelled.</source>
- <translation>Deblocarea portofelului a fost anulata.</translation>
- </message>
- <message>
- <source>Private key for the entered address is not available.</source>
- <translation>Cheia privată pentru adresa introdusă nu este disponibila.</translation>
- </message>
- <message>
- <source>Message signing failed.</source>
- <translation>Semnarea mesajului nu a reuşit.</translation>
- </message>
- <message>
- <source>Message signed.</source>
- <translation>Mesaj semnat.</translation>
- </message>
- <message>
- <source>The signature could not be decoded.</source>
- <translation>Semnatura nu a putut fi decodată.</translation>
- </message>
- <message>
- <source>Please check the signature and try again.</source>
- <translation>Vă rugăm verificaţi semnătura şi încercaţi din nou.</translation>
- </message>
- <message>
- <source>The signature did not match the message digest.</source>
- <translation>Semnatura nu se potriveşte cu mesajul.</translation>
- </message>
- <message>
- <source>Message verification failed.</source>
- <translation>Verificarea mesajului nu a reuşit.</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation>Mesaj verificat. </translation>
- </message>
-</context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <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>Deschis pentru inca un bloc</numerusform><numerusform>Deschis pentru inca %n blocuri</numerusform><numerusform>Deschis pentru inca %n blocuri</numerusform></translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Deschis pînă la %1</translation>
- </message>
- <message>
- <source>conflicted with a transaction with %1 confirmations</source>
- <translation>in conflict cu o tranzactie cu %1 confirmari</translation>
- </message>
- <message>
- <source>0/unconfirmed, %1</source>
- <translation>0/neconfirmat, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation>in memory pool</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation>nu e in memory pool</translation>
- </message>
- <message>
- <source>abandoned</source>
- <translation>abandonat</translation>
- </message>
- <message>
- <source>%1/unconfirmed</source>
- <translation>%1/neconfirmat</translation>
- </message>
- <message>
- <source>%1 confirmations</source>
- <translation>%1 confirmări</translation>
- </message>
- <message>
- <source>Status</source>
- <translation>Stare</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Sursa</translation>
- </message>
- <message>
- <source>Generated</source>
- <translation>Generat</translation>
- </message>
- <message>
- <source>From</source>
- <translation>De la</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>necunoscut</translation>
- </message>
- <message>
- <source>To</source>
- <translation>Către</translation>
- </message>
- <message>
- <source>own address</source>
- <translation>adresa proprie</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>doar-supraveghere</translation>
- </message>
- <message>
- <source>label</source>
- <translation>etichetă</translation>
- </message>
- <message>
- <source>Credit</source>
- <translation>Credit</translation>
- </message>
- <message numerus="yes">
- <source>matures in %n more block(s)</source>
- <translation><numerusform>se matureaza intr-un bloc</numerusform><numerusform>se matureaza in %n blocuri</numerusform><numerusform>se matureaza in %n blocuri</numerusform></translation>
- </message>
- <message>
- <source>not accepted</source>
- <translation>neacceptat</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>Taxă tranzacţie</translation>
- </message>
- <message>
- <source>Net amount</source>
- <translation>Suma netă</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mesaj</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Comentariu</translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation>ID tranzacţie</translation>
- </message>
- <message>
- <source>Transaction total size</source>
- <translation>Dimensiune totala tranzacţie</translation>
- </message>
- <message>
- <source>Transaction virtual size</source>
- <translation>Dimensiune virtuala a tranzactiei</translation>
- </message>
- <message>
- <source>Output index</source>
- <translation>Index debit</translation>
- </message>
- <message>
- <source>Merchant</source>
- <translation>Comerciant</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>Monedele generate se pot cheltui doar dupa inca %1 blocuri. După ce a fost generat, s-a propagat în reţea, urmând să fie adăugat in blockchain. Dacă nu poate fi inclus in lanţ, starea sa va deveni "neacceptat" si nu va putea fi folosit la tranzacţii. Acest fenomen se întâmplă atunci cand un alt nod a generat un bloc la o diferenţa de câteva secunde.</translation>
- </message>
- <message>
- <source>Debug information</source>
- <translation>Informaţii pentru depanare</translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation>Tranzacţie</translation>
- </message>
- <message>
- <source>Inputs</source>
- <translation>Intrări</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantitate</translation>
- </message>
- <message>
- <source>true</source>
- <translation>adevărat</translation>
- </message>
- <message>
- <source>false</source>
- <translation>fals</translation>
- </message>
-</context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Acest panou arată o descriere detaliată a tranzacţiei</translation>
- </message>
- <message>
- <source>Details for %1</source>
- <translation>Detalii pentru %1</translation>
- </message>
-</context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tip</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etichetă</translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Deschis pînă la %1</translation>
- </message>
- <message>
- <source>Unconfirmed</source>
- <translation>Neconfirmat</translation>
- </message>
- <message>
- <source>Abandoned</source>
- <translation>Abandonat</translation>
- </message>
- <message>
- <source>Confirming (%1 of %2 recommended confirmations)</source>
- <translation>Confirmare (%1 din %2 confirmari recomandate)</translation>
- </message>
- <message>
- <source>Confirmed (%1 confirmations)</source>
- <translation>Confirmat (%1 confirmari)</translation>
- </message>
- <message>
- <source>Conflicted</source>
- <translation>În conflict</translation>
- </message>
- <message>
- <source>Immature (%1 confirmations, will be available after %2)</source>
- <translation>Imatur (%1 confirmari, va fi disponibil după %2)</translation>
- </message>
- <message>
- <source>Generated but not accepted</source>
- <translation>Generat dar neacceptat</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Recepţionat cu</translation>
- </message>
- <message>
- <source>Received from</source>
- <translation>Primit de la</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Trimis către</translation>
- </message>
- <message>
- <source>Payment to yourself</source>
- <translation>Plată către dvs.</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Minat</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>doar-supraveghere</translation>
- </message>
- <message>
- <source>(n/a)</source>
- <translation>(indisponibil)</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(fără etichetă)</translation>
- </message>
- <message>
- <source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>Starea tranzacţiei. Treceţi cu mouse-ul peste acest cîmp pentru afişarea numărului de confirmari.</translation>
- </message>
- <message>
- <source>Date and time that the transaction was received.</source>
- <translation>Data şi ora la care a fost recepţionată tranzacţia.</translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation>Tipul tranzacţiei.</translation>
- </message>
- <message>
- <source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation>Indiferent dacă sau nu o adresa doar-suăpraveghere este implicată în această tranzacţie.</translation>
- </message>
- <message>
- <source>User-defined intent/purpose of the transaction.</source>
- <translation>Intentie/scop al tranzactie definit de user.</translation>
- </message>
- <message>
- <source>Amount removed from or added to balance.</source>
- <translation>Suma extrasă sau adăugată la sold.</translation>
- </message>
-</context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Toate</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Astăzi</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>Saptamana aceasta</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>Luna aceasta</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Luna trecuta</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Anul acesta</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Interval...</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Recepţionat cu</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Trimis către</translation>
- </message>
- <message>
- <source>To yourself</source>
- <translation>Către dvs.</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Minat</translation>
- </message>
- <message>
- <source>Other</source>
- <translation>Altele</translation>
- </message>
- <message>
- <source>Enter address, transaction id, or label to search</source>
- <translation>Introduceți adresa, ID-ul tranzacției, sau eticheta pentru a căuta</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation>Suma minimă</translation>
- </message>
- <message>
- <source>Abandon transaction</source>
- <translation>Abandoneaza tranzacţia</translation>
- </message>
- <message>
- <source>Increase transaction fee</source>
- <translation>Cresteti comisionul pentru tranzacţie</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Copiază adresa</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Copiază eticheta</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Copiază suma</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Copiază ID tranzacţie</translation>
- </message>
- <message>
- <source>Copy raw transaction</source>
- <translation>Copiază tranzacţia bruta</translation>
- </message>
- <message>
- <source>Copy full transaction details</source>
- <translation>Copiaza toate detaliile tranzacţiei</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Editează eticheta</translation>
- </message>
- <message>
- <source>Show transaction details</source>
- <translation>Arată detaliile tranzacţiei</translation>
- </message>
- <message>
- <source>Export Transaction History</source>
- <translation>Export istoric tranzacţii</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Fisier .csv cu separator - virgula</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Confirmat</translation>
- </message>
- <message>
- <source>Watch-only</source>
- <translation>Doar-supraveghere</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Data</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tip</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etichetă</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresă</translation>
- </message>
- <message>
- <source>ID</source>
- <translation>ID</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Exportarea a eșuat</translation>
- </message>
- <message>
- <source>There was an error trying to save the transaction history to %1.</source>
- <translation>S-a produs o eroare la salvarea istoricului tranzacţiilor la %1.</translation>
- </message>
- <message>
- <source>Exporting Successful</source>
- <translation>Export reuşit</translation>
- </message>
- <message>
- <source>The transaction history was successfully saved to %1.</source>
- <translation>Istoricul tranzacţiilor a fost salvat cu succes la %1.</translation>
- </message>
- <message>
- <source>Range:</source>
- <translation>Interval:</translation>
- </message>
- <message>
- <source>to</source>
- <translation>către</translation>
- </message>
-</context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- <message>
- <source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Unitatea în care sînt arătate sumele. Faceţi clic pentru a selecta o altă unitate.</translation>
- </message>
-</context>
-<context>
- <name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>Nu a fost încărcat nici un portofel.</translation>
- </message>
-</context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Trimite monede</translation>
- </message>
- <message>
- <source>Fee bump error</source>
- <translation>Eroare in cresterea taxei</translation>
- </message>
- <message>
- <source>Increasing transaction fee failed</source>
- <translation>Cresterea comisionului pentru tranzactie a esuat.</translation>
- </message>
- <message>
- <source>Do you want to increase the fee?</source>
- <translation>Doriti sa cresteti taxa de tranzactie?</translation>
- </message>
- <message>
- <source>Current fee:</source>
- <translation>Comision curent:</translation>
- </message>
- <message>
- <source>Increase:</source>
- <translation>Crestere:</translation>
- </message>
- <message>
- <source>New fee:</source>
- <translation>Noul comision:</translation>
- </message>
- <message>
- <source>Confirm fee bump</source>
- <translation>Confirma cresterea comisionului</translation>
- </message>
- <message>
- <source>Can't sign transaction.</source>
- <translation>Nu s-a reuşit semnarea tranzacţiei</translation>
- </message>
- <message>
- <source>Could not commit transaction</source>
- <translation>Tranzactia nu a putut fi consemnata.</translation>
- </message>
-</context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Export</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportă datele din tab-ul curent într-un fişier</translation>
- </message>
- <message>
- <source>Backup Wallet</source>
- <translation>Backup portofelul electronic</translation>
- </message>
- <message>
- <source>Wallet Data (*.dat)</source>
- <translation>Date portofel (*.dat)</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>Backup esuat</translation>
- </message>
- <message>
- <source>There was an error trying to save the wallet data to %1.</source>
- <translation>S-a produs o eroare la salvarea datelor portofelului la %1.</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Backup efectuat cu succes</translation>
- </message>
- <message>
- <source>The wallet data was successfully saved to %1.</source>
- <translation>Datele portofelului s-au salvat cu succes la %1.</translation>
- </message>
- <message>
- <source>Cancel</source>
- <translation>Anulare</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>Distribuit sub licenţa de programe MIT, vezi fişierul însoţitor %s sau %s</translation>
- </message>
- <message>
- <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation>Reductia e configurata sub minimul de %d MiB. Rugam folositi un numar mai mare.</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>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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Rescanarile nu sunt posibile in modul redus. Va trebui sa folositi -reindex, ceea ce va descarca din nou intregul blockchain.</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>
- <message>
- <source>Unable to start HTTP server. See debug log for details.</source>
- <translation>Imposibil de pornit serverul HTTP. Pentru detalii vezi logul de depanare.</translation>
- </message>
- <message>
- <source>Bitcoin Core</source>
- <translation>Nucleul Bitcoin</translation>
- </message>
- <message>
- <source>The %s developers</source>
- <translation>Dezvoltatorii %s</translation>
- </message>
- <message>
- <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
- <translation>Nu se poate obține o blocare a directorului de date %s. %s probabil rulează deja.</translation>
- </message>
- <message>
- <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
- <translation>Nu se pot furniza conexiuni specifice in acelasi timp in care addrman este folosit pentru a gasi conexiuni de iesire.</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>Eroare la citirea %s! Toate cheile sînt citite corect, dar datele tranzactiei sau anumite intrări din agenda sînt incorecte sau lipsesc.</translation>
- </message>
- <message>
- <source>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: %u)</source>
- <translation>Gruparea a iesirilor pe adrese, selectand totul sau nimic, in loc de selectarea bazata per-iesire. Intimitatea este imbunatatita deoarece o adresa este folosita doar o singura data (cu exceptia cuiva care trimite catre aceiasi adresa dup ce cheltuie din ea), dar se pot genera taxe mai mari deoarece poate rezulta o selectare suboptimala a monedelor datorata limitarii impuse (implicit: %u)</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>Vă rugăm verificaţi dacă data/timpul calculatorului dvs. sînt corecte! Dacă ceasul calcultorului este gresit, %s nu va funcţiona corect.</translation>
- </message>
- <message>
- <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <translation>Va rugam sa contribuiti daca apreciati ca %s va este util. Vizitati %s pentru mai multe informatii despre 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>Baza de date a blocurilor contine un bloc ce pare a fi din viitor. Acest lucru poate fi cauzat de setarea incorecta a datei si orei in computerul dvs. Reconstruiti baza de date a blocurilor doar daca sunteti sigur ca data si ora calculatorului dvs sunt corecte.</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>Aceasta este o versiune de test preliminară - vă asumaţi riscul folosind-o - nu folosiţi pentru minerit sau aplicaţiile comercianţilor</translation>
- </message>
- <message>
- <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>Aceasta este taxa de tranzactie la care puteti renunta daca restul este mai mic decat praful la acest nivel.</translation>
- </message>
- <message>
- <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <translation>Imposibil de refacut blocurile. Va trebui sa reconstruiti baza de date folosind -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>Imposibil de a readuce baza de date la statusul pre-fork. Va trebui redescarcat blockchainul.</translation>
- </message>
- <message>
- <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>Atenţie: Reţeaua nu pare să fie de acord în totalitate! Aparent nişte mineri au probleme.</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>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>
- <message>
- <source>Cannot resolve -%s address: '%s'</source>
- <translation>Nu se poate rezolva adresa -%s: '%s'</translation>
- </message>
- <message>
- <source>Change index out of range</source>
- <translation>Indexul de schimbare este iesit din parametrii</translation>
- </message>
- <message>
- <source>Copyright (C) %i-%i</source>
- <translation>Copyright (C) %i-%i</translation>
- </message>
- <message>
- <source>Corrupted block database detected</source>
- <translation>Bloc defect din baza de date detectat</translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Doriţi să reconstruiţi baza de date blocuri acum?</translation>
- </message>
- <message>
- <source>Error creating %s: You can't create non-HD wallets with this version.</source>
- <translation>Eroare la crearea %s: Nu se pot crea portofele non-HD cu aceasta versiune.</translation>
- </message>
- <message>
- <source>Error initializing block database</source>
- <translation>Eroare la iniţializarea bazei de date de blocuri</translation>
- </message>
- <message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Eroare la iniţializarea mediului de bază de date a portofelului %s!</translation>
- </message>
- <message>
- <source>Error loading %s</source>
- <translation>Eroare la încărcarea %s</translation>
- </message>
- <message>
- <source>Error loading %s: Private keys can only be disabled during creation</source>
- <translation>Eroare la incarcarea %s: Cheile private pot fi dezactivate doar in momentul crearii</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet corrupted</source>
- <translation>Eroare la încărcarea %s: Portofel corupt</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet requires newer version of %s</source>
- <translation>Eroare la încărcarea %s: Portofelul are nevoie de o versiune %s mai nouă</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Eroare la încărcarea bazei de date de blocuri</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Eroare la deschiderea bazei de date de blocuri</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Eroare: Spaţiu pe disc redus!</translation>
- </message>
- <message>
- <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>Nu s-a reuşit ascultarea pe orice port. Folosiţi -listen=0 dacă vreţi asta.</translation>
- </message>
- <message>
- <source>Failed to rescan the wallet during initialization</source>
- <translation>Rescanarea portofelului in timpul initializarii a esuat.</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>Import...</translation>
- </message>
- <message>
- <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>Incorect sau nici un bloc de geneza găsit. Directorul de retea greşit?</translation>
- </message>
- <message>
- <source>Initialization sanity check failed. %s is shutting down.</source>
- <translation>Nu s-a reuşit iniţierea verificării sănătăţii. %s se inchide.</translation>
- </message>
- <message>
- <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>Sumă nevalidă pentru -%s=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
- <translation>Sumă nevalidă pentru -discardfee=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>Suma nevalidă pentru -fallbackfee=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Specified blocks directory "%s" does not exist.</source>
- <translation>Directorul de blocuri "%s" specificat nu exista.</translation>
- </message>
- <message>
- <source>Upgrading txindex database</source>
- <translation>Actualizarea bazei de date txindex</translation>
- </message>
- <message>
- <source>Loading P2P addresses...</source>
- <translation>Încărcare adrese P2P...</translation>
- </message>
- <message>
- <source>Loading banlist...</source>
- <translation>Încărcare banlist...</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>Nu sînt destule descriptoare disponibile.</translation>
- </message>
- <message>
- <source>Prune cannot be configured with a negative value.</source>
- <translation>Reductia nu poate fi configurata cu o valoare negativa.</translation>
- </message>
- <message>
- <source>Prune mode is incompatible with -txindex.</source>
- <translation>Modul redus este incompatibil cu -txindex.</translation>
- </message>
- <message>
- <source>Replaying blocks...</source>
- <translation>Se reiau blocurile...</translation>
- </message>
- <message>
- <source>Rewinding blocks...</source>
- <translation>Se deruleaza blocurile...</translation>
- </message>
- <message>
- <source>The source code is available from %s.</source>
- <translation>Codul sursa este disponibil la %s.</translation>
- </message>
- <message>
- <source>Transaction fee and change calculation failed</source>
- <translation>Calcului taxei de tranzactie si a restului a esuat.</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer. %s is probably already running.</source>
- <translation>Nu se poate efectua legatura la %s pe acest computer. %s probabil ruleaza deja.</translation>
- </message>
- <message>
- <source>Unable to generate keys</source>
- <translation>Nu s-au putut genera cheile</translation>
- </message>
- <message>
- <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
- <translation>Argumentul nesuportat -benchmark este ignorat, folositi debug=bench.</translation>
- </message>
- <message>
- <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
- <translation>Argument nesuportat -debugnet ignorat, folosiţi -debug=net.</translation>
- </message>
- <message>
- <source>Unsupported argument -tor found, use -onion.</source>
- <translation>Argument nesuportat -tor găsit, folosiţi -onion.</translation>
- </message>
- <message>
- <source>Unsupported logging category %s=%s.</source>
- <translation>Categoria de logging %s=%s nu este suportata.</translation>
- </message>
- <message>
- <source>Upgrading UTXO database</source>
- <translation>Actualizarea bazei de date UTXO</translation>
- </message>
- <message>
- <source>User Agent comment (%s) contains unsafe characters.</source>
- <translation>Comentariul (%s) al Agentului Utilizator contine caractere nesigure.</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Se verifică blocurile...</translation>
- </message>
- <message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Eroare: Ascultarea conexiunilor de intrare nu a reuşit (ascultarea a reurnat eroarea %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>Sumă nevalidă pentru -maxtxfee=&lt;amount&gt;: '%s' (trebuie să fie cel puţin taxa minrelay de %s pentru a preveni blocarea tranzactiilor)</translation>
- </message>
- <message>
- <source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>Suma tranzactiei este prea mica pentru a fi trimisa dupa ce se scade taxa.</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>Trebuie reconstruita intreaga baza de date folosind -reindex pentru a va intoarce la modul non-redus. Aceasta va determina descarcarea din nou a intregului blockchain</translation>
- </message>
- <message>
- <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
- <translation>Eroare la incarcarea %s: Nu se poate dezactiva HD la un portofel care este deja HD.</translation>
- </message>
- <message>
- <source>Error reading from database, shutting down.</source>
- <translation>Eroare la citirea bazei de date. Oprire.</translation>
- </message>
- <message>
- <source>Error upgrading chainstate database</source>
- <translation>Eroare la actualizarea bazei de date chainstate</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informaţie</translation>
- </message>
- <message>
- <source>Invalid -onion address or hostname: '%s'</source>
- <translation>Adresa sau hostname -onion invalide: '%s'</translation>
- </message>
- <message>
- <source>Invalid -proxy address or hostname: '%s'</source>
- <translation>Adresa sau hostname -proxy invalide: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation>Sumă nevalidă pentru -paytxfee=&lt;suma&gt;: '%s' (trebuie să fie cel puţin %s)</translation>
- </message>
- <message>
- <source>Invalid netmask specified in -whitelist: '%s'</source>
- <translation>Mască reţea nevalidă specificată în -whitelist: '%s'</translation>
- </message>
- <message>
- <source>Need to specify a port with -whitebind: '%s'</source>
- <translation>Trebuie să specificaţi un port cu -whitebind: '%s'</translation>
- </message>
- <message>
- <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <translation>Se micsoreaza -maxconnections de la %d la %d, datorita limitarilor de sistem.</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Nu s-a reuşit semnarea tranzacţiei</translation>
- </message>
- <message>
- <source>Specified -walletdir "%s" does not exist</source>
- <translation>Nu exista -walletdir "%s" specificat</translation>
- </message>
- <message>
- <source>Specified -walletdir "%s" is a relative path</source>
- <translation>-walletdir "%s" specificat este o cale relativa</translation>
- </message>
- <message>
- <source>The transaction amount is too small to pay the fee</source>
- <translation>Suma tranzactiei este prea mica pentru plata taxei</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>Acesta este un program experimental.</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Suma tranzacţionată este prea mică</translation>
- </message>
- <message>
- <source>Transaction too large for fee policy</source>
- <translation>Tranzacţia are suma prea mare pentru a beneficia de gratuitate</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Tranzacţie prea mare</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation>Nu se poate lega la %s pe acest calculator. (Legarea a întors eroarea %s)</translation>
- </message>
- <message>
- <source>Unable to generate initial keys</source>
- <translation>Nu s-au putut genera cheile initiale</translation>
- </message>
- <message>
- <source>Verifying wallet(s)...</source>
- <translation>Se verifică portofelul(ele)...</translation>
- </message>
- <message>
- <source>Wallet %s resides outside wallet directory %s</source>
- <translation>Portofelul %s se află în afara directorului portofelului %s</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Avertisment</translation>
- </message>
- <message>
- <source>Warning: unknown new rules activated (versionbit %i)</source>
- <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>
- <message>
- <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
- <translation>Eroare la incarcarea %s: Nu se poate activa HD la un portofel care este deja non-HD.</translation>
- </message>
- <message>
- <source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation>Aceasta este taxa de tranzactie pe care este posibil sa o platiti daca estimarile de taxe nu sunt disponibile.</translation>
- </message>
- <message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Acest produs include software dezvoltat de OpenSSL Project pentru a fi folosit in Toolkitul OpenSSL %s, software criptografic scris de Eric Young si software UPnP scris de Thomas Bernard. </translation>
- </message>
- <message>
- <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <translation>Lungimea totala a sirului versiunii retelei (%i) depaseste lungimea maxima (%i). Reduceti numarul sa dimensiunea uacomments. </translation>
- </message>
- <message>
- <source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
- <translation>S-a gasit un argument -socks nesuportat. Setarea versiunii SOCKS nu mai este posibila, sunt suportate doar proxiurile SOCKS5.</translation>
- </message>
- <message>
- <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
- <translation>Se ignora argumentul nesuportat -whitelistalwaysrelay, folositi -whitelistrelay si/sau -whitelistforcerelay.</translation>
- </message>
- <message>
- <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
- <translation>Atentie: se mineaza blocuri cu versiune necunoscuta! Este posibil sa fie in vigoare reguli necunoscute.</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>
- <message>
- <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
- <translation>Eroare la incarcarea portofelului %s. Este specificat un fisier -wallet duplicat.</translation>
- </message>
- <message>
- <source>Keypool ran out, please call keypoolrefill first</source>
- <translation>Keypool epuizat, folositi intai functia keypoolrefill</translation>
- </message>
- <message>
- <source>Starting network threads...</source>
- <translation>Se pornesc threadurile retelei...</translation>
- </message>
- <message>
- <source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation>Portofelul va evita sa plateasca mai putin decat minimul taxei de retransmisie.</translation>
- </message>
- <message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Acesta este minimum de taxa de tranzactie care va fi platit la fiecare tranzactie.</translation>
- </message>
- <message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Aceasta este taxa de tranzactie pe care o platiti cand trimiteti o tranzactie.</translation>
- </message>
- <message>
- <source>Transaction amounts must not be negative</source>
- <translation>Sumele tranzactionate nu pot fi negative</translation>
- </message>
- <message>
- <source>Transaction has too long of a mempool chain</source>
- <translation>Tranzacţia are o lungime prea mare in lantul mempool</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>Tranzactia trebuie sa aiba cel putin un destinatar</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Reţeaua specificată în -onlynet este necunoscută: '%s'</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Fonduri insuficiente</translation>
- </message>
- <message>
- <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
- <translation>Nu se poate genera o adresa pentru rest. Cheile private sunt dezactivate pentru acest portofel.</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>
- <message>
- <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <translation>Atentie: S-au detectat chei private in portofelul {%s} cu cheile private dezactivate</translation>
- </message>
- <message>
- <source>Cannot write to data directory '%s'; check permissions.</source>
- <translation>Nu se poate scrie in directorul de date '%s"; verificati permisiunile.</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Încărcare index bloc...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Încărcare portofel...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Nu se poate retrograda portofelul</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Rescanare...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Încărcare terminată</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Eroare</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts
index 4bd02d9f3d..b7515b1a7c 100644
--- a/src/qt/locale/bitcoin_ru.ts
+++ b/src/qt/locale/bitcoin_ru.ts
@@ -67,7 +67,11 @@
</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>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -132,6 +136,10 @@
<translation>Повторите новый пароль</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Показать пароль</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Зашифровать электронный кошелёк</translation>
</message>
@@ -141,15 +149,15 @@
</message>
<message>
<source>Unlock wallet</source>
- <translation>Разблокировать бумажник</translation>
+ <translation>Разблокировать кошелёк</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Данная операция требует введения пароля для расшифровки вашего бумажника.</translation>
+ <translation>Данная операция требует введения пароля для расшифровки вашего кошелька.</translation>
</message>
<message>
<source>Decrypt wallet</source>
- <translation>Расшифровать бумажник</translation>
+ <translation>Расшифровать кошелёк</translation>
</message>
<message>
<source>Change passphrase</source>
@@ -161,7 +169,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>Предупреждение: если вы зашифруете бумажник и потеряете пароль, вы &lt;b&gt;ПОТЕРЯЕТЕ ВСЕ ВАШИ БИТКОИНЫ&lt;/b&gt;!</translation>
+ <translation>Предупреждение: Если вы зашифруете кошелёк и потеряете пароль, вы &lt;b&gt;ПОТЕРЯЕТЕ ВСЕ ВАШИ БИТКОЙНЫ&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -172,8 +180,28 @@
<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;десяти или более случайных символов&lt;/b&gt;, или &lt;b&gt;восьми или более слов&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Введите старый и новый пароль для кошелька.</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>
+ <translation>Помните, что шифрование вашего кошелька не может полностью защитить ваши биткойны от кражи вредоносными программами, заражающими ваш компьютер.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Кошелёк зашифрован</translation>
+ </message>
+ <message>
+ <source>Your wallet is about 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>
@@ -181,7 +209,7 @@
</message>
<message>
<source>Wallet encryption failed</source>
- <translation>Не удалось зашифровать бумажник</translation>
+ <translation>Не удалось зашифровать кошелёк</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
@@ -193,7 +221,7 @@
</message>
<message>
<source>Wallet unlock failed</source>
- <translation>Разблокировка бумажника не удалась</translation>
+ <translation>Не удалось разблокировать кошелёк</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
@@ -205,7 +233,7 @@
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
- <translation>Пароль бумажника успешно изменён.</translation>
+ <translation>Пароль кошелька успешно изменён.</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
@@ -259,7 +287,7 @@
</message>
<message>
<source>&amp;About %1</source>
- <translation>&amp;Около %1</translation>
+ <translation>&amp;О %1</translation>
</message>
<message>
<source>Show information about %1</source>
@@ -287,7 +315,7 @@
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>&amp;Сделать резервную копию бумажника...</translation>
+ <translation>&amp;Резервная копия кошелька...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
@@ -298,8 +326,16 @@
<translation>Открыть &amp;URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Создать кошелёк...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Создать новый кошелёк</translation>
+ </message>
+ <message>
<source>Wallet:</source>
- <translation>Кошелёк</translation>
+ <translation>Кошелёк:</translation>
</message>
<message>
<source>Click to disable network activity.</source>
@@ -327,7 +363,7 @@
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation>Послать средства на биткойн адрес</translation>
+ <translation>Послать средства на Биткойн-адрес</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -338,14 +374,6 @@
<translation>Изменить пароль, используемый для шифрования кошелька</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Окно отладки</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Открыть консоль отладки и диагностики</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Проверить сообщение...</translation>
</message>
@@ -371,11 +399,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>
@@ -406,16 +434,12 @@
<translation>Показать список использованных адресов и меток получателей</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Открыть биткойн: URI или запрос платежа</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Опции командной строки</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n активное подключение к сети Bitcoin</numerusform><numerusform>%n активных подключения к сети Bitcoin</numerusform><numerusform>%n активных подключений к сети Bitcoin</numerusform><numerusform>%n активных подключений к сети Bitcoin</numerusform></translation>
+ <translation><numerusform>%n активное подключение к сети Bitcoin</numerusform><numerusform>%n активных подключения к сети Bitcoin</numerusform><numerusform>%n активных подключений к сети Bitcoin</numerusform><numerusform>%n активных подключений к сети Биткойн</numerusform></translation>
</message>
<message>
<source>Indexing blocks on disk...</source>
@@ -467,19 +491,19 @@
</message>
<message>
<source>Open Wallet</source>
- <translation>Открыть Кошелек</translation>
+ <translation>Открыть Кошелёк</translation>
</message>
<message>
<source>Open a wallet</source>
- <translation>Открыть кошелек</translation>
+ <translation>Открыть кошелёк</translation>
</message>
<message>
<source>Close Wallet...</source>
- <translation>Закрыть Кошелек...</translation>
+ <translation>Закрыть Кошелёк...</translation>
</message>
<message>
<source>Close wallet</source>
- <translation>Закрыть кошелек</translation>
+ <translation>Закрыть кошелёк</translation>
</message>
<message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
@@ -487,7 +511,7 @@
</message>
<message>
<source>default wallet</source>
- <translation>Кошелек по умолчанию</translation>
+ <translation>Кошелёк по умолчанию</translation>
</message>
<message>
<source>No wallets available</source>
@@ -499,7 +523,7 @@
</message>
<message>
<source>Minimize</source>
- <translation>Сворачивать</translation>
+ <translation>Свернуть</translation>
</message>
<message>
<source>Zoom</source>
@@ -544,7 +568,7 @@
<message>
<source>Wallet: %1
</source>
- <translation>Кошелек: %1
+ <translation>Кошелёк: %1
</translation>
</message>
<message>
@@ -587,15 +611,15 @@
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>Кошелек &lt;b&gt;зашифрован&lt;/b&gt; и сейчас &lt;b&gt;разблокирован&lt;/b&gt;</translation>
+ <translation>Кошелёк &lt;b&gt;зашифрован&lt;/b&gt; и сейчас &lt;b&gt;разблокирован&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation>Кошелек &lt;b&gt;зашифрован&lt;/b&gt; и сейчас &lt;b&gt;заблокирован&lt;/b&gt;</translation>
+ <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>
+ <translation>Произошла критическая ошибка. Биткойн больше не может продолжать безопасную работу и будет закрыт.</translation>
</message>
</context>
<context>
@@ -751,10 +775,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <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>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Кошелёк создан</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Создать кошелёк</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Название кошелька</translation>
+ </message>
+ <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>Create</source>
+ <translation>Создать</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -791,7 +863,7 @@
</message>
<message>
<source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>Введенный адрес "%1" не является действительным адресом Bitcoin.</translation>
+ <translation>Введенный адрес "%1" не является действительным Биткойн-адресом.</translation>
</message>
<message>
<source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
@@ -803,7 +875,7 @@
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation>Невозможно разблокировать кошелек.</translation>
+ <translation>Невозможно разблокировать кошелёк.</translation>
</message>
<message>
<source>New key generation failed.</source>
@@ -840,12 +912,8 @@
<translation>версия</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-бит)</translation>
- </message>
- <message>
<source>About %1</source>
- <translation>Около %1</translation>
+ <translation>О %1</translation>
</message>
<message>
<source>Command-line options</source>
@@ -871,6 +939,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>
@@ -891,6 +963,10 @@
<translation>Bitcoin Core</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>
@@ -904,7 +980,7 @@
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
- <translation>Кошелек также будет сохранен в эту директорию.</translation>
+ <translation>Кошелёк также будет сохранен в эту директорию.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
@@ -922,7 +998,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(требуется %n ГБ)</numerusform><numerusform>(%n ГБ требуется)</numerusform><numerusform>(%n ГБ требуется)</numerusform><numerusform>(%n ГБ требуется)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n ГБ необходимо для полного блокчейна)</numerusform><numerusform>(%n ГБ необходимо для полного блокчейна)</numerusform><numerusform>(%n ГБ необходимо для полного блокчейна)</numerusform><numerusform>(%n ГБ необходимо для полного блокчейна)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -977,35 +1057,27 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Открыть URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Открыть запрос на оплату из URI или файла</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Выберите файл запроса платежа</translation>
+ <source>Open wallet failed</source>
+ <translation>Не удалось открыть кошелёк </translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Выберите файл запроса платежа для открытия</translation>
+ <source>Open wallet warning</source>
+ <translation>Кошелёк открыт</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
- <translation>Кошелек по умолчанию</translation>
+ <translation>Кошелёк по умолчанию</translation>
</message>
<message>
<source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
- <translation>Кошелек открывается &lt;b&gt;%1&lt;/b&gt;... </translation>
+ <translation>Кошелёк открывается &lt;b&gt;%1&lt;/b&gt;...</translation>
</message>
</context>
<context>
@@ -1036,15 +1108,15 @@
</message>
<message>
<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>
+ <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>
+ <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 hidden services:</translation>
+ <translation>Использовать отдельные прокси SOCKS&amp;5 для подключения к узлам через скрытые сервисы Tor:</translation>
</message>
<message>
<source>Hide the icon from the system tray.</source>
@@ -1052,7 +1124,7 @@
</message>
<message>
<source>&amp;Hide tray icon</source>
- <translation>&amp;Спрятать иконку в трее</translation>
+ <translation>&amp;Скрыть иконку из трея</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>
@@ -1128,7 +1200,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>Автоматически открыть порт для Bitcoin-клиента на маршрутизаторе. Работает только если Ваш маршрутизатор поддерживает UPnP, и данная функция включена.</translation>
+ <translation>Автоматически открыть порт для Биткойн-клиента на маршрутизаторе. Работает только если Ваш маршрутизатор поддерживает UPnP, и данная функция включена.</translation>
</message>
<message>
<source>Map port using &amp;UPnP</source>
@@ -1144,11 +1216,11 @@
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Подключится к сети Bitcoin через SOCKS5 прокси.</translation>
+ <translation>Подключится к сети Биткойн через прокси SOCKS5.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Выполнить подключение через прокси-сервер SOCKS5 (прокси-сервер по умолчанию):</translation>
+ <translation>&amp;Выполнить подключение через прокси SOCKS5 (прокси по умолчанию):</translation>
</message>
<message>
<source>Proxy &amp;IP:</source>
@@ -1180,7 +1252,7 @@
</message>
<message>
<source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Соединяться к Биткоин-сети через отдельные SOCKS5 прокси через Tor hidden services:</translation>
+ <translation>Подключатся к Биткойн-сети через отдельный прокси SOCKS5 для скрытых сервисов Tor.</translation>
</message>
<message>
<source>&amp;Window</source>
@@ -1196,7 +1268,7 @@
</message>
<message>
<source>M&amp;inimize on close</source>
- <translation>З&amp;акрыть при сворачивании</translation>
+ <translation>С&amp;вернуть при закрытии</translation>
</message>
<message>
<source>&amp;Display</source>
@@ -1280,7 +1352,7 @@
</message>
<message>
<source>The supplied proxy address is invalid.</source>
- <translation>Введенный адрес прокси-сервера недействителен.</translation>
+ <translation>Указанный прокси-адрес недействителен.</translation>
</message>
</context>
<context>
@@ -1291,7 +1363,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>Отображаемая информация может быть устаревшей. Ваш бумажник автоматически синхронизируется с сетью Bitcoin после подключения, но этот процесс пока не завершён.</translation>
+ <translation>Отображаемая информация может быть устаревшей. Ваш кошелёк автоматически синхронизируется с сетью Биткойн после подключения, но этот процесс пока не завершён.</translation>
</message>
<message>
<source>Watch-only:</source>
@@ -1366,7 +1438,7 @@
</message>
<message>
<source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>Не удаётся запустить bitcoin: обработчик click-to-pay</translation>
+ <translation>Не удаётся запустить биткойн: обработчик click-to-pay</translation>
</message>
<message>
<source>URI handling</source>
@@ -1377,16 +1449,12 @@
<translation>'bitcoin://' не верный URI. Используйте 'bitcoin:' вместо этого.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Вы используете URL BIP70, который не будет поддерживаться в будущем.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Неверный URL запроса платежа: %1</translation>
+ <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>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Не удалось обработать запрос на оплату, так как поддержка BIP70 не была имплементирована.</translation>
+ <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>
@@ -1394,72 +1462,12 @@
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>Не удалось обработать идентификатор! Это может быть связано с неверным Bitcoin-адресом или неправильными параметрами идентификатора.</translation>
+ <translation>Не удалось обработать идентификатор! Это может быть связано с неверным Биткойн-адресом или неправильными параметрами идентификатора.</translation>
</message>
<message>
<source>Payment request file handling</source>
<translation>Обработка запроса платежа</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Файл запроса платежа не может быть прочитан! Обычно это происходит из-за неверного файла запроса платежа.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Запрос платежа отклонен</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Сеть запроса платежа не совпадает с сетью клиента.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Истекло время ожидания запроса платежа</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Запрос платежа не инициализирован</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Непроверенные запросы платежей с нестандартными платёжными сценариями не поддерживаются.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Неверный запрос платежа.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Запрошенная сумма платежа %1 слишком мала (считается пылью).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Возврат от %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Запрос платежа %1 слишком большой (%2 байтов, разрешено %3 байтов).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Ошибка связи с %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Запрос платежа не понятен!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Неправильный ответ от сервера %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Ошибка сетевого запроса</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Оплата подтверждена</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1496,7 +1504,7 @@
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Введите биткоин-адрес (напр. %1)</translation>
+ <translation>Введите биткойн-адрес (напр. %1)</translation>
</message>
<message>
<source>%1 d</source>
@@ -1637,10 +1645,6 @@
<translation>Информация</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Окно отладки</translation>
- </message>
- <message>
<source>General</source>
<translation>Общий</translation>
</message>
@@ -1702,7 +1706,7 @@
</message>
<message>
<source>Wallet: </source>
- <translation>Кошелек:</translation>
+ <translation>Кошелёк:</translation>
</message>
<message>
<source>(none)</source>
@@ -1894,7 +1898,7 @@
</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>ВНИМАНИЕ: Мошенники предлагали пользователям вводить сюда команды, похищая таким образом содержимое их бумажников. Не используйте эту консоль без полного понимания смысла команд.</translation>
+ <translation>ВНИМАНИЕ: Мошенники предлагали пользователям вводить сюда команды, похищая таким образом содержимое их кошельков. Не используйте эту консоль без полного понимания смысла команд.</translation>
</message>
<message>
<source>Network activity disabled</source>
@@ -1957,7 +1961,7 @@
</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>Необязательное сообщение для запроса платежа, которое будет показано при открытии запроса. Заметьте: сообщение не будет отправлено вместе с платежом через сеть Bitcoin.</translation>
+ <translation>Необязательное сообщение для запроса платежа, которое будет показано при открытии запроса. Заметьте: сообщение не будет отправлено вместе с платежом через сеть Биткойн.</translation>
</message>
<message>
<source>An optional label to associate with the new receiving address.</source>
@@ -1989,7 +1993,7 @@
</message>
<message>
<source>Generate native segwit (Bech32) address</source>
- <translation>Создать "родной" segwit (Bech32) адрес </translation>
+ <translation>Создать "родной" segwit (Bech32) адрес</translation>
</message>
<message>
<source>Requested payments history</source>
@@ -2181,10 +2185,6 @@
<translation>Предупреждение: оценка комиссии в данный момент невозможна.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>свернуть настройки комиссионных</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>
@@ -2229,6 +2229,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>
@@ -2301,6 +2305,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>с кошелька '%1'</translation>
</message>
<message>
+ <source>%1 to '%2'</source>
+ <translation>%1 на '%2'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>С %1 на %2</translation>
</message>
@@ -2333,10 +2341,18 @@ 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>Send</source>
+ <translation>Отправить</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Адрес получателя неверный. Пожалуйста, перепроверьте.</translation>
</message>
@@ -2361,10 +2377,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Создание транзакции завершилось неудачей!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Транзакция была отменена по следующей причине: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Комиссия более чем в %1 считается абсурдно высокой.</translation>
</message>
@@ -2378,7 +2390,7 @@ 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>
@@ -2416,12 +2428,8 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Выбрать предыдущий использованный адрес</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <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>
@@ -2441,7 +2449,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>
+ <translation>С отправляемой суммы будет удержана комиссия. Получателю придёт меньше биткойнов, чем вы вводите в поле количества. Если выбрано несколько получателей, комиссия распределяется поровну.</translation>
</message>
<message>
<source>S&amp;ubtract fee from amount</source>
@@ -2469,7 +2477,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>Сообщение прикрепленное к bitcoin идентификатору будет сохранено вместе с транзакцией для вашего сведения. Заметьте: сообщение не будет отправлено через сеть Bitcoin.</translation>
+ <translation>Сообщение прикрепленное к биткойн идентификатору будет сохранено вместе с транзакцией для вашего сведения. Заметьте: Сообщение не будет отправлено через сеть Биткойн.</translation>
</message>
<message>
<source>Pay To:</source>
@@ -2479,17 +2487,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Memo:</source>
<translation>Примечание:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Введите метку для этого адреса, чтобы добавить его в свою адресную книгу</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Да</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2514,11 +2511,11 @@ 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>
@@ -2550,7 +2547,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>
@@ -2574,11 +2571,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
- <translation>Bitcoin-адрес, которым было подписано сообщение</translation>
+ <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>
@@ -2609,6 +2606,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>
@@ -2783,6 +2784,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>
@@ -3103,7 +3108,11 @@ 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>
+ <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>
@@ -3161,7 +3170,7 @@ 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>
@@ -3218,10 +3227,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Удаление: последняя синхронизация кошелька вышла за рамки удаленных данных. Вам нужен -reindex (скачать всю цепь блоков в случае удаленного узла)</translation>
</message>
<message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Повторное сканирование не возможно в режиме удаления. Вам надо будет использовать -reindex, который загрузит заново всю цепь блоков.</translation>
- </message>
- <message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>Ошибка: произошла критическая внутренняя ошибка, для получения деталей см. debug.log</translation>
</message>
@@ -3322,6 +3327,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
<translation>Пересобрать БД блоков прямо сейчас?</translation>
</message>
@@ -3343,11 +3356,11 @@ 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>
- <translation>Ошибка загрузки %s: кошелек требует более поздней версии %s</translation>
+ <translation>Ошибка загрузки %s: кошелёк требует более поздней версии %s</translation>
</message>
<message>
<source>Error loading block database</source>
@@ -3363,7 +3376,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Failed to rescan the wallet during initialization</source>
- <translation>Не удалось повторно сканировать кошелек во время инициализации</translation>
+ <translation>Не удалось повторно сканировать кошелёк во время инициализации</translation>
</message>
<message>
<source>Importing...</source>
@@ -3447,7 +3460,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Transaction fee and change calculation failed</source>
- <translation>Не удалось рассчитать комиссию и сдачу для транзакции </translation>
+ <translation>Не удалось рассчитать комиссию и сдачу для транзакции</translation>
</message>
<message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
@@ -3475,7 +3488,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
- <translation>Необходимо перезаписать бумажник, перезапустите %s для завершения операции.</translation>
+ <translation>Необходимо перезаписать кошелёк, перезапустите %s для завершения операции.</translation>
</message>
<message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
@@ -3612,16 +3625,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Это комиссия за транзакцию, которую вы можете заплатить, когда расчёт комиссии недоступен.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Этот продукт включает ПО, разработанное OpenSSL Project для использования в OpenSSL Toolkit %s и криптографическое ПО, написанное Eric Young и ПО для работы с UPnP, написанное Thomas Bernard.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
+ <translation>Внимание: Файл кошелька поврежден, данные восстановлены! Оригинальный %s сохранен как %s в %s; Если баланс или транзакции некорректны, вы должны восстановить файл из резервной копии.</translation>
</message>
<message>
<source>%s is set very high!</source>
@@ -3645,7 +3654,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Это размер комиссии, которую вы заплатите при отправке транзакции </translation>
+ <translation>Это размер комиссии, которую вы заплатите при отправке транзакции</translation>
</message>
<message>
<source>Transaction amounts must not be negative</source>
@@ -3669,7 +3678,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>
+ <translation>Невозможно обновить не разделенный HD кошелёк без обновления для поддержки предварительно разделенного пула ключей. Пожалуйста, используйте -upgradewallet=169900 или -upgradeallet без указания версии.</translation>
</message>
<message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
diff --git a/src/qt/locale/bitcoin_ru_RU.ts b/src/qt/locale/bitcoin_ru_RU.ts
deleted file mode 100644
index 430f2e4191..0000000000
--- a/src/qt/locale/bitcoin_ru_RU.ts
+++ /dev/null
@@ -1,2407 +0,0 @@
-<TS language="ru_RU" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Кликните правой кнопкой мыши для редактирования адреса или метки</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Создать новый адрес</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>Новый</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Скопировать выбранный адрес в буфер обмена</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>Копировать</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>&amp;Закрыть</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <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>
- <message>
- <source>&amp;Export</source>
- <translation>Экспортировать</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>Удалить</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Выбрать адрес для отправки монет</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Выбрать адрес для получения монет</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>Выбрать</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Адреса отправки</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <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>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Это ваши Bitcoin адреса для получения платежей. Настоятельно рекомендуем использовать новые адреса для получения каждой транзакции.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Копировать адрес</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Копировать &amp;метку</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Редактировать</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Экспортировать список адресов</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Экспорт не удался</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Произошла ошибка при попытке сохранения списка адресов в %1. Пожалуйста попробуйте позже.</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Метка</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Адрес</translation>
- </message>
- <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>
- <message>
- <source>New passphrase</source>
- <translation>Новый пароль</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Повторите новый пароль</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Отобразить пароль</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>
- </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>
- <message>
- <source>Decrypt wallet</source>
- <translation>Расшифровать кошелек</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Изменить пароль</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Введите старый и новый пароль к кошельку.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Подтвердите шифрование кошелька</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Внимание: если вы зашифруете ваш кошелек и потеряете ваш пароль, то вы &lt;b&gt;ПОТЕРЯЕТЕ ВСЕ ВАШИ БИТКОЙНЫ&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Вы уверены, что вы хотите зашифровать ваш кошелек?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Кошелек зашифрован</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 закроется сейчас для завершения процесса шифрования. Запомните что шифрование вашего кошелька не сможет полностью защитить ваши биткойны от кражи при помощи вредоносного ПО, заразившего ваш компьютер.</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>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Шифрование кошелька завершилось неудачно.</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Шифрование кошелька завершилось неудачно из-за внутренней ошибки. Ваш кошелек не был зашифрован.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Пароли не совпадают.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Ошибка разблокировки кошелька</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Пароль, введенный при шифровании кошелька, некорректен.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Расшифровка кошелька завершилась неудачно.</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Пароль для кошелька был успешно изменен.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Внимание: клавиша CapsLock включена!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP / маска подсети</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Заблокировано до</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Подписать &amp;сообщение...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Синхронизация с сетью...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Обзор</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Узел</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Отобразить главное окно кошелька</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Транзакции</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Просмотр истории транзакций</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>В&amp;ыход</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Выйти</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;О программе %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Показать информацию о %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>О библиотеке &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Показать информацию о библиотеке Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Опции...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Изменить опции конфигурации для %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Зашифровать кошелёк</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Создать резервную копию кошелька</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Изменить пароль...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Адреса для отправки...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>&amp;Адреса для получения...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Открыть &amp;URI...</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>Кошелек:</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>Кошелек по умолчанию</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Нажмите для отключения взаимодействия с сетью.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Взаимодействие с сетью отключено.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Нажмите для включения взаимодействия с сетью.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Синхронизация заголовков (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Реиндексация блоков на диске...</translation>
- </message>
- <message>
- <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>Прокси &lt;b&gt;включен&lt;/b&gt;: %1</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Послать средства на биткойн адрес</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Выполнить резервное копирование кошелька в другом месте расположения</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Изменить пароль, используемый для шифрования кошелька</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Окно отладки</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Открыть консоль отладки и диагностики</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Проверить сообщение...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Кошелек</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Отправить</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Получить</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Показать / Спрятать</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Показать или скрыть главное окно</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Зашифровать приватные ключи, принадлежащие вашему кошельку</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Подписывайте сообщения Bitcoin адресами чтобы подтвердить что это написали именно Вы</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Проверяйте сообщения чтобы убедиться что они подписаны конкретными Bitcoin адресами</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Файл</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Настройки</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Помощь</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Панель вкладок</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Запросить платеж</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Показать список использованных адресов и меток получателей</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Показать список использованных адресов и меток получателей</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Открыть биткойн: URI или запрос платежа</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>Опции командной строки</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n активное подключение к сети Bitcoin</numerusform><numerusform>%n активных подключения к сети Bitcoin</numerusform><numerusform>%n активных подключений к сети Bitcoin</numerusform><numerusform>%n активных подключений к сети Bitcoin</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Выполняется индексирование блоков на диске...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Выполняется обработка блоков на диске...</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>Обработан %n блок истории транзакций.</numerusform><numerusform>Обработано %n блока истории транзакций.</numerusform><numerusform>Обработано %n блоков истории транзакций.</numerusform><numerusform>Обработано %n блоков истории транзакций.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>Выполнено %1</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Последний полученный блок был сгенерирован %1 назад.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>После этого транзакции больше не будут видны.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Ошибка</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Предупреждение</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Информация</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Готов</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Подключение к пирам...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Синхронизация...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Дата: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Объем: %1
-</translation>
- </message>
- <message>
- <source>Wallet: %1
-</source>
- <translation>Кошелек: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Тип: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Ярлык: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Адрес: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Отправленная транзакция</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Входящая транзакция</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>Кошелек &lt;b&gt;зашифрован&lt;/b&gt; и сейчас &lt;b&gt;разблокирован&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation>Кошелек &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>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Выбор коинов</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Количество:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Байтов:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Количество:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Комиссия:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Пыль:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>После комиссии:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Сдача:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>Выбрать все</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Режим дерева</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Режим списка</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Количество</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Получено с меткой</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Получено с адресом</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Подтверждения</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Подтвержденные</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Копировать адрес</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Копировать метку</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Копировать сумму</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Копировать ID транзакции</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Заблокировать непотраченное</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Разблокировать непотраченное</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Копировать количество</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Скопировать комиссию</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Скопировать после комиссии</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Скопировать байты</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Скопировать пыль</translation>
- </message>
- <message>
- <source>Copy change</source>
- <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>
- <message>
- <source>(change)</source>
- <translation>(сдача)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Изменить адрес</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Метка</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Адрес</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Новый адрес отправки</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Изменить адрес получения</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Изменить адрес отправки</translation>
- </message>
- <message>
- <source>The entered address "%1" is already in the address book with label "%2".</source>
- <translation>Введённый адрес "%1" уже существует в адресной книге с меткой "%2".</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Невозможно разблокировать кошелек.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Произошла ошибка при генерации нового ключа.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Будет создана новая директория данных.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>имя</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>Каталог уже существует. Добавьте %1, если хотите создать новую директорию здесь.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Данный путь уже существует и это не каталог.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Невозможно создать директорию данных здесь.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>версия</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>Около %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Опции командной строки</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Добро пожаловать</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Добро пожаловать в %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>Поскольку программа запущена впервые, вы должны указать где %1 будет хранить данные.</translation>
- </message>
- <message>
- <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation>Если вы указали сокращать объём хранимого блокчейна (pruning), все исторические данные все равно должны быть скачаны и обработаны, но впоследствии они будут удалены для экономии места на диске.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Использовать стандартную директорию данных</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Использовать пользовательскую директорию данных</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin Core</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>
- <message>
- <source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>Приблизительно %1 ГБ данных будет сохранено в эту директорию.</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <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>
- </context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Форма</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>Последние транзакции пока могут быть не видны, поэтому вы можете видеть некорректный баланс ваших кошельков. Отображаемая информация будет верна после завершения синхронизации. Прогресс синхронизации вы можете видеть ниже.</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>Попытка потратить средства, использованные в транзакциях, которые ещё не синхронизированы, будет отклонена сетью.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Количество оставшихся блоков</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Неизвестно...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Время последнего блока</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation>Прогресс</translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation>Прогресс за час</translation>
- </message>
- <message>
- <source>calculating...</source>
- <translation>выполняется вычисление...</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation>Расчетное время, оставшееся до синхронизации</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Спрятать</translation>
- </message>
- <message>
- <source>Unknown. Syncing Headers (%1)...</source>
- <translation>Не известно. Синхронизация заголовков (%1)...</translation>
- </message>
-</context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Открыть URI</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Выберите файл запроса платежа</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Выберите файл запроса платежа для открытия</translation>
- </message>
-</context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Опции</translation>
- </message>
- <message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation>Автоматически запускать %1 после входа в систему.</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Размер кеша &amp;базы данных</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>МБ</translation>
- </message>
- <message>
- <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>Использовать отдельные SOCKS&amp;5 прокси для подключения к пирам через Tor hidden services:</translation>
- </message>
- <message>
- <source>Hide the icon from the system tray.</source>
- <translation>Убрать значок с области уведомлений.</translation>
- </message>
- <message>
- <source>&amp;Hide tray icon</source>
- <translation>&amp;Спрятать иконку в трее</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Открыть файл конфигурации</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Сбросить все опции клиента к значениям по умолчанию.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Сбросить опции</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Сеть</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>W&amp;allet</source>
- <translation>К&amp;ошелёк</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Эксперт</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Включить возможность &amp;управления монетами</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>&amp;Тратить неподтвержденную сдачу</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Пробросить порт через &amp;UPnP</translation>
- </message>
- <message>
- <source>Accept connections from outside.</source>
- <translation>Принимать внешние подключения</translation>
- </message>
- <message>
- <source>Allow incomin&amp;g connections</source>
- <translation>Разрешить входящие соединения</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Подключится к сети Bitcoin через SOCKS5 прокси.</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Выполнить подключение через прокси-сервер SOCKS5 (прокси-сервер по умолчанию):</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>IP прокси:</translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>&amp;Порт:</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Порт прокси: (напр. 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation>Используется для подключения к пирам по:</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>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Соединяться к Биткоин-сети через отдельные SOCKS5 прокси через Tor hidden services:</translation>
- </message>
- <message>
- <source>&amp;Window</source>
- <translation>&amp;Окно</translation>
- </message>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Отобразить только значок в области уведомлений после сворачивания окна.</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>З&amp;акрыть при сворачивании</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>Язык пользовательского интерфейса:</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>Whether to show coin control features or not.</source>
- <translation>Показывать ли опцию управления монетами.</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;ОК</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Отмена</translation>
- </message>
- <message>
- <source>default</source>
- <translation>по умолчанию</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Подтвердить сброс опций</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Для активации изменений необходим перезапуск клиента.</translation>
- </message>
- <message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation>Клиент будет закрыт. Продолжить далее?</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Опции конфигурации</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Ошибка</translation>
- </message>
- <message>
- <source>The configuration file could not be opened.</source>
- <translation>Невозможно открыть файл конфигурации.</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Это изменение потребует перезапуск клиента.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Введенный адрес прокси-сервера недействителен.</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Форма</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Только просмотр:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Доступно:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Ваш доступный баланс</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>В ожидании:</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Незрелые:</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Балансы</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Всего:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Ваш текущий баланс:</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>Ваш текущий баланс (только чтение):</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Доступно:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Последние транзакции</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Ошибка запроса платежа</translation>
- </message>
- <message>
- <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
- <translation>'bitcoin://' не верный URI. Используйте 'bitcoin:' вместо этого.</translation>
- </message>
- <message>
- <source>Invalid payment address %1</source>
- <translation>Неверный адрес %1</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Запрос платежа отклонен</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Истекло время ожидания запроса платежа</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Запрос платежа не инициализирован</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Неверный запрос платежа.</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Ошибка связи с %1: %2</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Неправильный ответ от сервера %1</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Оплата подтверждена</translation>
- </message>
-</context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>Пользовательский агент</translation>
- </message>
- <message>
- <source>Node/Service</source>
- <translation>Узел/служба</translation>
- </message>
- <message>
- <source>NodeId</source>
- <translation>Идентификатор узла</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Отправлено</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Получено</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Количество</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Введите биткоин-адрес (напр. %1)</translation>
- </message>
- <message>
- <source>%1 d</source>
- <translation>%1 д</translation>
- </message>
- <message>
- <source>%1 h</source>
- <translation>%1 ч</translation>
- </message>
- <message>
- <source>%1 m</source>
- <translation>%1 м</translation>
- </message>
- <message>
- <source>%1 s</source>
- <translation>%1 с</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>Н/Д</translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 и %2</translation>
- </message>
- <message>
- <source>%1 B</source>
- <translation>%1 Б</translation>
- </message>
- <message>
- <source>%1 KB</source>
- <translation>%1 КБ</translation>
- </message>
- <message>
- <source>%1 MB</source>
- <translation>%1 МБ</translation>
- </message>
- <message>
- <source>%1 GB</source>
- <translation>%1 ГБ</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>неизвестно</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- <message>
- <source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Ошибка: указанная директория данных "%1" не существует.</translation>
- </message>
- <message>
- <source>Error: %1</source>
- <translation>Ошибка: %1</translation>
- </message>
-</context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Сохранить изображение...</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>&amp;Копировать изображение</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>Сохранить QR-код</translation>
- </message>
- <message>
- <source>PNG Image (*.png)</source>
- <translation>PNG Картинка (*.png)</translation>
- </message>
-</context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>Н/Д</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Версия клиента</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>Информация</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Окно отладки</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Сеть</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Название</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Количество соединений</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Блокчейн</translation>
- </message>
- <message>
- <source>Current number of blocks</source>
- <translation>Текущее количество блоков</translation>
- </message>
- <message>
- <source>Memory Pool</source>
- <translation>Пул памяти</translation>
- </message>
- <message>
- <source>Current number of transactions</source>
- <translation>Текущее количество транзакций</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Использование памяти</translation>
- </message>
- <message>
- <source>Wallet: </source>
- <translation>Кошелек:</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Сбросить</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Получено</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Отправлено</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Пиры</translation>
- </message>
- <message>
- <source>Banned peers</source>
- <translation>Заблокированные пиры</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <translation>Выберите пира для просмотра детальной информации.</translation>
- </message>
- <message>
- <source>Version</source>
- <translation>Версия</translation>
- </message>
- <message>
- <source>Synced Headers</source>
- <translation>Синхронизировано заголовков</translation>
- </message>
- <message>
- <source>Synced Blocks</source>
- <translation>Синхронизировано блоков</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>Пользовательский агент</translation>
- </message>
- <message>
- <source>Decrease font size</source>
- <translation>Уменьшить размер шрифта</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation>Увеличить размер шрифта</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Сервисы</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Время соединения</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Последние отправленные</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Последние полученные</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Время отклика Ping</translation>
- </message>
- <message>
- <source>Min Ping</source>
- <translation>Минимальное время отклика Ping</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Время последнего блока</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Открыть</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Консоль</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Сетевой трафик</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Вход:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Выход:</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;час</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;день</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;неделя</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;год</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>Кошелек по умолчанию</translation>
- </message>
- <message>
- <source>Type %1 for an overview of available commands.</source>
- <translation>Ввести %1 для обзора доступных команд.</translation>
- </message>
- <message>
- <source>never</source>
- <translation>никогда</translation>
- </message>
- <message>
- <source>Yes</source>
- <translation>Да</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Нет</translation>
- </message>
- <message>
- <source>Unknown</source>
- <translation>Неизвестно</translation>
- </message>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Метка:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Сообщение:</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Очистить все поля формы.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Отчистить</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>"Родные" segwit адреса (Bech32 или BIP-173) в дальнейшем уменьшат комиссии ваших транзакций и предоставят улучшенную защиту от опечаток, однако старые кошельки не поддерживают эти адреса. Если не выбрано, будет создан совместимый со старыми кошелёк.</translation>
- </message>
- <message>
- <source>Generate native segwit (Bech32) address</source>
- <translation>Создать "родной" segwit (Bech32) адрес </translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>История платежных запросов</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Запросить платеж</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Отобразить выбранный запрос (выполняет то же, что и двойной щелчок на записи)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Показать</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Удалить выбранные записи со списка</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Удалить</translation>
- </message>
- <message>
- <source>Copy URI</source>
- <translation>Копировать URI</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Копировать метку</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Копировать сообщение</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Копировать сумму</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>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Копировать &amp;Адрес</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Сохранить изображение...</translation>
- </message>
- <message>
- <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>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation>Ошибка преобразования URI в QR-код.</translation>
- </message>
-</context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Метка</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Сообщение</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(нет метки)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation>(нет сообщений)</translation>
- </message>
- <message>
- <source>(no amount requested)</source>
- <translation>(не указана запрашиваемая сумма)</translation>
- </message>
- <message>
- <source>Requested</source>
- <translation>Запрошено</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Отправить монеты</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Опции управления монетами</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Входы...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>выбрано автоматически</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Недостаточно средств!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Количество:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Байтов:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Количество:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Комиссия:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>После комиссии:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Сдача:</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Указать адрес для сдачи</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Комиссия за транзакцию:</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Выбрать...</translation>
- </message>
- <message>
- <source>Warning: Fee estimation is currently not possible.</source>
- <translation>Предупреждение: оценка комиссии в данный момент невозможна.</translation>
- </message>
- <message>
- <source>collapse fee-settings</source>
- <translation>свернуть настройки комиссионных</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>за килобайт</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Спрятать</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Рекомендованное значение:</translation>
- </message>
- <message>
- <source>Custom:</source>
- <translation>Пользовательское значение:</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Отправить нескольким получателям сразу</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>Добавить &amp;получателя</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Очистить все поля формы.</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Пыль:</translation>
- </message>
- <message>
- <source>Confirmation time target:</source>
- <translation>Целевое время подтверждения</translation>
- </message>
- <message>
- <source>Enable Replace-By-Fee</source>
- <translation>Включить Replace-By-Fee</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Баланс:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Подтвердить отправку</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Копировать количество</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Копировать сумму</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Скопировать комиссию</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Скопировать после комиссии</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Скопировать байты</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Скопировать пыль</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Скопировать сдачу</translation>
- </message>
- <message>
- <source>Are you sure you want to send?</source>
- <translation>Вы действительно хотите выполнить отправку?</translation>
- </message>
- <message>
- <source>or</source>
- <translation>или</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Комиссия</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation>Подтвердить отправку монет</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation>Сумма оплаты должна быть больше 0.</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation>Количество превышает ваш баланс.</translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation>Создание транзакции завершилось неудачей!</translation>
- </message>
- <message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Транзакция была отменена по следующей причине: %1</translation>
- </message>
- <message>
- <source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation>Комиссия более чем в %1 считается абсурдно высокой.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Истекло время ожидания запроса платежа</translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation>Предупреждение: Неверный Bitcoin адрес</translation>
- </message>
- <message>
- <source>Warning: Unknown change address</source>
- <translation>Предупреждение: Неизвестный адрес сдачи</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(нет метки)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Метка:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Выбрать предыдущий использованный адрес</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Вставить адрес из буфера обмена</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Удалить эту запись</translation>
- </message>
- <message>
- <source>Use available balance</source>
- <translation>Использовать доступный баланс</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Сообщение:</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Выполнить оплату в пользу:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Да</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>%1 is shutting down...</source>
- <translation>%1 завершает работу...</translation>
- </message>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Choose previously used address</source>
- <translation>Выбрать предыдущий использованный адрес</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Вставить адрес из буфера обмена</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Подпись</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Скопировать текущую подпись в буфер обмена системы</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation>Введенный адрес недействителен.</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Необходимо проверить адрес и выполнить повторную попытку.</translation>
- </message>
- <message>
- <source>Wallet unlock was cancelled.</source>
- <translation>Разблокирование кошелька было отменено.</translation>
- </message>
- <message>
- <source>Message signed.</source>
- <translation>Сообщение подписано.</translation>
- </message>
- <message>
- <source>The signature could not be decoded.</source>
- <translation>Невозможно расшифровать подпись.</translation>
- </message>
- </context>
-<context>
- <name>SplashScreen</name>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>in memory pool</source>
- <translation>в мемпуле</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation>не в мемпуле</translation>
- </message>
- <message>
- <source>Status</source>
- <translation>Статус</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Источник</translation>
- </message>
- <message>
- <source>From</source>
- <translation>От</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>неизвестно</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>только просмотр</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Комиссия</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Сообщение</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Комментарий</translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation>ID транзакции</translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation>Транзакция</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Количество</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>Details for %1</source>
- <translation>Детальная информация по %1</translation>
- </message>
-</context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Тип</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Метка</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Получено на</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Отправить</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Добыто</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>только просмотр</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(нет метки)</translation>
- </message>
- <message>
- <source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>Статус транзакции. Для отображения количества подтверждений необходимо навести курсор на это поле.</translation>
- </message>
- <message>
- <source>Date and time that the transaction was received.</source>
- <translation>Дата и время получения транзакции.</translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation>Тип транзакции.</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Все</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Сегодня</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>Эта неделя</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>Этот месяц</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Последний месяц</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Этот год</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Диапазон...</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Получено на</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Отправить</translation>
- </message>
- <message>
- <source>To yourself</source>
- <translation>Себе</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Добыто</translation>
- </message>
- <message>
- <source>Enter address, transaction id, or label to search</source>
- <translation>Введите адрес, ID транзакции или метку для поиска</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation>Минимальное количество</translation>
- </message>
- <message>
- <source>Abandon transaction</source>
- <translation>Отказ от транзакции</translation>
- </message>
- <message>
- <source>Increase transaction fee</source>
- <translation>Увеличить комиссию за транзакцию</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Копировать адрес</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Копировать метку</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Копировать сумму</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Копировать ID транзакции</translation>
- </message>
- <message>
- <source>Copy raw transaction</source>
- <translation>Копировать raw транзакцию</translation>
- </message>
- <message>
- <source>Copy full transaction details</source>
- <translation>Копировать все детали транзакции</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Изменить метку</translation>
- </message>
- <message>
- <source>Show transaction details</source>
- <translation>Отобразить детали транзакции</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Подтвержденные</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Тип</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Метка</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Адрес</translation>
- </message>
- <message>
- <source>ID</source>
- <translation>ИН</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Экспорт не удался</translation>
- </message>
- <message>
- <source>There was an error trying to save the transaction history to %1.</source>
- <translation>При попытке сохранения истории транзакций в %1 произошла ошибка.</translation>
- </message>
- <message>
- <source>Exporting Successful</source>
- <translation>Экспорт выполнен успешно</translation>
- </message>
- <message>
- <source>The transaction history was successfully saved to %1.</source>
- <translation>Историю транзакций было успешно сохранено в %1.</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Отправить монеты</translation>
- </message>
- <message>
- <source>Increasing transaction fee failed</source>
- <translation>Увеличение комиссии за транзакцию завершилось неудачей</translation>
- </message>
- <message>
- <source>Do you want to increase the fee?</source>
- <translation>Желаете увеличить комиссию?</translation>
- </message>
- <message>
- <source>Current fee:</source>
- <translation>Текущее значение комиссии</translation>
- </message>
- <message>
- <source>Increase:</source>
- <translation>Увеличить</translation>
- </message>
- <message>
- <source>New fee:</source>
- <translation>Новое значение комиссии:</translation>
- </message>
- <message>
- <source>Can't sign transaction.</source>
- <translation>Невозможно подписать транзакцию</translation>
- </message>
- <message>
- <source>Could not commit transaction</source>
- <translation>Не удалось выполнить транзакцию</translation>
- </message>
-</context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>Экспортировать</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Экспортировать данные в текущей вкладке в файл</translation>
- </message>
- <message>
- <source>Backup Wallet</source>
- <translation>Создать резервную копию кошелька</translation>
- </message>
- <message>
- <source>Wallet Data (*.dat)</source>
- <translation>Данные кошелька (*.dat)</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>Создание резервной копии кошелька завершилось неудачей</translation>
- </message>
- <message>
- <source>There was an error trying to save the wallet data to %1.</source>
- <translation>При попытке сохранения данных кошелька в %1 произошла ошибка.</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Резервное копирование выполнено успешно</translation>
- </message>
- <message>
- <source>The wallet data was successfully saved to %1.</source>
- <translation>Данные кошелька были успешно сохранены в %1.</translation>
- </message>
- </context>
-<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>Unable to start HTTP server. See debug log for details.</source>
- <translation>Невозможно запустить HTTP-сервер. Для получения более детальной информации необходимо обратиться к журналу отладки.</translation>
- </message>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>The %s developers</source>
- <translation>Разработчики %s</translation>
- </message>
- <message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d из последних 100 блоков имеют неожиданную версию</translation>
- </message>
- <message>
- <source>Copyright (C) %i-%i</source>
- <translation>Авторское право (©) %i-%i</translation>
- </message>
- <message>
- <source>Error loading %s</source>
- <translation>Ошибка загрузки %s</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet corrupted</source>
- <translation>Ошибка загрузки %s: кошелек поврежден</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet requires newer version of %s</source>
- <translation>Ошибка загрузки %s: кошелек требует более поздней версии %s</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Ошибка: место на диске заканчивается!</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>Выполняется импорт...</translation>
- </message>
- <message>
- <source>Loading P2P addresses...</source>
- <translation>Выполняется загрузка P2P-адресов...</translation>
- </message>
- <message>
- <source>Loading banlist...</source>
- <translation>Загрузка черного списка...</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>Недоступно достаточного количества дескрипторов файла.</translation>
- </message>
- <message>
- <source>Transaction fee and change calculation failed</source>
- <translation>Не удалось рассчитать комиссию и сдачу для транзакции </translation>
- </message>
- <message>
- <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
- <translation>Неподдерживаемый аргумент -debugnet пропущен, необходимо использовать -debug=net.</translation>
- </message>
- <message>
- <source>Unsupported argument -tor found, use -onion.</source>
- <translation>Обнаружен неподдерживаемый аргумент -tor, необходимо использовать -onion.</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Проверка блоков...</translation>
- </message>
- <message>
- <source>Error reading from database, shutting down.</source>
- <translation>Ошибка чтения с базы данных, выполняется закрытие.</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Информация</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Подписание транзакции завершилось неудачей</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Размер транзакции слишком мал</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Транзакция слишком большая</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Предупреждение</translation>
- </message>
- <message>
- <source>Starting network threads...</source>
- <translation>Запуск сетевых потоков...</translation>
- </message>
- <message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Это минимальная комиссия, которую вы платите для любой транзакции</translation>
- </message>
- <message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Это размер комиссии, которую вы заплатите при отправке транзакции </translation>
- </message>
- <message>
- <source>Transaction amounts must not be negative</source>
- <translation>Размер транзакции не может быть отрицательным</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>Транзакция должна иметь хотя бы одного получателя</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Недостаточно средств</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Загрузка индекса блоков...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Выполняется загрузка кошелька...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Невозможно выполнить переход на более раннюю версию кошелька</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Выполняется повторное сканирование...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Загрузка завершена</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Ошибка</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_si.ts b/src/qt/locale/bitcoin_si.ts
index 4fa59aa06a..fbcc8ae7bb 100644
--- a/src/qt/locale/bitcoin_si.ts
+++ b/src/qt/locale/bitcoin_si.ts
@@ -136,7 +136,7 @@
<source>URI:</source>
<translation>URI:</translation>
</message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
</context>
@@ -237,9 +237,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts
index 2bca9716d2..8435a49319 100644
--- a/src/qt/locale/bitcoin_sk.ts
+++ b/src/qt/locale/bitcoin_sk.ts
@@ -70,6 +70,10 @@
<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>
@@ -132,6 +136,10 @@
<translation>Zopakujte nové heslo</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Zobraziť frázu</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Zašifrovať peňaženku</translation>
</message>
@@ -172,6 +180,30 @@
<translation>Peňaženka zašifrovaná</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>Zadajte novú prístupovú frázu pre peňaženku.&lt;br/&gt;Prosím použite frázu dlhú &lt;b&gt;desať či viac náhodných znakov&lt;/b&gt;, alebo &lt;b&gt;osem či viac slov&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Zadajte starú a novú frázu pre túto peňaženku.</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>Pamätajte, že zašifrovanie peňaženky neochráni úplne vaše bitcoiny pred ukradnutím škodlivými programami vo vašom počítači.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Peňaženka na zašifrovanie</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Vaša peňaženka bude zašifrovaná.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Vaša peňaženka je zašifrovaná.</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>DÔLEŽITÉ: Všetky predchádzajúce zálohy vašej peňaženky, ktoré ste vykonali by mali byť nahradené novo vytvorenou, zašifrovanou peňaženkou. Z bezpečnostných dôvodov bude predchádzajúca záloha nezašifrovanej peňaženky k ničomu, akonáhle začnete používať novú, zašifrovanú peňaženku.</translation>
</message>
@@ -279,7 +311,7 @@
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Zašifrovať Peňaženku...</translation>
+ <translation>&amp;Zašifrovať peňaženku...</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
@@ -287,13 +319,21 @@
</message>
<message>
<source>&amp;Change Passphrase...</source>
- <translation>&amp;Zmena Hesla...</translation>
+ <translation>&amp;Zmeniť heslo...</translation>
</message>
<message>
<source>Open &amp;URI...</source>
<translation>Otvoriť &amp;URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Vytvoriť peňaženku...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Vytvoriť novú peňaženku</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Peňaženka:</translation>
</message>
@@ -334,14 +374,6 @@
<translation>Zmeniť heslo použité na šifrovanie peňaženky</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Okno pre ladenie</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Otvor konzolu pre ladenie a diagnostiku</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>O&amp;veriť správu...</translation>
</message>
@@ -402,10 +434,6 @@
<translation>Zobraziť zoznam použitých prijímacích adries a ich popisov</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Otvoriť bitcoin URI alebo výzvu k platbe</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Možnosti príkazového riadku</translation>
</message>
@@ -447,7 +475,7 @@
</message>
<message>
<source>Information</source>
- <translation>Informácia</translation>
+ <translation>Informácie</translation>
</message>
<message>
<source>Up to date</source>
@@ -738,7 +766,7 @@
</message>
<message>
<source>change from %1 (%2)</source>
- <translation>zmena od %1 (%2)</translation>
+ <translation>zmeniť z %1 (%2)</translation>
</message>
<message>
<source>(change)</source>
@@ -747,10 +775,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Vytvára sa peňaženka &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Vytvorenie peňaženky zlyhalo</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Varovanie vytvárania peňaženky</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Vytvoriť peňaženku</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Názov peňaženky</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>Zašifrovať peňaženku. Peňaženka bude zašifrovaná frázou, ktoré si zvolíte.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Zašifrovať peňaženku</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>Vypnúť súkromné kľúče pre túto peňaženku. Peňaženky s vypnutými súkromnými kľúčmi nebudú mať súkromné kľúče a nemôžu mať HD inicializáciu ani importované súkromné kľúče. Toto je ideálne pre peňaženky iba na sledovanie.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>Vypnúť súkromné kľúče</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>Vytvoriť prázdnu peňaženku. Prázdne peňaženky na začiatku nemajú žiadne súkromné kľúče ani skripty. Neskôr môžu byť importované súkromné kľúče a adresy alebo nastavená HD inicializácia.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Vytvoriť prázdnu peňaženku</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Vytvoriť</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -836,10 +912,6 @@
<translation>verzia</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>O %1</translation>
</message>
@@ -867,6 +939,10 @@
<translation>Hneď po stlačení OK, začne %1 stťahovať a spracovávať celý %4 reťazec blokov (%2 GB), začínajúc nejstaršími transakcemi z roku %3, kdey bol %4 spustený.</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>Zvrátenie tohto nastavenia vyžaduje opätovné stiahnutie celého reťazca blokov. Je rýchlejšie najprv stiahnuť celý reťazec blokov a potom ho redukovať neskôr. Vypne niektoré pokročilé funkcie.</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>Prvá synchronizácia je veľmi náročná a môžu sa tak vďaka nej začat na Vašom počítači projavovať doteraz skryté hárdwarové problémy. Vždy, keď spustíte %1, bude sťahovanie pokračovať tam, kde skončilo.</translation>
</message>
@@ -887,6 +963,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Zahodiť bloky po ich overení, okrem posledných %1 GB (redukovanie)</translation>
+ </message>
+ <message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation>V tejto zložke bude uložených aspoň %1 GB dát a postupom času sa bude zväčšovať.</translation>
</message>
@@ -918,7 +998,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(z %n GB potrebného)</numerusform><numerusform>(z %n GB potrebných)</numerusform><numerusform>(z %n GB potrebných)</numerusform><numerusform>(z %n GB potrebných)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB potrebný pre plný reťazec)</numerusform><numerusform>(%n GB potrebné pre plný reťazec)</numerusform><numerusform>(%n GB potrebných pre plný reťazec)</numerusform><numerusform>(%n GB potrebných pre plný reťazec)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -973,28 +1057,20 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Otvoriť URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Otvoriť požiadavku na zaplatenie z URI alebo súboru</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Vyberte súbor s výzvou k platbe</translation>
+ <source>Open wallet failed</source>
+ <translation>Otvorenie peňaženky zlyhalo</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Vyberte ktorý súbor s výzvou na platbu otvoriť</translation>
+ <source>Open wallet warning</source>
+ <translation>Varovanie otvárania peňaženky</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>predvolená peňaženka</translation>
@@ -1064,7 +1140,7 @@
</message>
<message>
<source>Open Configuration File</source>
- <translation>Otvoriť konfiguračný súbor </translation>
+ <translation>Otvoriť konfiguračný súbor</translation>
</message>
<message>
<source>Reset all client options to default.</source>
@@ -1080,7 +1156,7 @@
</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>Zakáže niektoré pokročilé funkcie, ale všetky bloky budú stále plne overené. Obnovenie tohto nastavenia vyžaduje opätovné prevzatie celého blockchainu. Skutočné využitie disku môže byť o niečo vyššie.</translation>
+ <translation>Zakáže niektoré pokročilé funkcie, ale všetky bloky budú stále plne overené. Obnovenie tohto nastavenia vyžaduje opätovné prevzatie celého reťazca blokov. Skutočné využitie disku môže byť o niečo vyššie.</translation>
</message>
<message>
<source>Prune &amp;block storage to</source>
@@ -1092,7 +1168,7 @@
</message>
<message>
<source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation>Obnovenie tohto nastavenia vyžaduje opätovné prevzatie celého blockchainu.</translation>
+ <translation>Obnovenie tohto nastavenia vyžaduje opätovné stiahnutie celého reťazca blokov.</translation>
</message>
<message>
<source>MiB</source>
@@ -1112,7 +1188,7 @@
</message>
<message>
<source>Enable coin &amp;control features</source>
- <translation>Povoliť možnosti &amp;kontroly minci</translation>
+ <translation>Povoliť možnosti &amp;kontroly mincí</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>
@@ -1216,7 +1292,7 @@
</message>
<message>
<source>Whether to show coin control features or not.</source>
- <translation>Či zobrazovať možnosti kontroly minci alebo nie.</translation>
+ <translation>Či zobrazovať možnosti kontroly mincí alebo nie.</translation>
</message>
<message>
<source>&amp;Third party transaction URLs</source>
@@ -1373,16 +1449,12 @@
<translation>'bitcoin://' je neplatná URI. Použite 'bitcoin:'</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Používate adresu URL typu BIP70, ktorá nebude v budúcnosti podporovaná.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL pre stiahnutie výzvy na zaplatenie je neplatné: %1</translation>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Kvôli mnohým bezpečnostným chybám v BIP70 sa dôrazne odporúča ignorovať inštrukcie na prepínanie peňaženiek od akýchkoľvek obchodníkov.</translation>
</message>
<message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Nemožno spracovať žiadosť o platbu, pretože podpora pre BIP70 nebola zahrnutá.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Ak dostávate túto chybu mali by ste od obchodníka vyžiadať URI adresu kompatibilnú s BIP21.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1396,66 +1468,6 @@
<source>Payment request file handling</source>
<translation>Obsluha súboru s požiadavkou na platbu</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Súbor s výzvou na zaplatenie sa nedá čítať! To môže byť spôsobené aj neplatným súborom s výzvou.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Požiadavka na platbu zamietnutá</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Sieť požiadavky na platbu nie je zhodná so sieťou klienta.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Vypršala platnosť požiadavky na platbu.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Požiadavka na platbu nie je inicializovaná</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Program nepodporuje neoverené platobné požiadavky na vlastné skripty.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Chybná požiadavka na platbu.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Požadovaná suma platby %1 je príliš nízka (považovaná za prach).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Vrátenie z %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Požiadavka na platbu %1 je príliš veľká (%2 bajtov, povolené je %3 bajtov).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Chyba komunikácie s %1: %2 </translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Požiadavka na platbu nemôže byť analyzovaná!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Zlá odpoveď zo servera %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Chyba požiadavky siete</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Platba potvrdená</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1544,7 +1556,7 @@
</message>
<message>
<source>%1 and %2</source>
- <translation> %1 a %2</translation>
+ <translation>%1 a %2</translation>
</message>
<message numerus="yes">
<source>%n year(s)</source>
@@ -1606,6 +1618,10 @@
<translation>Chyba kódovania URI do QR Code.</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>Nie je dostupná podpora QR kódov.</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>Uložiť QR Code</translation>
</message>
@@ -1626,11 +1642,7 @@
</message>
<message>
<source>&amp;Information</source>
- <translation>&amp;Informácia</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Okno pre ladenie</translation>
+ <translation>&amp;Informácie</translation>
</message>
<message>
<source>General</source>
@@ -1650,7 +1662,7 @@
</message>
<message>
<source>Blocksdir</source>
- <translation>Blocksdir</translation>
+ <translation>Priečinok s blokmi</translation>
</message>
<message>
<source>To specify a non-default location of the blocks directory use the '%1' option.</source>
@@ -1887,7 +1899,7 @@
</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>UPOZORNENIE: Podvodníci sú aktívni a hovoria používateľom, aby sem zadávali príkazy, ktorými im ale následne vykradnú ich peňaženky. Nepoužívajte túto konzolu, ak plne nepoynáte dôsledky jednotlivých príkazov.</translation>
+ <translation>UPOZORNENIE: Podvodníci sú aktívni a hovoria používateľom, aby sem zadávali príkazy, ktorými im ale následne vykradnú ich peňaženky. Nepoužívajte túto konzolu, ak plne nepoznáte dôsledky jednotlivých príkazov.</translation>
</message>
<message>
<source>Network activity disabled</source>
@@ -1965,6 +1977,10 @@
<translation>Voliteľná požadovaná suma. Nechajte prázdne alebo nulu ak nepožadujete určitú sumu.</translation>
</message>
<message>
+ <source>&amp;Create new receiving address</source>
+ <translation>Vytvoriť novú adresu pre prijímanie</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Vyčistiť všetky polia formulára.</translation>
</message>
@@ -2107,7 +2123,7 @@
</message>
<message>
<source>Coin Control Features</source>
- <translation>Možnosti kontroly minci</translation>
+ <translation>Možnosti kontroly mincí</translation>
</message>
<message>
<source>Inputs...</source>
@@ -2170,10 +2186,6 @@
<translation>Upozornenie: teraz nie je možné poplatok odhadnúť.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>zbaliť nastavenia poplatkov</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>
@@ -2286,6 +2298,10 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>%1 (%2 blokov)</translation>
</message>
<message>
+ <source> from wallet '%1'</source>
+ <translation> z peňaženky '%1'</translation>
+ </message>
+ <message>
<source>%1 to '%2'</source>
<translation>%1 do '%2'</translation>
</message>
@@ -2322,6 +2338,10 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Celková suma</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Pre prezretie zoznamu príjemcov kliknite "Zobraziť detaily..."</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Potvrďte odoslanie mincí</translation>
</message>
@@ -2350,10 +2370,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Vytvorenie transakcie zlyhalo!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Transakcia bola odmietnutá z nasledujúceho dôvodu: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Poplatok vyšší ako %1 sa považuje za neprimerane vysoký.</translation>
</message>
@@ -2405,10 +2421,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Vybrať predtým použitú adresu</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Toto je normálna platba.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Zvoľte adresu kam poslať platbu</translation>
</message>
@@ -2468,17 +2480,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<source>Memo:</source>
<translation>Poznámka:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Zadajte popis pre túto adresu pre pridanie do adresára</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>áno</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2772,6 +2773,10 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Index výstupu</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(Certifikát nebol overený)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Kupec</translation>
</message>
@@ -3095,8 +3100,12 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Zatvoriť peňaženku</translation>
</message>
<message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>Naozaj chcete zavrieť peňaženku &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>Zatvorenie peňaženky na príliš dlhú dobu môže mať za následok potrebu znova synchronizovať celý blockchain v prípade, že je aktivované redukovanie blockchainu. </translation>
+ <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>
@@ -3196,7 +3205,7 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<name>bitcoin-core</name>
<message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
- <translation>Distribuované pod softvérovou licenciou MIT, viď sprievodný súbor %s alebo %s</translation>
+ <translation>Distribuované pod softvérovou licenciou MIT, pozri sprievodný súbor %s alebo %s</translation>
</message>
<message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
@@ -3204,11 +3213,7 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
</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>Prerezávanie: posledná synchronizácia peňaženky prebehla pred už prerezanými dátami. Je treba previesť -reindex (v prípade prerezávacieho režimu stiahne znovu celý reťazec blokov)</translation>
- </message>
- <message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>V prerezávaciom režime nie je možné reťazec blokov preskenovať. Musíte vykonať -reindex, čo znova stiahne celý reťaec blokov.</translation>
+ <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>
@@ -3280,7 +3285,7 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
</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>
+ <translation>%d z posledných 100 blokov má neočakávanú verziu</translation>
</message>
<message>
<source>%s corrupt, salvage failed</source>
@@ -3367,6 +3372,10 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Kontrola čistoty pri inicializácií zlyhala. %s sa vypína.</translation>
</message>
<message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Neplatné oprávnenie P2P: '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
<translation>Neplatná suma pre -%s=&lt;amount&gt;: '%s'</translation>
</message>
@@ -3383,6 +3392,14 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Zadaný adresár blokov "%s" neexistuje.</translation>
</message>
<message>
+ <source>Unknown address type '%s'</source>
+ <translation>Neznámy typ adresy '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation>Neznámy typ zmeny '%s'</translation>
+ </message>
+ <message>
<source>Upgrading txindex database</source>
<translation>Inovuje sa txindex databáza</translation>
</message>
@@ -3391,6 +3408,10 @@ 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>
@@ -3464,7 +3485,7 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
</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>K návratu k neprerezávaciemu režimu je treba prestavať databázu použitím -reindex. Tiež sa znova stiahne celý reťazec blokov</translation>
+ <translation>K návratu k neredukovanému režimu je potrebné prestavať databázu použitím -reindex. Tiež sa znova stiahne celý reťazec blokov</translation>
</message>
<message>
<source>Error reading from database, shutting down.</source>
@@ -3499,6 +3520,10 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Je potrebné zadať port s -whitebind: '%s'</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Režim redukovania je nekompatibilný s -blockfilterindex.</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Obmedzuje sa -maxconnections z %d na %d kvôli systémovým obmedzeniam.</translation>
</message>
@@ -3581,10 +3606,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Toto je poplatok za transakciu keď odhad poplatkov ešte nie je k dispozícii.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Tento produkt zahrňuje programy vyvinuté projektom OpenSSL pre použití v OpenSSL Toolkite %s a kryptografický program od Erika Younga a program UPnP od Thomasa Bernarda.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<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>
diff --git a/src/qt/locale/bitcoin_sk_SK.ts b/src/qt/locale/bitcoin_sk_SK.ts
deleted file mode 100644
index 68a41c2d9a..0000000000
--- a/src/qt/locale/bitcoin_sk_SK.ts
+++ /dev/null
@@ -1,3651 +0,0 @@
-<TS language="sk_SK" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Kliknite pravým tlačidlom myši pre úpravu adresy alebo štítku</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Vytvoriť novú adresu</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Nový</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Skopírovať aktuálne označenú adresu do schránky</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Skopírovať</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>C&amp;</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Vymazať aktuálne označenú adresu zo zoznamu</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Pre vyhľadávanie zadajte adresu alebo štítok</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportovať dáta z aktuálnej karty do súboru</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportovať</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Vymazať</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Vyberte adresu do ktorej chcete poslať mince</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Vyberte adresu do ktorej chcete prijímať mince</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>Vy&amp;brať</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Adresa odosielateľa</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Adresa prijímaťeľa</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>Toto je vaša Bitcoin adresa pre odosielanie platieb. Vždy si overte hodnotu a adresu prijímateľa pred odoslaním vaších mincí.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Toto je vaša Bitcoin adresa pre prijímanie platieb. Odporúčame Vám používať vždy novú adresu pre každú transakciu.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Skopírovať adresu</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Skopírvať &amp;Štítok</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Upraviť</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Exportovať zoznam adries</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Čiarkou oddelené súbory (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Exportovanie zlyhalo</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Štítok</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(žiadny štítok)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Prístupové frázy</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Zadajte vašu frázu</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Nová fráza</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Zopakujte novú frázu</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Ukázať heslo</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Vložte novú frázu do peňaženky.&lt;br/&gt;Prosím použite frázu pozostávajúcu z&lt;b&gt;desiatich, alebo viacerých náhodných charakterov, alebo pozostávajúcu z &lt;b&gt; alebo viacerých slov&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Zašifrovať peňaženku</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Táto operácia si vyžaduje frázu Vašej peňaženky na jej odomknutie.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Odomknúť peňaženku</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Táto operácia si vyžaduje frázu vašej peňaženky na jej dešifrovanie.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Dešifrovanie peňaženky</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Zmeniť frázu</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Zadajte starú a novú frázu do vašej peňaženky.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Potvrďiť zašifrovanie peňaženky</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Upozornenie: Keď si zašifrujete vašu peňaženku a stratíte svoju frázu, &lt;b&gt; STRATÍTE VŠETKY VAŠE BITCOINY &lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Ste si istý že si želáte svoju peňaženku zašifrovať?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Peňaženka zašifrovaná</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 sa teraz zatvorí aby sa dokončil proces šifrovania. Zapamätajte si, že zašifrovanie vašej peňaženky nemôže úplne ochrániť vaše bitcoiny od ukradnutia malvérom ktorý môže infikovať Váš počítač.</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>DÔLEŽITÉ: Všetky predošlé zálohy vašej peňaženky by mali byť nahradené na novo vygenerovaným zašifrovaným súborom. Z bezpečnostných dôvodov, predošlé zálohy nezašifrovaného súboru s peňaženkou budú nefunkčné hneď ako začnete používať vašu novú, zašifrovanú peňaženku.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Šifrovanie peňaženky zlyhalo</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Zašifrovanie peňaženky zlyhalo kvôli vnútornej chybe. Vaša peňaženka nebola zašifrovaná.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Zadané frázy sa nezhodujú.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Odomknutie peňaženky zlyhalo</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Zadaná fráza na dešifrovanie peňaženky je nesprávna.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Odšifrovanie peňaženky zlyhalo.</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Fráza peňaženky bola úspešne zmenená.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Upozornenie: Máte zapnutý Caps Lock!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmask</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Zablokovaný do</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Podpísať &amp;správu...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Synchronizujem so sieťou...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Prehľad</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Uzol</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Ukázať celkový prehľad penňaženky</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transakcie</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Prehľadávať históriu transakcií</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>U&amp;končiť</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Odísť z peňaženky</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;O %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Ukázať informácie o %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>O &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Ukázať informácie o Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Možnosti</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Modifikovať konfigurácie nastavení pre %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Zašifrovať peňaženku</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Zálohovať peňaženku</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Zmeniť prístupovú frázu</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Adresy odosielateľov...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>&amp;Adresy prijímateľov...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Otvoriť &amp;URL</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>Peňaženka:</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>Predvolená peňaženka</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Kliknite pre odpojenie sieťovej aktivity.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Aktivity siete boli odpojené.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Kliknite pre obnovenie sieťovej aktivity.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Synchronizujem Hlavičky (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Reindexujem bloky na disk</translation>
- </message>
- <message>
- <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>Proxy je &lt;b&gt;povolené&lt;/b&gt;: %1</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Poslať mince do Bitcoin adresy</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Zálohovať peňaženku na inú lokáciu</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Zmeniť prístupovú frázu použitú pri šifrovaní peňaženky</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Ladiace okno</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Otvoriť ladiacu a diagnostickú konzolu</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Overiť správu...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Peňaženka</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Poslať</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Prijať</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Ukázať / skryť</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Ukázať alebo zakázať hlavné Okno</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Zašifrovať súkromné kľúče patriace k vašej peňaženke</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Podpísať správu s vašou Bitcoin adresou pre dokázanie že ich vlastníte</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Overiť správy pre zaručenie že boli podpísané špecifickými Bitcoin adresami</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Súbor</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Nastavenia</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Pomoc</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Panel nástrojov</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Vyžiadať platby (vygeneruje sa QR kód a bitcoin: URI)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Ukázať zoznam použitých odosielacích adries a štítkov</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Ukázať zoznam použitých prijímacích adries a štítkov</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Otvoriť Bitcoin: URI alebo vyžiadanie platby</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Možnosti príkazového riadku</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n aktívne pripojenia na Bitcoin sieti</numerusform><numerusform>%n aktívne pripojenia na Bitcoin sieti</numerusform><numerusform>%n aktívne pripojenia na Bitcoin sieti</numerusform><numerusform>%n aktívne pripojenia na Bitcoin sieti</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Indexovať bloky na disku</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Spracovávam bloky na disku</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>Spracovaných %n blokov s históriou transakcií.</numerusform><numerusform>Spracovaných %n blokov s históriou transakcií.</numerusform><numerusform>Spracovaných %n blokov s históriou transakcií.</numerusform><numerusform>Spracovaných %n blokov s históriou transakcií.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 za</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Posledný prijatý blok bol vygenerovaný pred %1 .</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Transakcie po tejto ešte nebudú viditeľné</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Chyba</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Upozornenie</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informácie</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Aktuálne</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Ukázať %1 pomocnú správu na dostanie zoznamu s možnými možnosťami v Bitcoin príkazovom riadku</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>%1 klient</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Pripája sa k Peerom</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Dobieham...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Dátum: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Čiastka: %1
-</translation>
- </message>
- <message>
- <source>Wallet: %1
-</source>
- <translation>Peňaženka: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Typ: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Štítok: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Adresa: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Odoslané transakcie</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Prichádzajúca transakcia</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>Generácia HD kľúča je &lt;b&gt;zapnutá&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>Generácia HD kľúča je &lt;b&gt;vypnutá&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>Peňaženka je &lt;b&gt;zašifrovaná&lt;/b&gt; a aktuálne &lt;b&gt;odomknutá&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>Peňaženka je &lt;b&gt;zašifrovaná&lt;/b&gt; a aktuá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>Nastala fatálna chyba. Bitcoin už nemôže pokračovať bezpečne a vypne sa.</translation>
- </message>
-</context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Výber mincí</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Množstvo:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bajty:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Čiastka:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Poplatok:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Prach:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Po zaplatení poplatku:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Zmena:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(od)značiť všetky</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Stromový režim</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Režim zoznamu</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Čiastka</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Prijaté so štítkom</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Prijaté s adresou</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Potvrdenia</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Potvrdenie</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Kopírovať adresu</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Kopírovať štítok</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopírovať čiastku</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Kopírovať ID transakcie</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Zamknúť nevyužité</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Odomknúť nevyužité</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Kopírovať množstvo</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Kopírovať poplatok</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Kopírovať po zaplatení poplatku</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Kopírovať bajty</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Kopírovať prach</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Kopírovať zmenu</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 zamknuté)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>áno</translation>
- </message>
- <message>
- <source>no</source>
- <translation>nie</translation>
- </message>
- <message>
- <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Tento štítok sa zmení na červený ak nejaký prijímateľ obdrží čiastku menšiu ako je aktuálny prah prachu</translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Môže sa kolísať o +/- %1 satoshi() za vstup</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(žiadny štítok)</translation>
- </message>
- <message>
- <source>change from %1 (%2)</source>
- <translation>zmeniť z %1 (%2)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation>(zmena)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Upraviť adresu</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Štítok</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>Štítok priradený k tejto položke zoznamu adries</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>Adresa priradená k tejto položke zoznamu adries. Toto je možné upraviť iba pre odosielanie adries.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Adresa</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Nová odosielacia adresa</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Upraviť príjimaciu adresu</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Upraviť odosielaciu adresu</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>Vložená adresa ''%1'' nie je platná Bitcoin adresa.</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>Adresa ''%1'' už existuje ako prijímacia adresa so štítkom ''%2'' .Nemôže tak byť pridaná ako odosielacia adresa.</translation>
- </message>
- <message>
- <source>The entered address "%1" is already in the address book with label "%2".</source>
- <translation>Vložená adresa ''%1'' sa už nachádza v knihe adries so štítokm ''%2''.</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Nebolo možné odomknúť peňaženku.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Generovanie nového kľúča zlyhalo.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Bude vytvorený nový adresár dát.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>meno</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>Tento adresár už existuje. Pridajte %1 ak ste tu chceli vytvoriť nový adresár.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Cesta už existuje, a nie je to adresár.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Nemôžem tu vytvoriť adresár dát.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>verzia</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>O %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Možnosti príkazového riadku</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Vitajte</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Vitajte v %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>Kedže toto je prvé spustenie programu, si môžete vybrať kde %1 bude ukladať svoje dáta.</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>Keď kliknete na OK tak %1 začne sťahovanie a spracuje celý %4 blockchain (%2GB) počnúc najmladšími transakciami v %3 keď sa %4 prvý krát spustil.</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>Počiatočná synchronizácia je veľmi náročná a môže odhaliť hardvérove problémy vo vašom počítači o ktorých ste do teraz nevedeli. Vždy keď zapnete %1 tak sa sťahovanie začne presne tam kde bolo pred vypnutím.</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>Keď ste si vybrali limit na uloženie blockchainu (zmenšenie) tak sa historické dáta budú musieť aj tak sťiahnuť a spracovať ale potom budú zmazané aby sa používanie disku znížilo.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Použiť predvolený dátový adresár</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Použiť vlastný dátový adresár:</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation>V tomto adresári bude uložené minimálne %1 GB dát, časom sa využité dáta zvýšia.</translation>
- </message>
- <message>
- <source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>V tomto adresári bude uložených približne %1 GB dát.</translation>
- </message>
- <message>
- <source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 stiahne a bude uchovávať kópiu Bitcoin blockchainu.</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation>Peňaženka bude tiež uložená v tomto adresári.</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Chyba: Špecifický dátový adresár ''%1'' nemôže byť vytvorený.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Chyba</translation>
- </message>
- <message numerus="yes">
- <source>%n GB of free space available</source>
- <translation><numerusform>Je voľných %n GB miesta na disku</numerusform><numerusform>Je voľných %n GB miesta na disku</numerusform><numerusform>Je voľných %n GB miesta na disku</numerusform><numerusform>Je voľných %n GB miesta na disku</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>(of %n GB needed)</source>
- <translation><numerusform>(z %n GB potrebných)</numerusform><numerusform>(z %n GB potrebných)</numerusform><numerusform>(z %n GB potrebných)</numerusform><numerusform>(z %n GB potrebných)</numerusform></translation>
- </message>
-</context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Forma</translation>
- </message>
- <message>
- <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation>Nedávne transakcie ešte nemusia byť viditeľné takže zostatok vo vašej peňaženke môže byť nesprávny. Táto informácia sa opraví keď sa vaša peňaženka zosynchronizuje s Bitcoin sieťou ako je popísané nižšie.</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>Pokusy o minutie bitcoinov ktoré sú ovplyvnené ešte nezobrazenými transakciami nebudú prijaté sieťou.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Číslo zostávajúcich blokov</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Neznáme...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Čas predošlého bloku</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation>Pokrok</translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation>Zvýšenie pokroku za hodinu</translation>
- </message>
- <message>
- <source>calculating...</source>
- <translation>kalkulujem...</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation>Predpokladaný čas do zosynchronizovania</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Skryť</translation>
- </message>
- <message>
- <source>Unknown. Syncing Headers (%1)...</source>
- <translation>Neznáme. Synchronizujem Hlavičky (%1)...</translation>
- </message>
-</context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>otvoriť URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Otvoriť žiadosť o platbu z URI alebo súboru</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Vyberte súbor s požiadavkou o platbu</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Vyberte súbor s požiadavkou o platbu na otvorenie</translation>
- </message>
-</context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Možnosti</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Hlavné</translation>
- </message>
- <message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation>Automaticky spustiť %1 po prihlásení sa do systému</translation>
- </message>
- <message>
- <source>&amp;Start %1 on system login</source>
- <translation>&amp;Spustiť %1 pri prihlásení sa do systému</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Veľkosť &amp;databázy cache</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>Číslo skriptu a &amp;overovacích vlákien</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>IP adresa proxy (napr. 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>Ukázať či predvolene dodané SOCKS5 proxy je používané nadosiahnutie peerov cez tento typ siete.</translation>
- </message>
- <message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Použiť oddelené SOCKS&amp;5 proxy na dosiahnutie peerov cez skryté služby Toru:</translation>
- </message>
- <message>
- <source>Hide the icon from the system tray.</source>
- <translation>Skryť ikony na systémovej lište.</translation>
- </message>
- <message>
- <source>&amp;Hide tray icon</source>
- <translation>&amp;Skryť lištu s ikonami</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>Minimalizovať namiesto zatvorenia aplikácie keď je okno zatvorené. Keď je táto možnosť zapnutá tak sa aplikácia zatvorí len po tom čo ju zatvoríte v menu.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Aktívne možnosti príkazového riadku ktoré potláčajú vyššie uvedené možnosti:</translation>
- </message>
- <message>
- <source>Open the %1 configuration file from the working directory.</source>
- <translation>Otvoriť %1 konfiguračný súbor z fungujúceho adresára.</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Otvoriť konfiguračný súbor</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Resetovať všetky možnosti klienta na predvolené.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Resetovať možnosti</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Sieť</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>Zakáže niektoré pokročilé funkcie, ale všetky bloky budú stále plne overené. Obnovenie tohto nastavenia vyžaduje opätovné prevzatie celého blockchainu. Skutočné využitie disku môže byť o niečo vyššie.</translation>
- </message>
- <message>
- <source>Prune &amp;block storage to</source>
- <translation>Zmenšiť &amp;blok úložisko na</translation>
- </message>
- <message>
- <source>GB</source>
- <translation>GB</translation>
- </message>
- <message>
- <source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation>Obnovenie tohto nastavenia vyžaduje opätovné prevzatie celého blockchainu.</translation>
- </message>
- <message>
- <source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = automaticky, &lt;0 = nechajte toľko jadier voľných)</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>P&amp;eňaženka</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Expert</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Povoliť funkcie "&amp;coin control"</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>Ak vypnete míňanie nepotvrdeného výdavku tak výdavok z transakcie bude možné použiť až keď daná transakcia bude mať aspoň jedno potvrdenie. Toto má vplyv aj na výpočet vášho zostatku.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>&amp;Míňať nepotvrdené mince</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>Automaticky otvoriť port Bitcoin klienta na routeri. Toto funguje len vtedy, keď Váš router podporuje a má zapnuté UPnP </translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Zmapovať port za pomoci &amp;UPnP</translation>
- </message>
- <message>
- <source>Accept connections from outside.</source>
- <translation>Povoliť pripojenia z vonku.</translation>
- </message>
- <message>
- <source>Allow incomin&amp;g connections</source>
- <translation>Povoliť prichá&amp;dzajúce spojenia</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Pripojiť sa k Bitcoin sieti cez SOCKS5 proxy.</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Pripojiť cez SOCKS5 proxy (predvolené 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 proxy (napr. 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation>Používa sa na oslovenie peerov prostredníctvom:</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>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Pripojiť sa k Bitcoin sieti cez osobitné SOCKS5 proxy pre skryté služby Toru</translation>
- </message>
- <message>
- <source>&amp;Window</source>
- <translation>&amp;Okno</translation>
- </message>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Ukázať lištu s ikonami len po minimalizovaní okna.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimalizovať na lištu namiesto hlavného panelu</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>M&amp;inimalizovať pri zavretí</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Ukázať</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>&amp;Jazyk používateľského rozhrania:</translation>
- </message>
- <message>
- <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation>Tu môžete nastaviť jazyk užívateľského rozhrania. Tieto nastavenia sa uskutočnia po reštarte %1</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>Ukazovať čiastky v &amp;Jednotke</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Vybrať predvolené pododdelenie jednotky na ukázanie v rozhraní a posielaní mincí.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Chcete zobrazovať funkcie mince alebo nie.</translation>
- </message>
- <message>
- <source>&amp;Third party transaction URLs</source>
- <translation>URL transakcií &amp;Tretej strany</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;OK</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Zrušiť</translation>
- </message>
- <message>
- <source>default</source>
- <translation>predvolené</translation>
- </message>
- <message>
- <source>none</source>
- <translation>žiadne</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Potvrdiť zresetovanie nastavení</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Vyžaduje sa reštart klienta na aktivovanie zmien.</translation>
- </message>
- <message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation>Klient sa vypne. Chcete pokračovať?</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Nastavenia konfigurácií</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>Konfiguračný súbor slúži na zadanie pokročilých používateľských možností, ktoré prekonávajú nastavenia GUI. Okrem toho všetky možnosti príkazového riadku prekonajú tento konfiguračný súbor.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Chyba</translation>
- </message>
- <message>
- <source>The configuration file could not be opened.</source>
- <translation>Konfiguračný súbor nemohol byť otvorený.</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Táto zmena by si vyžadovala reštart klienta.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Zadaná proxy adresa je nesprávna.</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Forma</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>Ukázaná informácia už môže byť zastaraná. Vaša peňaženka sa automaticky zosynchronizuje s Bitcoin sieťou po tom, čo bude pripojená k internetu , tento proces sa zatiaľ nedokončil.</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Len sledovať</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Dostupné:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Váš aktuálny vyčerpateľný zostatok</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Prebieha:</translation>
- </message>
- <message>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Celkový počet transakcií, ktoré ešte treba potvrdiť a zatiaľ sa nezapočítavajú do vyčerpateľného zostatku</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Nezrelý:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>Vyťažený zostatok ešte nevyspel</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Zostatky</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Spolu:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Váš aktuálny zostatok</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>Váš aktuálny zostatok v adresách watch-only</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Minuteľné:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Nedávne transakcie</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Nepotvrdené transakcie vo watch-only adresách</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Vyťažený zostatok vo watch-only adresách ktorý ešte nevyspel</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>Aktuálny celkový zostatok v adresách iba na sledovanie</translation>
- </message>
-</context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Chyba pri žiadosti o platbu</translation>
- </message>
- <message>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>Nemôžem spustiť Bitcoin: click-to-pay handler</translation>
- </message>
- <message>
- <source>URI handling</source>
- <translation>Narábanie s URI</translation>
- </message>
- <message>
- <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
- <translation>'bitcoin://' je nesprávna URI. Namiesto toho použite 'bitcoin'.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL pre stiahnutie výzvy na zaplatenie je neplatná: %1</translation>
- </message>
- <message>
- <source>Invalid payment address %1</source>
- <translation>Neplatná platobná adresa %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 nemohla byť analyzovaná. Môže to byť spôsobené neplatnou Bitcoin adresou alebo chybnými parametrami URI.</translation>
- </message>
- <message>
- <source>Payment request file handling</source>
- <translation>Spracovanie súboru so žiadosťou o platbu.</translation>
- </message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Súbor so žiadosťou o platbu nemohol byť otvorený! Toto môže byť zapríčinrné nesprávnym súborom so žiadosťou o platbu.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Žiadosť o platbu bola zamietnutá</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Sieť požiadavky na platbu nie je zhodná so sieťou klienta.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Žiadosť o platbu vypršala.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Žiadosť o platbu nebola inicializovaná.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Program nepodporuje neoverené platobné požiadavky na vlastné skripty.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Neplatná žiadosť o platbu.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Vyžiadaná čiastka %1 je príliš malá (je považovaná za prach).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Vrátiť z %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Žiadosť o platbu %1 je veľmi veľká (%2 bajtov, povolená je veľkosť do %3 bajtov).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Nastala chyba pri komunikácii %1: s %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Žiadosť o platbu nemôže byť analyzovaná!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Zlá odpoveď zo servera %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Chyba požiadavky siete</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Platba potvrdená</translation>
- </message>
-</context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>Užívateľský agent</translation>
- </message>
- <message>
- <source>Node/Service</source>
- <translation>Uzol/Servis</translation>
- </message>
- <message>
- <source>NodeId</source>
- <translation>ID uzla</translation>
- </message>
- <message>
- <source>Ping</source>
- <translation>Ping</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Odoslané</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Doručené</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Čiastka</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Vložte bitcoin adresu (napr. %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>Žiadne</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>Nie je dostupné</translation>
- </message>
- <message>
- <source>%1 ms</source>
- <translation>%1 ms</translation>
- </message>
- <message numerus="yes">
- <source>%n second(s)</source>
- <translation><numerusform>%n sekunda</numerusform><numerusform>%n sekúnd</numerusform><numerusform>%n sekúnd</numerusform><numerusform>%n sekúnd</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n minute(s)</source>
- <translation><numerusform>%n minúta</numerusform><numerusform>%n minút</numerusform><numerusform>%n minút</numerusform><numerusform>%n minút</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n hour(s)</source>
- <translation><numerusform>%n hodina</numerusform><numerusform>%n hodín</numerusform><numerusform>%n hodín</numerusform><numerusform>%n hodín</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n day(s)</source>
- <translation><numerusform>%n deň</numerusform><numerusform>%n dní</numerusform><numerusform>%n dní</numerusform><numerusform>%n dní</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n week(s)</source>
- <translation><numerusform>%n týždeň</numerusform><numerusform>%n týždňov</numerusform><numerusform>%n týždňov</numerusform><numerusform>%n týždňov</numerusform></translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 a %2</translation>
- </message>
- <message numerus="yes">
- <source>%n year(s)</source>
- <translation><numerusform>%n rok</numerusform><numerusform>%n rokov</numerusform><numerusform>%n rokov</numerusform><numerusform>%n rokov</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>%1 didn't yet exit safely...</source>
- <translation>%1 sa zatiaľ nevyplo bezpečne</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>neznáme</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- <message>
- <source>Error parsing command line arguments: %1.</source>
- <translation>Chyba pri analyzovaní argumentov príkazového riadku: %1.</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Chyba: špecifikovaný dátový adresár ''%1'' neexistuje.</translation>
- </message>
- <message>
- <source>Error: Cannot parse configuration file: %1.</source>
- <translation>Chyba: Nemôžem analyzovať konfiguračný súbor: %1.</translation>
- </message>
- <message>
- <source>Error: %1</source>
- <translation>Chyba: %1</translation>
- </message>
-</context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Uložiť obrázok...</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>&amp;Kopírovať obrázok</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>Uložiť QR kód</translation>
- </message>
- <message>
- <source>PNG Image (*.png)</source>
- <translation>Obrázok vo formáte PNG (*.png)</translation>
- </message>
-</context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>Nie je dostupné</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Verzia klienta</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Informácie</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Ladiace okno</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Všeobecné</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>Používam verziu BerkeleyDB</translation>
- </message>
- <message>
- <source>Datadir</source>
- <translation>Datadir</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Čas spustenia</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Sieť</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Meno</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Číslo pripojení</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Blockchain</translation>
- </message>
- <message>
- <source>Current number of blocks</source>
- <translation>Aktuálny počet blokov</translation>
- </message>
- <message>
- <source>Memory Pool</source>
- <translation>Memory Pool</translation>
- </message>
- <message>
- <source>Current number of transactions</source>
- <translation>Aktuálny počet transakcií</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Použitie pamäte</translation>
- </message>
- <message>
- <source>Wallet: </source>
- <translation>Peňaženka:</translation>
- </message>
- <message>
- <source>(none)</source>
- <translation>(žiadne)</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Reštart</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Doručené</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Odoslané</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Peeri</translation>
- </message>
- <message>
- <source>Banned peers</source>
- <translation>Zablokovaný Peeri</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <translation>Vyberte si peera aby ste si mohli pozrieť bližšie informácie.</translation>
- </message>
- <message>
- <source>Whitelisted</source>
- <translation>Na zozname povolených</translation>
- </message>
- <message>
- <source>Direction</source>
- <translation>Smer</translation>
- </message>
- <message>
- <source>Version</source>
- <translation>Verzia</translation>
- </message>
- <message>
- <source>Starting Block</source>
- <translation>Počiatočný blok</translation>
- </message>
- <message>
- <source>Synced Headers</source>
- <translation>Zosynchronizované hlavičky</translation>
- </message>
- <message>
- <source>Synced Blocks</source>
- <translation>Zosynchronizované bloky</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>Užívateľský agent</translation>
- </message>
- <message>
- <source>Decrease font size</source>
- <translation>Znížiť veľkosť písma</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation>Zvýšiť veľkosť písma</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Služby</translation>
- </message>
- <message>
- <source>Ban Score</source>
- <translation>Skóre zákazu</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Čas pripojenia</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Naposledy odoslané</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Naposledy doručené</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Čas pingu</translation>
- </message>
- <message>
- <source>The duration of a currently outstanding ping.</source>
- <translation>Trvanie momentálne nevyriešeného pingu.</translation>
- </message>
- <message>
- <source>Ping Wait</source>
- <translation>Čakanie pingu</translation>
- </message>
- <message>
- <source>Min Ping</source>
- <translation>Minimálny ping</translation>
- </message>
- <message>
- <source>Time Offset</source>
- <translation>Čas vyváženia</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Čas predošlého bloku</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Otvoriť</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Konzola</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Sieťová prevádzka</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Spolu</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Do:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Z:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Debugovať súbor s logom</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Vyčistiť konzolu</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;hodina</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;deň</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;týždeň</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;rok</translation>
- </message>
- <message>
- <source>&amp;Disconnect</source>
- <translation>&amp;Odpojiť</translation>
- </message>
- <message>
- <source>Ban for</source>
- <translation>Zablokovať na</translation>
- </message>
- <message>
- <source>&amp;Unban</source>
- <translation>&amp;Odblokovať</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>Predvolená peňaženka</translation>
- </message>
- <message>
- <source>Welcome to the %1 RPC console.</source>
- <translation>Vitajte v %1 RPC konzole.</translation>
- </message>
- <message>
- <source>Type %1 for an overview of available commands.</source>
- <translation>Napíšte %1 pre prehľad dostupných príkazov.</translation>
- </message>
- <message>
- <source>For more information on using this console type %1.</source>
- <translation>Pre viac informácii na používanie tejto konzoly napíšte %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>UPOZORNENIE: Podvodníci sú aktívny. Podvodníci hovoria používateľom aby tu písali rôzne príkazy čím ukradnú obsah ich peňaženiek. Nepoužívajte túto konzolu bez toho, aby ste vedeli čo presne tieto príkazy znamenajú.</translation>
- </message>
- <message>
- <source>Network activity disabled</source>
- <translation>Aktivita siete bola vypnutá</translation>
- </message>
- <message>
- <source>Executing command without any wallet</source>
- <translation>Vykonávam príkaz bez peňaženky</translation>
- </message>
- <message>
- <source>Executing command using "%1" wallet</source>
- <translation>Vykonávam príkaz za použitia peňaženky ''%1''</translation>
- </message>
- <message>
- <source>(node id: %1)</source>
- <translation>(ID uzla: %1)</translation>
- </message>
- <message>
- <source>via %1</source>
- <translation>cez %1</translation>
- </message>
- <message>
- <source>never</source>
- <translation>nikdy</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Prichádzajúci</translation>
- </message>
- <message>
- <source>Outbound</source>
- <translation>Odchádzajúci</translation>
- </message>
- <message>
- <source>Yes</source>
- <translation>Áno</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nie</translation>
- </message>
- <message>
- <source>Unknown</source>
- <translation>Neznáme</translation>
- </message>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>&amp;Čiastka:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Štítok:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Správa:</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>Nepovinná správa ktorá bude pripojená k žiadosti o platbu. Správa bude zobrazená po otvorení žiadosti o platbu. Táto správa nebude odoslaná spolu s platbou na Bitcoin sieti.</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation>Nepovinný štítok na priradenie k novej príjimaciej adrese.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Používajte túto formu pri vyžiadaní platieb. Všetky políčka sú &lt;b&gt;nepovinné&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>Voliteľná čiastka na vyžiadanie. Ak nechce vyžiadať špecifickú čiastku tak zanechajte pole prázdne alebo doň napíšte nulu.</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Zmazať všetky políčka formulára.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Zmazať</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>Natívne segwit adresy (ako Bech32 alebo BIP-173) neskôr zredukujú váš transakčný poplatok a ponúkajú lepšiu ochranu proti preklepom, staré peňaženky ich ale nepodporujú. Keď toto pole nie je začiarknuté tak sa vytvorí adresa ktorá bude kompatibilná so starými peňaženkami.</translation>
- </message>
- <message>
- <source>Generate native segwit (Bech32) address</source>
- <translation>Vygenerovať natívnu segwit (Bech32) adresu</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>História vyžiadaných platieb</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Vyžiadať platbu</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Ukázať vybranú žiadosť (rovnaké ako dvojité kliknutie na položku)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Ukázať</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Vymazať vybrané položky zo zoznamu</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Vymazať</translation>
- </message>
- <message>
- <source>Copy URI</source>
- <translation>Skopírovať URI</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Kopírovať štítok</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Skopírovať správu</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopírovať čiastku</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>QR kód</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Skopírovať &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Skopírovať &amp;Adresu</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Uložiť obrázok...</translation>
- </message>
- <message>
- <source>Request payment to %1</source>
- <translation>Vyžiadať platbu do %1</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation>Informácie 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>Čiastka</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Štítok</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Správa</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Peňaženka</translation>
- </message>
- <message>
- <source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation>Výsledná URI je príliš dlhá, skúste zmenšiť text pre štítok / správu.</translation>
- </message>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation>Chyba pri kódovaní URI do QR kódu</translation>
- </message>
-</context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Štítok</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Správa</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(žiadny štítok)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation>(žiadna správa)</translation>
- </message>
- <message>
- <source>(no amount requested)</source>
- <translation>(nebola vyžiadaná žiadna čiastka)</translation>
- </message>
- <message>
- <source>Requested</source>
- <translation>Vyžiadané</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Poslať mince</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Funkcie kontroly mincí</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Vstupy...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>automaticky vybrané</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Nedostatok mincí!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Množstvo:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bajty:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Čiastka:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Poplatok:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Po zaplatení poplatku:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Zmena:</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>Ak je táto možnosť aktivovaná ale adresa pre výdavok je prázdna alebo neplatná, výdavok bude poslaný na novovytvorenú adresu.</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Vlastná adresa zmeny</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Transakčný poplatok:</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Vybrať...</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>Použitie fallbackfee môže vyústiť v transakciu, ktorá bude trvať hodiny alebo dni (prípadne večnosť) , kým bude potvrdená. Zvážte preto manuálne nastavenie poplatku, alebo počkajte kým sa Vám kompletne zvaliduje reťazec blokov.</translation>
- </message>
- <message>
- <source>Warning: Fee estimation is currently not possible.</source>
- <translation>Upozornenie: Momentálne nie je možné odhadnúť cenu transakčného poplatku.</translation>
- </message>
- <message>
- <source>collapse fee-settings</source>
- <translation>zbaliť nastavenia poplatkov</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>Špecifikujte vlastný transakčný polatok za 1 kB (1000 bajtov) virtuálnej veľkosti transakcie.
-
-Zapamätajte si: Keďže cena poplatku je počítaná za bajt, tak poplatok o hodnote ''100 satoshi za kB'' pri veľkosti transakcie 500 bajtov (polovica z 1kB) by stál len 50 satoshi.</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>za kilobajt</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Skryť</translation>
- </message>
- <message>
- <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
- <translation>Zaplatenie len minimálneho poplatku je v poriadku, pokiaľ existuje menej transakcií ako miesta v blokoch. Uvedomte si však, že ak bude vyšší dopyt po transakciách ako dokáže sieť spracovať, môže byť vaša transakcia oneskorená alebo dokonca nikdy nepotvrdená.</translation>
- </message>
- <message>
- <source>(read the tooltip)</source>
- <translation>(prečítajte si radu)</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Odporúčané:</translation>
- </message>
- <message>
- <source>Custom:</source>
- <translation>Vlastné:</translation>
- </message>
- <message>
- <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>( ,,Múdre'' poplatky zatiaľ neboli začané. Malo by to zvyčajne zabrať pár blokov...)</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Poslať viacerím príjimateľom na raz</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>Pridať &amp;Prijímateľa</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Zmazať všetky políčka formulára.</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Prach:</translation>
- </message>
- <message>
- <source>Confirmation time target:</source>
- <translation>Časový cieľ na potvrdenie:</translation>
- </message>
- <message>
- <source>Enable Replace-By-Fee</source>
- <translation>Povoliť nahradenie poplatkom</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>S nahradením poplatkov (BIP-125) môžete zvýšiť transakčný poplatok po tom, čo je transakcia odoslaná. Bez tejto funkcie je odporúčaný vyšší poplatok aby sa predišlo oneskoreniu transakcie.</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Vymazať &amp;Všetko</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Zostatok:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Potvrdiť odoslanie</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>P&amp;oslať</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Kopírovať množstvo</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopírovať čiastku</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Kopírovať poplatok</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Kopírovať po zaplatení poplatku</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Kopírovať bajty</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Kopírovať prach</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Kopírovať zmenu</translation>
- </message>
- <message>
- <source>%1 (%2 blocks)</source>
- <translation>%1 (%2 blokov)</translation>
- </message>
- <message>
- <source>%1 to %2</source>
- <translation>%1 do %2</translation>
- </message>
- <message>
- <source>Are you sure you want to send?</source>
- <translation>Ste si istý že chcete odoslať?</translation>
- </message>
- <message>
- <source>or</source>
- <translation>alebo</translation>
- </message>
- <message>
- <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
- <translation>Poplatok môžete zvýšiť neskôr (signalizácia nahradenia poplatku, BIP-125).</translation>
- </message>
- <message>
- <source>from wallet %1</source>
- <translation>z peňaženky %1</translation>
- </message>
- <message>
- <source>Please, review your transaction.</source>
- <translation>Prosím, skontrolujte svoju transakciu.</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Transakčný poplatok</translation>
- </message>
- <message>
- <source>Not signalling Replace-By-Fee, BIP-125.</source>
- <translation>Nesignalizujem nahradenie poplatku, BIP-125</translation>
- </message>
- <message>
- <source>Total Amount</source>
- <translation>Celková Čiastka</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation>Potvrdiť odoslanie mincí</translation>
- </message>
- <message>
- <source>The recipient address is not valid. Please recheck.</source>
- <translation>Adresa príjimateľa je nesprávna. Prosím skontrolujte ju.</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation>Čiastka na zaplatenie musí byť väčšia ako 0.</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation>Táto čiastka je väčšia ako váš zostatok.</translation>
- </message>
- <message>
- <source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>Celková suma presahuje váš zostatok po tom, čo je k sume pridaný %1 transakčný poplatok.</translation>
- </message>
- <message>
- <source>Duplicate address found: addresses should only be used once each.</source>
- <translation>Boli nájdené duplicitné adresy: každá adresa by sa mala použiť len raz.</translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation>Vytvorenie transakcie zlyhalo!</translation>
- </message>
- <message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Transakcia bola odmietnutá kvôli: %1</translation>
- </message>
- <message>
- <source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation>Poplatok väčší ako %1 je považovaný za absurdne veľký poplatok.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Žiadosť o platbu vypršala.</translation>
- </message>
- <message>
- <source>Pay only the required fee of %1</source>
- <translation>Zaplaťte len vyžadovaný poplatok %1</translation>
- </message>
- <message numerus="yes">
- <source>Estimated to begin confirmation within %n block(s).</source>
- <translation><numerusform>Predpoklad na začanie potvrdenia do %n bloku.</numerusform><numerusform>Predpoklad na začanie potvrdenia do %n blokov.</numerusform><numerusform>Predpoklad na začanie potvrdenia do %n blokov.</numerusform><numerusform>Predpoklad na začanie potvrdenia do %n blokov.</numerusform></translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation>Upozornenie: Nesprávna Bitcoin adresa</translation>
- </message>
- <message>
- <source>Warning: Unknown change address</source>
- <translation>Upozornenie: Neznáma zmena adresy</translation>
- </message>
- <message>
- <source>Confirm custom change address</source>
- <translation>Potvrďte vlastnú zmenu adresy</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>Adresa ktorú chcete zmeniť nie je súčasťou tejto peňaženky. Všetky peňažné prostriedky z Vašej peňaženky môžu byť poslané na túto adresu. Ste si istý?</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(žiadny štítok)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>Č&amp;iastka</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>Zaplatiť &amp;to</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Štítok:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Vyberte si predchádzajcu použitú adresu</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Toto je normálna platba</translation>
- </message>
- <message>
- <source>The Bitcoin address to send the payment to</source>
- <translation>Bitcoin adresa do ktorej môžete poslať platbu</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Prilepiť adresu zo schránky</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Vymazať tento vstup</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>Poplatok bude odčítaný z čiastky ktorá bola odoslaná. Prijímateľ obdrží menej Bitcoinov ako vložíte do poľa s čiastkou. Ak ste si vybrali viacerích prijímateľov tak bude poplatok rozdelený rovnomerne.</translation>
- </message>
- <message>
- <source>S&amp;ubtract fee from amount</source>
- <translation>O&amp;dčítať poplatok z čiastky</translation>
- </message>
- <message>
- <source>Use available balance</source>
- <translation>Použiť dostupný zostatok</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Správa:</translation>
- </message>
- <message>
- <source>This is an unauthenticated payment request.</source>
- <translation>Toto je neoverená žiadosť o platbu.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation>Toto je overená žiadosť o platbu.</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Zadajte štítok pre túto adresu aby ste ju pridali do zoznamu použitých adries.</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>Správa pripojená k Bitcoin URI ktorá bude uložená spolu s transakciou pre vašu referenciu. Poznámka: Táto správa nebude odoslaná cez Bitcoin sieť.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Zaplatiť:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Poznámka:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Zadajte štítok pre túto adresu aby ste ju pridali do vašej knihy adries</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Áno</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>%1 is shutting down...</source>
- <translation>%1 sa vypína...</translation>
- </message>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>Nevypínajte počítač pokým toto okno nezmizne.</translation>
- </message>
-</context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Podpisy - Podpísať / overiť Správu</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Podpísať Správu</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>Môžete podpísať správy / dohody s vašimi adresami, aby ste dokázali, že môžete obdržať Bitcoiny ktoré tam boli zaslané. Buďte opatrný a nikdy nepodpodpisujte nič náhodné alebo nejasné, kedže phishing útoky sa vás môžu pokúsiť naviesť na podpísanie vašej indentity. Podpisujte len podrobné vyhlásenia s ktorými súhlasíte.</translation>
- </message>
- <message>
- <source>The Bitcoin address to sign the message with</source>
- <translation>Bitcoin adresa na podpísanie správy</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Vyberte si predchádzajcu použitú adresu</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Prilepiť adresu zo schránky</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Tu vložte správu ktorú chcete podpísať</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Podpis</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Skopírovať aktuálny podpis do clipboardu systému</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Podpíšte túto správu na overenie vlastníctva tejto Bitcoin adresy</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Podpísať &amp;Správu</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Resetovať všetky políčka s podpisovaním správy</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Vymazať &amp;Všetko</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Overiť správu</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>Vložte adresu príjemcu a správu (uistite sa, že presne kopírujete ukončenia riadkov, medzery, odseky atď.) a podpis pre potvrdenie správy. Buďte opatrní a nedomýšľajte si viac než je uvedené v samotnej podpísanej správe a môžete sa tak vyhnúť podvodu Man-in-the-middle útokom. Poznámka: Toto len potvrdzuje, že podpisujúca strana môže prijímať na tejto adrese, nepotvrdzuje to vlastníctvo žiadnej transakcie!</translation>
- </message>
- <message>
- <source>The Bitcoin address the message was signed with</source>
- <translation>Bitcoin adresa s ktorou bola táto správa podpísaná</translation>
- </message>
- <message>
- <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Overte správu aby ste sa uistili že bola podpísaná so špecifickou Bitcoin adresou</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Overiť &amp;Správu</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Resetovať všetky políčka overenia správy</translation>
- </message>
- <message>
- <source>Click "Sign Message" to generate signature</source>
- <translation>Kliknite na ''Podpísať Správu'' na vygenerovanie podpisu.</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation>Zadaná adresa je nesprávna.</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Prosím skontrolujte adresu a skúste to znova.</translation>
- </message>
- <message>
- <source>The entered address does not refer to a key.</source>
- <translation>Zadaná adresa neodkazuje na kľúč.</translation>
- </message>
- <message>
- <source>Wallet unlock was cancelled.</source>
- <translation>Odomknutie peňaženky bolo zatvorené.</translation>
- </message>
- <message>
- <source>Private key for the entered address is not available.</source>
- <translation>Súkromný kľúč pre zadanú adresu nie je dostupný.</translation>
- </message>
- <message>
- <source>Message signing failed.</source>
- <translation>Podpísanie správy zlyhalo.</translation>
- </message>
- <message>
- <source>Message signed.</source>
- <translation>Správa bola podpísaná.</translation>
- </message>
- <message>
- <source>The signature could not be decoded.</source>
- <translation>Podpis nemohol byť dekódovaný.</translation>
- </message>
- <message>
- <source>Please check the signature and try again.</source>
- <translation>Prosím skontrolujte podpis a skúste to znova.</translation>
- </message>
- <message>
- <source>The signature did not match the message digest.</source>
- <translation>Podpis sa nezhoduje s výťahom zo správy.</translation>
- </message>
- <message>
- <source>Message verification failed.</source>
- <translation>Overenie správy zlyhalo.</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation>Správa overená.</translation>
- </message>
-</context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <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>Otvorené ešte %n blokov</numerusform><numerusform>Otvorené ešte %n blokov</numerusform><numerusform>Otvorené ešte %n blokov</numerusform><numerusform>Otvorené ešte %n blokov</numerusform></translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Otvorené do %1</translation>
- </message>
- <message>
- <source>conflicted with a transaction with %1 confirmations</source>
- <translation>stretnutie s transakciou s %1 potvrdeniami</translation>
- </message>
- <message>
- <source>0/unconfirmed, %1</source>
- <translation>0/nepotvrdené, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation>v memory poole</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation>nenachádza sa v memory poole</translation>
- </message>
- <message>
- <source>abandoned</source>
- <translation>opustené</translation>
- </message>
- <message>
- <source>%1/unconfirmed</source>
- <translation>%1/nepotvrdené</translation>
- </message>
- <message>
- <source>%1 confirmations</source>
- <translation>%1 potvrdení</translation>
- </message>
- <message>
- <source>Status</source>
- <translation>Status</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Zdroj</translation>
- </message>
- <message>
- <source>Generated</source>
- <translation>Generované</translation>
- </message>
- <message>
- <source>From</source>
- <translation>Z</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>neznáme</translation>
- </message>
- <message>
- <source>To</source>
- <translation>Do</translation>
- </message>
- <message>
- <source>own address</source>
- <translation>vlastná adresa</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>len na sledovanie</translation>
- </message>
- <message>
- <source>label</source>
- <translation>štítok</translation>
- </message>
- <message>
- <source>Credit</source>
- <translation>Kredit</translation>
- </message>
- <message numerus="yes">
- <source>matures in %n more block(s)</source>
- <translation><numerusform>Vyzrie o %n blokov</numerusform><numerusform>Vyzrie o %n blokov</numerusform><numerusform>Vyzrie o %n blokov</numerusform><numerusform>Vyzrie o %n blokov</numerusform></translation>
- </message>
- <message>
- <source>not accepted</source>
- <translation>neprijaté</translation>
- </message>
- <message>
- <source>Debit</source>
- <translation>Dlh</translation>
- </message>
- <message>
- <source>Total debit</source>
- <translation>Dlh spolu</translation>
- </message>
- <message>
- <source>Total credit</source>
- <translation>Kredit spolu</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Transakčný poplatok</translation>
- </message>
- <message>
- <source>Net amount</source>
- <translation>Čistá čiastka</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Správa</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Komentár</translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation>ID transakcie</translation>
- </message>
- <message>
- <source>Transaction total size</source>
- <translation>Celková veľkosť transakcie</translation>
- </message>
- <message>
- <source>Transaction virtual size</source>
- <translation>Virtuálna veľkosť transakcie</translation>
- </message>
- <message>
- <source>Output index</source>
- <translation>Výstupný index</translation>
- </message>
- <message>
- <source>Merchant</source>
- <translation>Obchodník</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>Vygenerované mince musia vyzrieť %1 blokov kým môžu byť minuté. Keď ste vytvorili tento blok tak bol odoslaný do siete aby sa pridal do blockchainu. Keď sa nedostane do reťaze tak sa neho stav zmení na ''Zamietnutý'' a nebude sa dať míňať. Toto sa môže príležitostne stať keď iný uzol vygeneruje block pár sekúnd prev vaším.</translation>
- </message>
- <message>
- <source>Debug information</source>
- <translation>Informácie o ladení</translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation>Transakcia</translation>
- </message>
- <message>
- <source>Inputs</source>
- <translation>Vstupy</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Čiastka</translation>
- </message>
- <message>
- <source>true</source>
- <translation>pravda</translation>
- </message>
- <message>
- <source>false</source>
- <translation>nepravda</translation>
- </message>
-</context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Táto tabuľa ukazuje detailný popis transakcie</translation>
- </message>
- <message>
- <source>Details for %1</source>
- <translation>Detaily pre %1</translation>
- </message>
-</context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Typ</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Štítok</translation>
- </message>
- <message numerus="yes">
- <source>Open for %n more block(s)</source>
- <translation><numerusform>Otvorené ešte %n blokov</numerusform><numerusform>Otvorené ešte %n blokov</numerusform><numerusform>Otvorené ešte %n blokov</numerusform><numerusform>Otvorené ešte %n blokov</numerusform></translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Otvorené do %1</translation>
- </message>
- <message>
- <source>Unconfirmed</source>
- <translation>Nepotvrdené</translation>
- </message>
- <message>
- <source>Abandoned</source>
- <translation>Opustené</translation>
- </message>
- <message>
- <source>Confirming (%1 of %2 recommended confirmations)</source>
- <translation>Potvrdzujem (%1 z %2 odporúčaných potvrdení)</translation>
- </message>
- <message>
- <source>Confirmed (%1 confirmations)</source>
- <translation>Potvrdené (%1 potvrdení)</translation>
- </message>
- <message>
- <source>Conflicted</source>
- <translation>Konfliktné</translation>
- </message>
- <message>
- <source>Immature (%1 confirmations, will be available after %2)</source>
- <translation>Nevyzrelý (%1 potvrdení, bude dostupné po %2 potvrdeniach1ň</translation>
- </message>
- <message>
- <source>Generated but not accepted</source>
- <translation>Vygenerované ale neprijaté</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Prijaté s</translation>
- </message>
- <message>
- <source>Received from</source>
- <translation>Prijaté od</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Odoslané do</translation>
- </message>
- <message>
- <source>Payment to yourself</source>
- <translation>Platba pre samého seba</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Vyťažené</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>len na sledovanie</translation>
- </message>
- <message>
- <source>(n/a)</source>
- <translation>(nie je dostupné)</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(žiadny štítok)</translation>
- </message>
- <message>
- <source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>Status transakcie. Namierte kurzor na toto pole aby ste videli počet potvrdení.</translation>
- </message>
- <message>
- <source>Date and time that the transaction was received.</source>
- <translation>Dátum a čas prijata transakcie.</translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation>Typ transakcie.</translation>
- </message>
- <message>
- <source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation>Či sa táto adresa určená len na sledovanie zapojila v tejto transakcii alebo nie.</translation>
- </message>
- <message>
- <source>User-defined intent/purpose of the transaction.</source>
- <translation>Užívateľom definovaný zámer/ účel transakcie.</translation>
- </message>
- <message>
- <source>Amount removed from or added to balance.</source>
- <translation>Čiastka zmazaná alebo pridaná do zostatku.</translation>
- </message>
-</context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Všetko</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Dnes</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>Tento týždeň</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>Tento mesiac</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Minulý mesiac</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Tento rok</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Rozsah...</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Doručené s</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Odoslané do</translation>
- </message>
- <message>
- <source>To yourself</source>
- <translation>Sebe</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Vyťažené</translation>
- </message>
- <message>
- <source>Other</source>
- <translation>Ostatné</translation>
- </message>
- <message>
- <source>Enter address, transaction id, or label to search</source>
- <translation>Zadajte adresu, ID transakcie alebo štítok aby ste mohli vyhľadávať</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation>Minimálna čiastka</translation>
- </message>
- <message>
- <source>Abandon transaction</source>
- <translation>Opustiť transakciu</translation>
- </message>
- <message>
- <source>Increase transaction fee</source>
- <translation>Zvýšiť transakčný poplatok</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Kopírovať adresu</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Kopírovať štítok</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Kopírovať čiastku</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Kopírovať ID transakcie</translation>
- </message>
- <message>
- <source>Copy raw transaction</source>
- <translation>Skopírovať raw transakciu</translation>
- </message>
- <message>
- <source>Copy full transaction details</source>
- <translation>Skopírovať všetky detaily transakcie</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Upraviť štítok</translation>
- </message>
- <message>
- <source>Show transaction details</source>
- <translation>Ukázať detaily transakcie</translation>
- </message>
- <message>
- <source>Export Transaction History</source>
- <translation>Exportovať Históriu Transakcií</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Čiarkou oddelené zložky (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Potvrdenie</translation>
- </message>
- <message>
- <source>Watch-only</source>
- <translation>Len sledovať</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Dátum</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Typ</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Štítok</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>ID</source>
- <translation>ID</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Exportovanie zlyhalo</translation>
- </message>
- <message>
- <source>There was an error trying to save the transaction history to %1.</source>
- <translation>Nastala chyba pri ukladaní histórie transakcií do %1.</translation>
- </message>
- <message>
- <source>Exporting Successful</source>
- <translation>Exportovanie úspešné.</translation>
- </message>
- <message>
- <source>The transaction history was successfully saved to %1.</source>
- <translation>História transakcií bola úspešne uložená do %1.</translation>
- </message>
- <message>
- <source>Range:</source>
- <translation>Rozsah...</translation>
- </message>
- <message>
- <source>to</source>
- <translation>do</translation>
- </message>
-</context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- <message>
- <source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Jednotka v ktorej chete zobrazovať čiastky. Kliknite ak si chcete vybrať inú jednotku.</translation>
- </message>
-</context>
-<context>
- <name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>Nebola načítaná žiadna peňaženka.</translation>
- </message>
-</context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Poslať mince</translation>
- </message>
- <message>
- <source>Fee bump error</source>
- <translation>Chyba pri zvyšovaní transakčného poplatku</translation>
- </message>
- <message>
- <source>Increasing transaction fee failed</source>
- <translation>Zvýšnie transakčného poplatku zlyhalo</translation>
- </message>
- <message>
- <source>Do you want to increase the fee?</source>
- <translation>Chcete zvýšiť transakčný poplatok?</translation>
- </message>
- <message>
- <source>Current fee:</source>
- <translation>Aktuálny transakčný poplatok:</translation>
- </message>
- <message>
- <source>Increase:</source>
- <translation>Navýšenie:</translation>
- </message>
- <message>
- <source>New fee:</source>
- <translation>Nový transakčný poplatok:</translation>
- </message>
- <message>
- <source>Confirm fee bump</source>
- <translation>Potvrdiť zvýšnie transakčného poplatku</translation>
- </message>
- <message>
- <source>Can't sign transaction.</source>
- <translation>Nemožno podpísať transakciu.</translation>
- </message>
- <message>
- <source>Could not commit transaction</source>
- <translation>Nemožno uskutočniť transakciu</translation>
- </message>
-</context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Exportovať</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Exportovať dáta z aktuálnej karty do zložky</translation>
- </message>
- <message>
- <source>Backup Wallet</source>
- <translation>Zálohovať peňaženku</translation>
- </message>
- <message>
- <source>Wallet Data (*.dat)</source>
- <translation>Dáta Peňaženky (*.dat)</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>Zálohovanie zlyhalo</translation>
- </message>
- <message>
- <source>There was an error trying to save the wallet data to %1.</source>
- <translation>Nastala chyba pri ukladaní dát peňaženky do %1.</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Zálohovanie úspešné</translation>
- </message>
- <message>
- <source>The wallet data was successfully saved to %1.</source>
- <translation>Dáta peňaženky boli úspešne uložené do %1.</translation>
- </message>
- <message>
- <source>Cancel</source>
- <translation>Zatvoriť</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>Distribuované pod licenciou softvéru MIT, pozrite si sprevádzajúci súbor %s alebo %s</translation>
- </message>
- <message>
- <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation>Zmenšenie nastavené pod minimálnu hodnotu %d MiB. Prosím použite vyššiu hodnotu.</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>Zmenšenie: posledná synchronizácia peňaženky prekračuje zmenšené dáta. Musíte použiť -reindex (opäť stiahnuť celý blockchain pre prípad zmenšeného uzla)</translation>
- </message>
- <message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Prehľadnia nie v zmenšenom uzle možné. Butete musieť použiť -reindex, ktorý opäť stiahne celý blockchain.</translation>
- </message>
- <message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Chyba: Nastala fatálna vnútorná chyba, pozrite si debug.log pre viac informácií</translation>
- </message>
- <message>
- <source>Pruning blockstore...</source>
- <translation>Zmenšujem blockstore...</translation>
- </message>
- <message>
- <source>Unable to start HTTP server. See debug log for details.</source>
- <translation>Nebolo možné spustiť HTTP server. Pozrite si debug log pre viac informácií.</translation>
- </message>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>The %s developers</source>
- <translation>Vývojári %s</translation>
- </message>
- <message>
- <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
- <translation>Nebolo možné získať zámok v dátovom adresári %s. %s Je už pravdepodobne zapnuté.</translation>
- </message>
- <message>
- <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
- <translation>Nemožno zadať konkrétne spojenie a zároveň mať nastavený addrman pre hľadanie odchádzajúcich spojení.</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>Chyba pri čítaní %s! Všetky kľúče boli prečítané správne, ale dáta transakcie alebo knihy adries chýbajú alebo sú nesprávne.</translation>
- </message>
- <message>
- <source>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: %u)</source>
- <translation>Skupinové výstupy z adresy, pri vybratí všetkých alebo žiadnych adries, namiesto vyberania na báze za výstup. Súkromie je vylepšené keďže adresa je použitá len raz (až na to, keď niekto na túto adresu niečo pošle po míňaní z tejto adresy), ale môže vyústiť v trochu väčšie poplatky keďže suboptimálny výber mincí môže vyústiť v pridanú limitáciu (predvolené: %u)</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>Prosím skontrolujte si, či má vaš počítač správne nastavený dátum a čas! Ak sú vaše hodiny nesprávne tak %s nebude fungovať tak, ako by malo,</translation>
- </message>
- <message>
- <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <translation>Prosím prispejte ak %s považujete za užitočné. Navštívte %s pre viac informácií o softwéri,</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>Databáza blokov obsahuje blok, ktorý vyzerá ako blok z budúcnosti. Toto môže byť zapríčinené zle nastaveným časom a dátumom. Prestavajte databázu blokov len keď si ste istý, že váš čas a dátum je nastavený správne</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>Toto je predbežné vydanie - používajte na vaše riziko - nepoužívajte na ťaženie alebo ak ste obchodník, na prijímanie platieb.</translation>
- </message>
- <message>
- <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>Toto je transakčný poplatok ktorý môžete vyhodiť ak je zmena menšia ako úroveň prachu.</translation>
- </message>
- <message>
- <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <translation>Nebolo možné prehrať blok. Budete musieť prestavať databázu použitím -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>Nebolo možné vrátiť databázu do obdobia pred forkom. Budete musieť znovu stiahnuť blockchain.</translation>
- </message>
- <message>
- <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>Upozornenie: Sieť s týmto úplne nesúhlasí! Niektorí ťažiči majú problémy.</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>Upozornenie: My plne nesúhlasíme so svojimi peermi! Buď budete musieť aktualizovať svoj uzol vy, alebo ostatné uzly.</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 bolo porušené, záchrana zlyhala</translation>
- </message>
- <message>
- <source>-maxmempool must be at least %d MB</source>
- <translation>-maxmempool musí mať minimálne %d MB</translation>
- </message>
- <message>
- <source>Change index out of range</source>
- <translation>Zmena indexu mimo rozsah</translation>
- </message>
- <message>
- <source>Copyright (C) %i-%i</source>
- <translation>Copyright (C) %i-%i</translation>
- </message>
- <message>
- <source>Corrupted block database detected</source>
- <translation>Bola zistená poškodená databáza blokov</translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Chcete prestavať databázu blokov teraz?</translation>
- </message>
- <message>
- <source>Error creating %s: You can't create non-HD wallets with this version.</source>
- <translation>Chyba pri vytváraní %s: Nemôžete vytvoriť nie-HD peňaženku v tejto verzii.</translation>
- </message>
- <message>
- <source>Error initializing block database</source>
- <translation>Chyba pri inicializácii databázy blokov</translation>
- </message>
- <message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Chyba pri incializácii prostredia %s databázy peňaženky!</translation>
- </message>
- <message>
- <source>Error loading %s</source>
- <translation>Chyba pri načítavaní %s</translation>
- </message>
- <message>
- <source>Error loading %s: Private keys can only be disabled during creation</source>
- <translation>Chyba pri načítavaní %s: Súkromné kľúče môžu byť deaktivované len počas vytvárania</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet corrupted</source>
- <translation>Chyba pri načítavaní %s: Peňaženka poškodená</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet requires newer version of %s</source>
- <translation>Chyba pri načítavaní %s: Peňaženka si vyžaduje novšiu verziu %s</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Chyba pri načítavaní databázy blokov</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Chyba pri otváraní databázy blokov</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Chyba: Málo miesta na disku!</translation>
- </message>
- <message>
- <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>Chyba počúvania na ktoromkoľvek porte. Použi -listen=0 keď chcete urobiť toto.</translation>
- </message>
- <message>
- <source>Failed to rescan the wallet during initialization</source>
- <translation>Zlyhalo prehľadávanie peňaženky počas inicializácie</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>Importujem...</translation>
- </message>
- <message>
- <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>Bol nájdený poškodený alebo žaidny počiatočný blok. Nesprávne datadir pre sieť?</translation>
- </message>
- <message>
- <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>Nesprávna čiastka pre -%s=&lt;amount&gt;:'%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
- <translation>Neplatná čiastka pre -discardfee=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>Neplatná čiastka pre -fallbackfee=&lt;amount&gt;:'%s'</translation>
- </message>
- <message>
- <source>Specified blocks directory "%s" does not exist.</source>
- <translation>Špecifikovaný adresár blokov ''%s'' neexistuje.</translation>
- </message>
- <message>
- <source>Upgrading txindex database</source>
- <translation>Vylepšujem databázu txindex</translation>
- </message>
- <message>
- <source>Loading P2P addresses...</source>
- <translation>Načítavam P2P adresy...</translation>
- </message>
- <message>
- <source>Loading banlist...</source>
- <translation>Načítavam zoznam zablokovaných...</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>Nie je k dispozícii dostatok deskriptorov súborov.</translation>
- </message>
- <message>
- <source>Prune cannot be configured with a negative value.</source>
- <translation>Zmenšenie nemôže byť konfigurované s negatívnou hodnotou.</translation>
- </message>
- <message>
- <source>Prune mode is incompatible with -txindex.</source>
- <translation>Mód zmenšenia je nekompatibilný s -txindex</translation>
- </message>
- <message>
- <source>Replaying blocks...</source>
- <translation>Prehrávam bloky...</translation>
- </message>
- <message>
- <source>Rewinding blocks...</source>
- <translation>Pretáčam bloky...</translation>
- </message>
- <message>
- <source>The source code is available from %s.</source>
- <translation>Zdrojový kód je dostupný z %s.</translation>
- </message>
- <message>
- <source>Transaction fee and change calculation failed</source>
- <translation>Kalkulácia transakčného poplatku a zmeny zlyhala.</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer. %s is probably already running.</source>
- <translation>Nebolo možné spojiť s %s na tomto počítači. %s už pravdepodoble je zapnuté.</translation>
- </message>
- <message>
- <source>Unable to generate keys</source>
- <translation>Nebolo možné vygenerovať kľúče.</translation>
- </message>
- <message>
- <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
- <translation>Nepodporovaný argument -benchmark bol ignorovaný, použite -debug=bench.</translation>
- </message>
- <message>
- <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
- <translation>Nepodporovaný argument -debugnet bol ignorovaný, použite -debug=net.</translation>
- </message>
- <message>
- <source>Unsupported argument -tor found, use -onion.</source>
- <translation>Našiel sa nepodporovaný argument -tor , použite -onion.</translation>
- </message>
- <message>
- <source>Unsupported logging category %s=%s.</source>
- <translation>Nepodporovaná logovacia kategória %s=%s.</translation>
- </message>
- <message>
- <source>Upgrading UTXO database</source>
- <translation>Vylepšujem UTXO databázu</translation>
- </message>
- <message>
- <source>User Agent comment (%s) contains unsafe characters.</source>
- <translation>Komentár používateľského agenta (%s) obsahuje nebezpečné znaky.</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Overujem bloky...</translation>
- </message>
- <message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Chyba: Počúvanie prichádzajúcich spojení zlyhalo (vrátená chyba je %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>transactions) Neplatná suma pre -maxtxfee=&lt;amount&gt;: '%s' (aby sa transakcia nezasekla, minimálny transakčný poplatok musí byť aspoň %s)</translation>
- </message>
- <message>
- <source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>Čiastka transakcie je po odčítaní transakčného poplatku veľmi malá</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>Musíte znova prestavať databázu použitím -reindex aby ste sa mohli vrátiť to nezmenšeného módu. Toto stiahne celý blockchain od znova</translation>
- </message>
- <message>
- <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
- <translation>hyba pri načítavaní %s: nemôžeš vypnúť HD už existujúcej HD peňaženky</translation>
- </message>
- <message>
- <source>Error reading from database, shutting down.</source>
- <translation>Chyba pri čítaní z databázy, vypína sa.</translation>
- </message>
- <message>
- <source>Error upgrading chainstate database</source>
- <translation>Chyba pri aktualizovaní chainstate databázy</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informácie</translation>
- </message>
- <message>
- <source>Invalid -onion address or hostname: '%s'</source>
- <translation>Nesprávna -onion adresa alebo hostname: '%s'</translation>
- </message>
- <message>
- <source>Invalid -proxy address or hostname: '%s'</source>
- <translation>Nesprávna -proxy adresa alebo hostname: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation>Neplatná čiastka pre -paytxfee=&lt;amount&gt;: '%s' (musí byť aspoň %s)</translation>
- </message>
- <message>
- <source>Invalid netmask specified in -whitelist: '%s'</source>
- <translation>Zadaná neplatná netmask vo -whitelist: '%s'</translation>
- </message>
- <message>
- <source>Need to specify a port with -whitebind: '%s'</source>
- <translation>Je potrebné zadať port s -whitebind: '%s'</translation>
- </message>
- <message>
- <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <translation>Zredukované -maxconnections z %d na %d kvôli systémovým obmedzeniam.</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Podpísanie transacie zlyhalo</translation>
- </message>
- <message>
- <source>Specified -walletdir "%s" does not exist</source>
- <translation>Špecifikované -walletdir ''%s'' neexistuje</translation>
- </message>
- <message>
- <source>Specified -walletdir "%s" is a relative path</source>
- <translation>Špecifikovaná -walletdir ''%s'' je príbuzná cesta</translation>
- </message>
- <message>
- <source>Specified -walletdir "%s" is not a directory</source>
- <translation>Špecifikované -walletdir ''%s'' nie je adresár</translation>
- </message>
- <message>
- <source>The transaction amount is too small to pay the fee</source>
- <translation>Transakčná čiastka je veľmi malá na zaplatenie poplatku</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>Toto je experimentálny softwér.</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Transakčná čiastka je veľmi malá</translation>
- </message>
- <message>
- <source>Transaction too large for fee policy</source>
- <translation>Transakcia je príliš veľká pre aktuálnu politiku poplatkov</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Transakcia je veľmi veľká</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation>Na tomto počítači sa nedá vytvoriť väzba %s (vytvorenie väzby vrátilo chybu %s)</translation>
- </message>
- <message>
- <source>Unable to generate initial keys</source>
- <translation>Nebolo možné vytvoriť počiatočné kľúče</translation>
- </message>
- <message>
- <source>Verifying wallet(s)...</source>
- <translation>Overujem peňaženku(y)...</translation>
- </message>
- <message>
- <source>Wallet %s resides outside wallet directory %s</source>
- <translation>Peňaženka %s sa nachádza mimo adresára s peňaženkou %s</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Upozornenie</translation>
- </message>
- <message>
- <source>Warning: unknown new rules activated (versionbit %i)</source>
- <translation>Upozornenie: boli aktivované nové, neznáme pravidlá (versionbit %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! Tak veľké polatky by boli zapatené na jedinú transakciu,</translation>
- </message>
- <message>
- <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
- <translation>Chyba pri načítavaní %s: Nemôžete povoliť HD na už existujúcich non-HD peňaženkách</translation>
- </message>
- <message>
- <source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation>Toto je transakčný poplatok ktorý môžete zaplatiť keď odhady poplatkov nie sú dostupné.</translation>
- </message>
- <message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Tento produkt zahrňuje softwér vyvinutý projektom OpenSSL pre použite v OpenSSL Toolkite %s a kryptografický program od Erika Younga a program UPnP od Thomasa Bernarda.</translation>
- </message>
- <message>
- <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <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>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
- <translation>Boli nájdené nepodporované -socks argumenty. Nastavenie SOCKS verzie už nie je možné, sú podporované len SOCKS5 proxy.</translation>
- </message>
- <message>
- <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
- <translation>Nepodporovaný argument -whitelistalwaysrelay ignorovaný, použite -whitelistrelay a/alebo -whitelistforcerelay.</translation>
- </message>
- <message>
- <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
- <translation>Upozornenie: Práve sa ťaží neznáma verzia bloku! Platia jeho možné neznáme pravidlá</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>Upozornenie: Súbor s peňaženkou bol poškodený, dáta boli zachránené. Originál %s uložený ako %s v %s; keď je váš zostatok alebo transakcie zobrazený nesprávne tak by ste mali obnoviť peňaženku zo zálohy.</translation>
- </message>
- <message>
- <source>%s is set very high!</source>
- <translation>%s je nastavené veľmi vysoko!</translation>
- </message>
- <message>
- <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
- <translation>Chyba pri načítavaní peňaženky %s. Zadaný duplicitný názov súboru -wallet.</translation>
- </message>
- <message>
- <source>Keypool ran out, please call keypoolrefill first</source>
- <translation>Vyčerpal sa keypool, najprv prosím zavolajte keypoolrefill</translation>
- </message>
- <message>
- <source>Starting network threads...</source>
- <translation>Spúšťam sieťové vlákna...</translation>
- </message>
- <message>
- <source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation>Peňaženka zabráni zaplateniu menšej sumy ako je minimálny poplatok.</translation>
- </message>
- <message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Toto je minimálny transakčný poplatok ktorý musíte zaplatiť za každú transakciu</translation>
- </message>
- <message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Toto je transakčný poplatok ktorý zaplatíte keď odošlete transakciu.</translation>
- </message>
- <message>
- <source>Transaction amounts must not be negative</source>
- <translation>Transakčná čiastka nemôže byť záporná.</translation>
- </message>
- <message>
- <source>Transaction has too long of a mempool chain</source>
- <translation>Transakcia má v mempoole príliš dlhý reťazec</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>Transakcia musí mať aspoň jedného príjemcu</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Neznáma sieť špcifikovaná v -onlynet: '%s'</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Nedostatočné prostriedky</translation>
- </message>
- <message>
- <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
- <translation>Nemožno vygenerovať kľúč na zmenu adresy. Súkromné kľúče sú v tejto peňaženke zakázané.</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>Nemožno vylepšiť non-HD oddelenú peňaženku bez aktualizovania na podporu keypoolu pre oddelením. Prosím použite -upgradewallet=169900 alebo -upgradewallet bez špecifikovanej verzie.</translation>
- </message>
- <message>
- <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
- <translation>Odhad poplatku zlyhal. Fallbackfee je zablokovaný. Počkajte niekoľko blokov alebo povoľte -fallbackfee</translation>
- </message>
- <message>
- <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <translation>Upozornenie: Súkromné kľúče zistené v peňaženke {%s} so zakázanými súkromnými kľúčmi.</translation>
- </message>
- <message>
- <source>Cannot write to data directory '%s'; check permissions.</source>
- <translation>Nemožno písať do dátového adresára '%s'; skontrolujte povolenia.</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Načítavam index blokov...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Načítavam peňaženku...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Nemožno degradovať peňaženku</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Prehľadávam...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Načítavanie dokončené</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Chyba</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_sl.ts b/src/qt/locale/bitcoin_sl.ts
index dd003dda88..251c040a22 100644
--- a/src/qt/locale/bitcoin_sl.ts
+++ b/src/qt/locale/bitcoin_sl.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Desni klik za urejanje naslovov ali oznak</translation>
+ <translation>Desni klik za urejanje naslova ali oznake</translation>
</message>
<message>
<source>Create a new address</source>
@@ -47,11 +47,11 @@
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Izberi naslov prejemnika kovancev</translation>
+ <translation>Izberi naslov prejemnika</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>Izberi naslov, na katerega želiš prejeti kovance</translation>
+ <translation>Izberi naslov, na katerega želiš prejeti sredstva</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -63,11 +63,15 @@
</message>
<message>
<source>Receiving addresses</source>
- <translation>Imenik naslovov za prejemanje</translation>
+ <translation>Imenik prejemnih naslovov</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>To so vaši Bitcoin naslovi za pošiljanje. Pred pošiljanjem vedno preverite količino in prejemnikov naslov.</translation>
+ <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>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -87,7 +91,7 @@
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>Podatki ločenimi z vejico (*.csv)</translation>
+ <translation>Podatki, ločeni z vejico (*.csv)</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -165,7 +169,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>Opozorilo: V primeru izgube gesla šifrirane denarnice, boste &lt;b&gt;IZGUBILI VSE SVOJE BITCOINE&lt;/b&gt;!</translation>
+ <translation>Opozorilo: V primeru izgube gesla šifrirane denarnice boste &lt;b&gt;IZGUBILI VSE SVOJE BITCOINE&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -180,6 +184,14 @@
<translation>Vnesite novo geslo za denarnico. &lt;br/&gt;Prosimo, uporabite geslo z vsaj &lt;b&gt;10 ali več naključnimi simboli&lt;/b&gt;, ali vsaj osmimi besedami.&lt;b&gt;</translation>
</message>
<message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Vnesite staro geslo in novo geslo za denarnico.</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>Pomnite, da šifriranje denarnice ne more preprečiti kraje bitcoinov preko morebitnih virusov na vašem računalniku.</translation>
+ </message>
+ <message>
<source>Wallet to be encrypted</source>
<translation>Denarnica, ki bo zašifrirana</translation>
</message>
@@ -193,7 +205,7 @@
</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>POMEMBNO: Vse starejše varnostne kopije denarnice je potrebno zamenjati z novoizdelano, šifrirano, varnostno kopijo. Zaradi varnosti bodo stare varnostne kopije postale neuporabne takoj, ko začnete uporabljati novo, šifrirano denarnico.</translation>
+ <translation>POMEMBNO: Vse starejše varnostne kopije denarnice je potrebno zamenjati z novo, šifrirano datoteko denarnice. Zaradi varnosti bodo stare varnostne kopije postale neuporabne takoj, ko začnete uporabljati novo, šifrirano denarnico.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
@@ -209,7 +221,7 @@
</message>
<message>
<source>Wallet unlock failed</source>
- <translation>Denarnice ni bilo mogoče odkleniti.</translation>
+ <translation>Denarnice ni bilo mogoče odkleniti</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
@@ -217,7 +229,7 @@
</message>
<message>
<source>Wallet decryption failed</source>
- <translation>Dešifriranje denarnice ni uspelo</translation>
+ <translation>Dešifriranje denarnice neuspešno</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
@@ -236,7 +248,7 @@
</message>
<message>
<source>Banned Until</source>
- <translation>Prepoved do</translation>
+ <translation>Blokiran do</translation>
</message>
</context>
<context>
@@ -271,11 +283,11 @@
</message>
<message>
<source>Quit application</source>
- <translation>Ustavite program</translation>
+ <translation>Izhod iz programa</translation>
</message>
<message>
<source>&amp;About %1</source>
- <translation>&amp;O nas%1</translation>
+ <translation>&amp;O %1</translation>
</message>
<message>
<source>Show information about %1</source>
@@ -327,7 +339,7 @@
</message>
<message>
<source>Click to disable network activity.</source>
- <translation>Kliknite, da onemogočite omrežno aktivnosti.</translation>
+ <translation>S klikom onemogočite omrežno aktivnost.</translation>
</message>
<message>
<source>Network activity disabled.</source>
@@ -335,7 +347,7 @@
</message>
<message>
<source>Click to enable network activity again.</source>
- <translation>Kliknite, da ponovno vključite omrežno aktivnost.</translation>
+ <translation>S klikom ponovno vključite omrežno aktivnost.</translation>
</message>
<message>
<source>Syncing Headers (%1%)...</source>
@@ -347,11 +359,11 @@
</message>
<message>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>Namestniški strežnik je omogočen&lt;/b&gt;: %1</translation>
+ <translation>Posredniški strežnik je &lt;b&gt;omogočen&lt;/b&gt;: %1</translation>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation>Izvedite plačilo na naslov Bitcoin</translation>
+ <translation>Izvedite plačilo na bitcoin-naslov</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -362,14 +374,6 @@
<translation>Spremenite geslo za šifriranje denarnice</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Razhroščevalno okno</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Odprite razhroščevalno in diagnostično konzolo</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Preveri sporočilo ...</translation>
</message>
@@ -395,11 +399,11 @@
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Podpišite poljubno sporočilo z enim svojih naslovov Bitcoin, da prejemniku sporočila dokažete, da je ta naslov v vaši lasti.</translation>
+ <translation>Podpišite poljubno sporočilo z enim svojih bitcoin-naslovov, da prejemniku sporočila dokažete, da je ta naslov v vaši lasti.</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Preverite, če je bilo prejeto sporočilo podpisano z določenim naslovom Bitcoin</translation>
+ <translation>Preverite, če je bilo prejeto sporočilo podpisano z določenim bitcoin-naslovom.</translation>
</message>
<message>
<source>&amp;File</source>
@@ -419,7 +423,7 @@
</message>
<message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Zahtevajte plačilo (ustvarite zahtevek s kodo QR in URI tipa bitcoin:)</translation>
+ <translation>Zahtevajte plačilo (ustvarite zahtevek s kodo QR in URI tipa bitcoin)</translation>
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
@@ -430,12 +434,8 @@
<translation>Preglejte in uredite seznam naslovov, na katere ste kdaj prejeli plačila</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Izvedite plačilo iz zahtevka v datoteki ali iz URI tipa bitcoin:</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
- <translation>Opcije &amp;ukazne vrstice</translation>
+ <translation>Možnosti &amp;ukazne vrstice</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
@@ -443,7 +443,7 @@
</message>
<message>
<source>Indexing blocks on disk...</source>
- <translation>Indeksirani bloki na disku ...</translation>
+ <translation>Ustvarjam kazalo blokov na disku ...</translation>
</message>
<message>
<source>Processing blocks on disk...</source>
@@ -455,7 +455,7 @@
</message>
<message>
<source>%1 behind</source>
- <translation>imam še %1 zaostanka</translation>
+ <translation>%1 zaostanka</translation>
</message>
<message>
<source>Last received block was generated %1 ago.</source>
@@ -479,7 +479,15 @@
</message>
<message>
<source>Up to date</source>
- <translation>Posodobljeno</translation>
+ <translation>Ažurno</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation>Okno vozlišča</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Odpri konzolo za razhroščevanje in diagnostiko</translation>
</message>
<message>
<source>&amp;Sending addresses</source>
@@ -487,7 +495,11 @@
</message>
<message>
<source>&amp;Receiving addresses</source>
- <translation>&amp;Naslovi za prejemanje ...</translation>
+ <translation>&amp;Naslovi za prejemanje</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Odpri URI tipa bitcoin:</translation>
</message>
<message>
<source>Open Wallet</source>
@@ -599,11 +611,11 @@
</message>
<message>
<source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>Generiranje HD ključa je &lt;b&gt;omogočeno&lt;/b&gt;</translation>
+ <translation>HD-tvorba ključev je &lt;b&gt;omogočena&lt;/b&gt;</translation>
</message>
<message>
<source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>Generiranje HD ključa je &lt;b&gt;onemogočeno&lt;/b&gt;</translation>
+ <translation>HD-tvorba ključev je &lt;b&gt;onemogočena&lt;/b&gt;</translation>
</message>
<message>
<source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
@@ -619,7 +631,7 @@
</message>
<message>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Napaka. Bitcoin ne more več varno nadaljevati in se bo zaprl.</translation>
+ <translation>Prišlo je do usodne napake. Bitcoin ne more več varno nadaljevati in se bo zaprl.</translation>
</message>
</context>
<context>
@@ -758,7 +770,7 @@
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Se lahko razlikuje +/- %1 satošijev na vnos.</translation>
+ <translation>Se lahko razlikuje +/- %1 satoši(jev) na vhod.</translation>
</message>
<message>
<source>(no label)</source>
@@ -783,7 +795,11 @@
<source>Create wallet failed</source>
<translation>Ustvarjanje denarnice neuspešno</translation>
</message>
- </context>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Opozorilo za ustvarjanje denarnice</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
<message>
@@ -796,13 +812,25 @@
</message>
<message>
<source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
- <translation>Šifriraj denarnico. Denarnica bo bila šifrirana z geslom po vaši izbiri.</translation>
+ <translation>Šifriraj denarnico. Denarnica bo šifrirana z geslom, ki ga izberete.</translation>
</message>
<message>
<source>Encrypt Wallet</source>
<translation>Šifriraj denarnico</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>Onemogoči zasebne ključe za to denarnico. Denarnice z onemogočenimi zasebnimi ključi ne bodo imele zasebnih ključev in ne morejo imeti HD-semena ali uvoženih zasebnih ključev. To je primerno za opazovane denarnice.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>Onemogoči zasebne ključe</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>Ustvari prazno denarnico. Prazne denarnice ne vključujejo zasebnih ključev ali skript. Pozneje lahko uvozite zasebne ključe ali vnesete HD-seme.</translation>
+ </message>
+ <message>
<source>Make Blank Wallet</source>
<translation>Ustvari prazno denarnico</translation>
</message>
@@ -839,7 +867,7 @@
</message>
<message>
<source>Edit receiving address</source>
- <translation>Nov naslov za prejemanje</translation>
+ <translation>Uredi prejemni naslov</translation>
</message>
<message>
<source>Edit sending address</source>
@@ -847,11 +875,11 @@
</message>
<message>
<source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>Vnešeni naslov %1 ni veljaven Bitcoin naslov.</translation>
+ <translation>Vnešeni naslov "%1" ni veljaven bitcoin-naslov.</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>Naslov %1 že obstaja kot naslov za prejemanje z oznako "%2" in ga je nemogoče dodati kot naslov za pošiljanje.</translation>
+ <translation>Naslov "%1" že obstaja kot naslov za prejemanje z oznako "%2" in ga je nemogoče dodati kot naslov za pošiljanje.</translation>
</message>
<message>
<source>The entered address "%1" is already in the address book with label "%2".</source>
@@ -896,10 +924,6 @@
<translation>različica</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>O %1</translation>
</message>
@@ -924,15 +948,19 @@
</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>Ko kliknete OK, bo %1 začel prenašati podatke in procesirati celotno %4 bazo podatkovnih blokov (%2 GB), začenši z najstarejšo transakcijo in z %3 ob prvotnem začetku %4.</translation>
+ <translation>Ko kliknete OK, bo %1 začel prenašati podatke in procesirati celotno %4 verigo blokov (%2 GB), začenši z najstarejšo transakcijo iz %3 ob prvotnem začetku %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>Če spremenite to nastavitev, morate ponovno naložiti celotno verigo blokov. Hitreje je najprej prenesti celotno verigo in jo obrezati pozneje. Ta nastavitev onemogoči nekatere napredne funkcije.</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>Začetna sinhronizacija je zelo zahtevna in lahko odkrije probleme s strojno opremo v vašem računalniku, ki so prej bili neopaženi. Vsakič, ko zaženete %1, bo le-ta nadaljeval s prenosom kjer je ostal.</translation>
+ <translation>Začetna sinhronizacija je zelo zahtevna in lahko odkrije probleme s strojno opremo v vašem računalniku, ki so prej bili neopaženi. Vsakič, ko zaženete %1, bo le-ta nadaljeval s prenosom, kjer je prejšnjič ostal.</translation>
</message>
<message>
<source>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>Če ste se odločili omejiti shranjevanje blokovnih verig (obrezovanje), je treba zgodovinske podatke še vedno prenesti in obdelati, vendar jih boste pozneje izbrisali, da bo uporaba diska nizka.</translation>
+ <translation>Če ste se odločili omejiti shranjevanje blokovnih verig (obrezovanje), je treba zgodovinske podatke še vedno prenesti in obdelati, vendar bodo kasneje izbrisani, da bo uporaba diska nizka.</translation>
</message>
<message>
<source>Use the default data directory</source>
@@ -947,6 +975,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Po verifikaciji zavrzite vse bloke, razen zadnjih %1 GB (obrezava)</translation>
+ </message>
+ <message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation>Vsaj %1 GB podatkov bo shranjenih v tem direktoriju, velikost podatkov pa bo s časom naraščala.</translation>
</message>
@@ -956,7 +988,7 @@
</message>
<message>
<source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 bo prenesel in shranil kopijo Bitcoin baze podatkovnih blokov.</translation>
+ <translation>%1 bo prenesel in shranil kopijo verige blokov.</translation>
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
@@ -972,7 +1004,7 @@
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
- <translation><numerusform>%n GiB prostega prostora na voljo</numerusform><numerusform>%n GiB prostega prostora na voljo</numerusform><numerusform>%n GiB prostega prostora na voljo</numerusform><numerusform>%n GiB prostega prostora na voljo</numerusform></translation>
+ <translation><numerusform>%n GiB prostega prostora na voljo</numerusform><numerusform>%n GiB prostega prostora na voljo</numerusform><numerusform>%n GiB prostega prostora na voljo</numerusform><numerusform>%n GB prostega prostora na voljo</numerusform></translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
@@ -991,11 +1023,11 @@
</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>Zadnje transakcije morda še niso vidne, zato je stanje v denarnici morda napačno. Ti podatki bodo pravilni, ko se bo vaša denarnica končala s sinhronizacijo z bitcoin omrežjem, kot je podrobneje opisano spodaj.</translation>
+ <translation>Zadnje transakcije morda še niso vidne, zato je prikazano stanje v denarnici lahko napačno. Pravilni podatki bodo prikazani, ko bo vaša denarnica končala s sinhronizacijo z bitcoin omrežjem; glejte podrobnosti spodaj.</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>Poskus porabe bitcoinov, na katere vplivajo še ne prikazane transakcije, omrežje ne bo sprejelo.</translation>
+ <translation>Poskusa pošiljanja bitcoinov, na katere vplivajo še ne prikazane transakcije, omrežje ne bo sprejelo.</translation>
</message>
<message>
<source>Number of blocks left</source>
@@ -1019,7 +1051,7 @@
</message>
<message>
<source>calculating...</source>
- <translation>Računam ...</translation>
+ <translation>računam ...</translation>
</message>
<message>
<source>Estimated time left until synced</source>
@@ -1030,32 +1062,28 @@
<translation>Skrij</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 se trenutno sinhronizira. Od soležnikov bodo preneseni in preverjeni zaglavja in bloki do vrha verige.</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
- <translation>Neznano. Sinhroniziram glave (%1, %2%)...</translation>
+ <translation>Neznano. Sinhroniziram glave (%1, %2%) ...</translation>
</message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Odpri URl</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Vnesite zahtevek za plačilo iz URI ali pa ga naložite iz datoteke</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Odpri bitcoin-URI</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Izbiranje datoteke z zahtevkom za plačilo</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Izberi datoteko za zahtevek plačila</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1064,6 +1092,10 @@
<translation>Odpiranje denarnice neuspešno</translation>
</message>
<message>
+ <source>Open wallet warning</source>
+ <translation>Opozorilo za odpiranje denarnice</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>privzeta denarnica</translation>
</message>
@@ -1092,15 +1124,15 @@
</message>
<message>
<source>Size of &amp;database cache</source>
- <translation>Velikost &amp;predpomnilnika podatkovne baze</translation>
+ <translation>Velikost &amp;predpomnilnika podatkovne baze:</translation>
</message>
<message>
<source>Number of script &amp;verification threads</source>
- <translation>Število programskih &amp;niti za preverjanje</translation>
+ <translation>Število programskih &amp;niti za preverjanje:</translation>
</message>
<message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Naslov IP posredniškega strežnika (npr. IPv4: 127.0.0.1 ali IPv6: ::1)</translation>
+ <translation>IP naslov posredniškega strežnika (npr. IPv4: 127.0.0.1 ali IPv6: ::1)</translation>
</message>
<message>
<source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
@@ -1112,7 +1144,7 @@
</message>
<message>
<source>Hide the icon from the system tray.</source>
- <translation>Skrij ikono na pladnju.</translation>
+ <translation>Skrij ikono na sistemskem pladnju.</translation>
</message>
<message>
<source>&amp;Hide tray icon</source>
@@ -1124,7 +1156,7 @@
</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>Naslovi URL tretjih oseb (npr. raziskovalec blokov), ki bodo navedeni v kontekstnem meniju seznama transakcij. Niz %s iz naslova URL je nadomeščen s hash vrednostjo transakcije. Več zaporednih naslovov URL je med seboj ločenih z znakom |.</translation>
+ <translation>Naslovi URL-jev tretjih oseb (npr. raziskovalec blokov), ki bodo navedeni v kontekstnem meniju seznama transakcij. Niz %s v nastavljenem URL-naslovu bo zamenjan z identifikatorjem transakcije. Več zaporednih naslovov URL lahko med seboj ločite z navpičnico |.</translation>
</message>
<message>
<source>Open the %1 configuration file from the working directory.</source>
@@ -1148,11 +1180,11 @@
</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>Onemogoči nekatere napredne funkcije, vendar bodo vsi bloki še vedno v celoti potrjeni. Če spremenite to nastavitev, morate ponovno naložiti celoten blok. Dejanska poraba diskov je morda nekoliko večja.</translation>
+ <translation>Ta nastavitev onemogoči nekatere napredne funkcije, vendar bodo vsi bloki še vedno v celoti preverjeni. Če spremenite to nastavitev, morate ponovno naložiti celotno verigo blokov. Dejanska poraba na disku je lahko nekoliko večja od nastavitve.</translation>
</message>
<message>
<source>Prune &amp;block storage to</source>
- <translation>Obreži velikost podatkovne baze na </translation>
+ <translation>Obreži velikost podatkovne &amp;baze na</translation>
</message>
<message>
<source>GB</source>
@@ -1180,15 +1212,15 @@
</message>
<message>
<source>Enable coin &amp;control features</source>
- <translation>Omogoči upravljanje s kovanci</translation>
+ <translation>Omogoči &amp;upravljanje s kovanci</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>Če onemogočite trošenje drobiža iz še nepotrjenih transakcij, potem vrnjenega drobiža ne morete uporabiti, dokler plačilo ni vsaj enkrat potrjeno. Ta opcija vpliva tudi na izračun stanja sredstev.</translation>
+ <translation>Če onemogočite trošenje vračila iz še nepotrjenih transakcij, potem vračila ne morete uporabiti, dokler plačilo ni vsaj enkrat potrjeno. Ta opcija vpliva tudi na izračun stanja sredstev.</translation>
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
- <translation>Omogoči &amp;trošenje drobiža iz še nepotrjenih plačil</translation>
+ <translation>Omogoči &amp;trošenje vračila iz še nepotrjenih plačil</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>
@@ -1204,7 +1236,7 @@
</message>
<message>
<source>Allow incomin&amp;g connections</source>
- <translation>&amp;Dovoli dohodne povezave</translation>
+ <translation>Dovoli &amp;dohodne povezave</translation>
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
@@ -1216,7 +1248,7 @@
</message>
<message>
<source>Proxy &amp;IP:</source>
- <translation>Naslov &amp;IP posredniškega strežnika:</translation>
+ <translation>&amp;IP naslov posredniškega strežnika:</translation>
</message>
<message>
<source>&amp;Port:</source>
@@ -1280,7 +1312,7 @@
</message>
<message>
<source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Izberite privzeto mersko enoto za prikaz v uporabniškem vmesniku in pri pošiljanju kovancev.</translation>
+ <translation>Izberite privzeto mersko enoto za prikaz v uporabniškem vmesniku in pri pošiljanju.</translation>
</message>
<message>
<source>Whether to show coin control features or not.</source>
@@ -1288,11 +1320,11 @@
</message>
<message>
<source>&amp;Third party transaction URLs</source>
- <translation>URL nakazila tretjih oseb</translation>
+ <translation>URL za nakazila &amp;tretjih oseb:</translation>
</message>
<message>
<source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation>Možnosti, nastavljene v tem pogovornem oknu so preglašene v ukazni vrstici ali konfiguracijski datoteki:</translation>
+ <translation>Možnosti, nastavljene v tem pogovornem oknu, ki so bile preglašene v ukazni vrstici ali konfiguracijski datoteki:</translation>
</message>
<message>
<source>&amp;OK</source>
@@ -1300,7 +1332,7 @@
</message>
<message>
<source>&amp;Cancel</source>
- <translation>&amp;Prekliči</translation>
+ <translation>P&amp;rekliči</translation>
</message>
<message>
<source>default</source>
@@ -1308,7 +1340,7 @@
</message>
<message>
<source>none</source>
- <translation>nič</translation>
+ <translation>(jih ni)</translation>
</message>
<message>
<source>Confirm options reset</source>
@@ -1367,7 +1399,7 @@
</message>
<message>
<source>Your current spendable balance</source>
- <translation>Skupni znesek vaših sredstev, s katerimi lahko prosto razpolagate</translation>
+ <translation>Skupno dobroimetje na razpolago</translation>
</message>
<message>
<source>Pending:</source>
@@ -1375,7 +1407,7 @@
</message>
<message>
<source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Skupni znesek sredstev s katerimi še ne razpolagate prosto, ker so del še nepotrjenih transakcij.</translation>
+ <translation>Skupni znesek sredstev, s katerimi še ne razpolagate prosto, ker so del še nepotrjenih transakcij.</translation>
</message>
<message>
<source>Immature:</source>
@@ -1395,7 +1427,7 @@
</message>
<message>
<source>Your current total balance</source>
- <translation>Trenutna vsota vseh vaših sredstev</translation>
+ <translation>Trenutno skupno dobroimetje</translation>
</message>
<message>
<source>Your current balance in watch-only addresses</source>
@@ -1407,7 +1439,7 @@
</message>
<message>
<source>Recent transactions</source>
- <translation>Nedavne transakcije</translation>
+ <translation>Zadnje transakcije</translation>
</message>
<message>
<source>Unconfirmed transactions to watch-only addresses</source>
@@ -1441,16 +1473,16 @@
<translation>'bitcoin://' ni veljaven URI. Uporabite raje 'bitcoin:' .</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Uporabljate BIP70 URL, ki v prihodnosti ne bo podprt.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>Ne morem obdelati plačila, ker BIP70 ni podprt.</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Naslov URL za pridobitev zahtevka za plačilo ni veljaven: %1</translation>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Zaradi varnostnih napak v BIP70 priporočamo, da se kakršna koli navodila trgovca za zamenjavo denarnic ne upoštevajo.</translation>
</message>
<message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Zahteve za plačilo ni mogoče obdelati, ker podpora za BIP70 ni bila sestavljena v Bitcoin Core.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Če ste prejeli to napako, zaprosite prejemnika za URI, ki je združljiv z BIP21.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1458,72 +1490,12 @@
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>URI je neprepoznaven! Možno je, da je naslov Bitcoin neveljaven, ali da so parametri v URI napačno oblikovani.</translation>
+ <translation>URI je neprepoznaven! Možno je, da je bitcoin-naslov neveljaven ali pa so parametri URI-ja napačno oblikovani.</translation>
</message>
<message>
<source>Payment request file handling</source>
<translation>Rokovanje z datoteko z zahtevkom za plačilo</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Datoteke z zahtevkom za plačilo ni mogoče prebrati! Možno je, da datoteka ni veljavna.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Zahtevek za plačilo zavrnjen</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Zahtevek za plačilo in vaš odjemalec se nahajata na dveh različnih omrežjih.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Zahtevek za plačilo je potekel.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Zahtevek za plačilo ni inicializiran.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Nepreverjeni zahtevki za plačilo, namenjeni plačilni skripti po meri, niso podprti.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Neveljaven zahtevek za plačilo.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Znesek %1 v zahtevku za plačilo je prenizek (smatran za prah).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Povračilo od %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Zahtevek za plačilo %1 je prevelik (%2 bajtov, dovoljenih je %3 bajtov.)</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Napaka pri povezavi z %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Zahtevek za plačilo je neprepoznaven!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Napačen odziv strežnika %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Napaka pri zahtevku za plačilo</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Plačilo potrjeno</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1560,7 +1532,7 @@
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Vnesite naslov Bitcoin (npr. %1):</translation>
+ <translation>Vnesite bitcoin-naslov (npr. %1)</translation>
</message>
<message>
<source>%1 d</source>
@@ -1604,11 +1576,11 @@
</message>
<message numerus="yes">
<source>%n day(s)</source>
- <translation><numerusform>%n dan</numerusform><numerusform>%n dni</numerusform><numerusform>%n dni</numerusform><numerusform>%n dni</numerusform></translation>
+ <translation><numerusform>%n dan</numerusform><numerusform>%n dneva</numerusform><numerusform>%n dnevi</numerusform><numerusform>%n dni</numerusform></translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
- <translation><numerusform>%n teden</numerusform><numerusform>%n tedna</numerusform><numerusform>%n tedne</numerusform><numerusform>%n tednov</numerusform></translation>
+ <translation><numerusform>%n teden</numerusform><numerusform>%n tedna</numerusform><numerusform>%n tedni</numerusform><numerusform>%n tednov</numerusform></translation>
</message>
<message>
<source>%1 and %2</source>
@@ -1659,7 +1631,7 @@
<name>QRImageWidget</name>
<message>
<source>&amp;Save Image...</source>
- <translation>&amp;Shrani sliko ...</translation>
+ <translation>&amp;Shrani sliko</translation>
</message>
<message>
<source>&amp;Copy Image</source>
@@ -1701,16 +1673,12 @@
<translation>&amp;Informacije</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Razhroščevalno okno</translation>
- </message>
- <message>
<source>General</source>
<translation>Splošno</translation>
</message>
<message>
<source>Using BerkeleyDB version</source>
- <translation>BerkeleyDB različica v rabi</translation>
+ <translation>Uporabljena različica BerkeleyDB</translation>
</message>
<message>
<source>Datadir</source>
@@ -1754,7 +1722,7 @@
</message>
<message>
<source>Memory Pool</source>
- <translation>Memory Pool</translation>
+ <translation>Čakalna vrsta transakcij</translation>
</message>
<message>
<source>Current number of transactions</source>
@@ -1762,7 +1730,7 @@
</message>
<message>
<source>Memory usage</source>
- <translation>Raba spomina</translation>
+ <translation>Raba pomnilnika</translation>
</message>
<message>
<source>Wallet: </source>
@@ -1798,7 +1766,7 @@
</message>
<message>
<source>Whitelisted</source>
- <translation>Dovoljeni</translation>
+ <translation>Na seznamu dovoljenih</translation>
</message>
<message>
<source>Direction</source>
@@ -1825,6 +1793,10 @@
<translation>Ime agenta</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Okno vozlišča</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>
@@ -1946,7 +1918,7 @@
</message>
<message>
<source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
- <translation>Uporabite tipki gor in dol za navigacijo po zgodovini ukazov, in %1 za čiščenje zaslona.</translation>
+ <translation>Uporabite tipki gor in dol za navigacijo po zgodovini ukazov in %1 za čiščenje zaslona.</translation>
</message>
<message>
<source>Type %1 for an overview of available commands.</source>
@@ -1958,7 +1930,7 @@
</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>OPOZORILO: Goljufi so bili aktivni! Uporabnikom svetujejo, naj tukaj vnašajo ukaze in jim tako kradejo vsebino denarnice. Te konzole ne uporabljajte, če ne popolnoma razumete posledic ukazov.</translation>
+ <translation>OPOZORILO: Goljufi so aktivni! Uporabnikom svetujejo, naj tukaj vnašajo ukaze, s čimer jim ukradejo vsebino denarnice. To konzolo uporabljajte le, če popolnoma razumete posledice ukazov.</translation>
</message>
<message>
<source>Network activity disabled</source>
@@ -2036,8 +2008,16 @@
<translation>Zahtevani znesek. Če ne zahtevate določenega zneska, pustite prazno ali nastavite vrednost na 0.</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>Neobvezna oznaka, povezana z novim prejemnim naslovom. Uporabite jo lahko za prepoznavo plačila. Zapisana bo tudi v zahtevek za plačilo.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Neobvezna oznaka, ki se shrani v zahtevek za plačilo in se lahko prikaže plačniku.</translation>
+ </message>
+ <message>
<source>&amp;Create new receiving address</source>
- <translation>&amp;Ustvari nov naslov za prejemanje</translation>
+ <translation>&amp;Ustvari nov prejemni naslov</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
@@ -2049,11 +2029,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>Nativni naslovi segwit (aka Bech32 ali BIP-173) kasneje znižajo vaše transakcijske stroške in nudijo boljšo zaščito pred tiskarskimi škrati, vendar jih stare denarnice ne podpirajo. Če ne izberete polja, bo namesto tega ustvarjen naslov združljiv s starejšimi denarnicami.</translation>
+ <translation>Lastni naslovi segwit (Bech32 ali BIP-173) kasneje znižajo vaše transakcijske stroške in nudijo boljšo zaščito pred tiskarskimi škrati, vendar jih stare denarnice ne podpirajo. Če polja ne označite, bo namesto tega ustvarjen naslov, združljiv s starejšimi denarnicami.</translation>
</message>
<message>
<source>Generate native segwit (Bech32) address</source>
- <translation>Ustvari domači segwit (Bech32) naslov</translation>
+ <translation>Ustvari lastni segwit (Bech32) naslov</translation>
</message>
<message>
<source>Requested payments history</source>
@@ -2077,7 +2057,7 @@
</message>
<message>
<source>Copy URI</source>
- <translation>Kopireaj URI</translation>
+ <translation>Kopiraj URI</translation>
</message>
<message>
<source>Copy label</source>
@@ -2171,7 +2151,7 @@
</message>
<message>
<source>Requested</source>
- <translation>Zahtevana plačila</translation>
+ <translation>Zahtevan znesek</translation>
</message>
</context>
<context>
@@ -2198,11 +2178,11 @@
</message>
<message>
<source>Quantity:</source>
- <translation>Št.vhodov:</translation>
+ <translation>Št. vhodov:</translation>
</message>
<message>
<source>Bytes:</source>
- <translation>Št.bajtov:</translation>
+ <translation>Št. bajtov:</translation>
</message>
<message>
<source>Amount:</source>
@@ -2222,7 +2202,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>Če to vključite, nato pa vnesete neveljaven naslov, ali pa pustite polje prazno, bo vrnjen drobiž poslan na novo ustvarjen naslov.</translation>
+ <translation>Če to vključite, nato pa vnesete neveljaven naslov za vračilo ali pa pustite polje prazno, bo vračilo poslano na novoustvarjen naslov.</translation>
</message>
<message>
<source>Custom change address</source>
@@ -2238,26 +2218,23 @@
</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>Uporaba nadomestnega nadomestila lahko pošlje transakcijo, ki bo trajala več ur ali dni (ali nikoli) za potrditev. Razmislite o ročni izbiri ali počakajte, da potrdite celotno verigo.</translation>
+ <translation>Uporaba nadomestne provizije lahko povzroči, da bo transakcija potrjena šele po več urah ali dneh (ali morda sploh nikoli). Razmislite o ročni nastavitvi provizije ali počakajte, da se preveri celotna veriga.</translation>
</message>
<message>
<source>Warning: Fee estimation is currently not possible.</source>
<translation>Opozorilo: ocena provizije trenutno ni mogoča.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>Skrije nastavitve provizije</translation>
- </message>
- <message>
<source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
Note: Since the fee is calculated on a per-byte basis, a fee 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>Določite poljubno provizijo na kB (1000 bajtov) navidezne velikosti transakcije.
-Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB" za transakcijo velikosti 500 bajtov (polovica enega kB) znašala 50 satoshijev.</translation>
+
+Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB" za transakcijo velikosti 500 bajtov (polovica enega kB) znašala 50 satošijev.</translation>
</message>
<message>
<source>per kilobyte</source>
- <translation>na KiB</translation>
+ <translation>na kilobajt</translation>
</message>
<message>
<source>Hide</source>
@@ -2273,7 +2250,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(Samodejni obračun provizije še ni pripravljen. Po navadi izračun traja nekaj blokov ...)</translation>
+ <translation>(Samodejni obračun provizije še ni pripravljen. Izračun običajno traja nekaj blokov ...)</translation>
</message>
<message>
<source>Send to multiple recipients at once</source>
@@ -2292,8 +2269,12 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Prah:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Skrij nastavitve 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>Kadar je v blokih manj volumna transakcij kot prostora v blokih, lahko rudarji in preusmeritvena vozlišča (relay nodes) uveljavijo minimalno provizijo. Plačilo le te minimalne provizije je čisto v redu, vendar se zavedajte, da lahko to povzroči nikoli potrjeno transakcijo, ko bo po bitcoin transakcijah večje povpraševanje, kot ga lahko obdela omrežje.</translation>
+ <translation>Kadar je v blokih manj prostora, kot je zahtev po transakcijah, lahko rudarji in posredovalna vozlišča zahtevajo minimalno provizijo. Plačilo le te minimalne provizije je čisto v redu, vendar se zavedajte, da lahko to povzroči, da se transakcija nikoli ne potrdi, če bo povpraševanje po bitcoin transakcijah večje, kot ga omrežje lahko obdela.</translation>
</message>
<message>
<source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
@@ -2309,11 +2290,11 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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>Z zamenjavo plačila (BIP-125) lahko po pošiljanju povečate pristojbino za transakcijo. Brez tega se lahko priporoči višja pristojbina za nadomestilo povečanega tveganja zamude pri transakciji.</translation>
+ <translation>"Replace-By-Fee" (BIP-125, "Povozi s provizijo") omogoča, da povečate provizijo za transakcijo po tem, ko je bila transakcija že poslana. Brez tega se lahko priporoči višja provizija za nadomestilo povečanega tveganja zamude pri transakciji.</translation>
</message>
<message>
<source>Clear &amp;All</source>
- <translation>Počisti &amp;vse </translation>
+ <translation>Počisti &amp;vse</translation>
</message>
<message>
<source>Balance:</source>
@@ -2360,6 +2341,14 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>%1 (%2 blokov)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Ustvari n&amp;epodpisano</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>Ustvari delno podpisano bitcoin-transakcijo (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>
+ </message>
+ <message>
<source> from wallet '%1'</source>
<translation>iz denarnice '%1'</translation>
</message>
@@ -2372,10 +2361,18 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>%1 do %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Želite shraniti to transakcijo kot osnutek?</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<translation>Ali ste prepričani, da želite poslati?</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>
+ </message>
+ <message>
<source>or</source>
<translation>ali</translation>
</message>
@@ -2400,8 +2397,32 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Skupni znesek</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Za pregled sezama prejemnikov, kliknite na "Pokaži podrobnosti"</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
- <translation>Potrdi pošiljanje kovancev</translation>
+ <translation>Potrdi pošiljanje</translation>
+ </message>
+ <message>
+ <source>Confirm transaction proposal</source>
+ <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>
<message>
<source>The recipient address is not valid. Please recheck.</source>
@@ -2417,7 +2438,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>Celotni znesek z vključeno provizijo %1 je večji od stanja sredstev, s katerimi razpolagate.</translation>
+ <translation>Celotni znesek z vključeno provizijo %1 je višji od vašega dobroimetja.</translation>
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
@@ -2428,10 +2449,6 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Transakcije ni bilo mogoče ustvariti!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Transakcija je bila zavrnjena: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Provizija, ki je večja od %1, velja za nesmiselno veliko.</translation>
</message>
@@ -2441,11 +2458,11 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
- <translation><numerusform>Predviden začetek potrditev po %n najdenemu bloku.</numerusform><numerusform>Predviden začetek potrditev po %n najdenih blokih.</numerusform><numerusform>Predviden začetek potrditev po %n najdenih blokih.</numerusform><numerusform>Predviden začetek potrditev po %n najdenih blokih.</numerusform></translation>
+ <translation><numerusform>Predviden začetek potrditev po %n najdenemu bloku.</numerusform><numerusform>Predviden začetek potrditev po %n najdenih blokih.</numerusform><numerusform>Predviden začetek potrditev po %n najdenih blokih.</numerusform><numerusform>Prva predvidena potrditev v naslednjih %n blokih.</numerusform></translation>
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
- <translation>Opozorilo: Neveljaven Bitcoin naslov</translation>
+ <translation>Opozorilo: Neveljaven bitcoin-naslov</translation>
</message>
<message>
<source>Warning: Unknown change address</source>
@@ -2457,7 +2474,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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>Naslov, ki ste ga izbrali za spremembo, ni del te denarnice. Na ta naslov se lahko pošlje katero koli ali vsa sredstva v vaši denarnici. Ali ste prepričani?</translation>
+ <translation>Naslov, ki ste ga izbrali za vračilo, ne pripada tej denarnici. Na ta naslov bodo lahko poslana katerakoli ali vsa sredstva v vaši denarnici. Ali ste prepričani?</translation>
</message>
<message>
<source>(no label)</source>
@@ -2472,7 +2489,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Pay &amp;To:</source>
- <translation>Prejemnik &amp;plačila:</translation>
+ <translation>&amp;Prejemnik plačila:</translation>
</message>
<message>
<source>&amp;Label:</source>
@@ -2483,12 +2500,8 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Izberite enega od že uporabljenih naslovov</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Plačilo je navadne vrste.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
- <translation>Naslov Bitcoin, na katerega bo plačilo poslano</translation>
+ <translation>Bitcoin-naslov, na katerega bo plačilo poslano</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2507,6 +2520,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Izpraznite vsebino polja</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>Znesek za pošiljanje v izbrani enoti</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>
@@ -2516,7 +2533,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Use available balance</source>
- <translation>Uporabi dobroimetje na voljo</translation>
+ <translation>Uporabi celotno dobroimetje</translation>
</message>
<message>
<source>Message:</source>
@@ -2536,7 +2553,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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>Sporočilo, ki ste ga pripeli na URI tipa bitcoin:. Shranjeno bo skupaj s podatki o transakciji. Opomba: Sporočilo ne bo poslano preko omrežja Bitcoin.</translation>
+ <translation>Sporočilo, ki je bilo pripeto na URI tipa bitcoin: in bo shranjeno skupaj s podatki o transakciji. Opomba: Sporočilo ne bo poslano preko omrežja Bitcoin.</translation>
</message>
<message>
<source>Pay To:</source>
@@ -2546,17 +2563,6 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<source>Memo:</source>
<translation>Opomba:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Vnesite oznako, pod katero bo zgornji naslov shranjen v imenik</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Da</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2581,11 +2587,11 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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>S svojimi naslovi lahko podpisujete sporočila ali pogodbe in s tem dokazujete, da na teh naslovih lahko prejemate kovance. Bodite previdni in ne podpisujte ničesar nejasnega ali naključnega, ker vas zlikovci preko ribarjenja (phishing) lahko prelisičijo, da na njih prepišete svojo identiteto. Podpisujte samo podrobno opisane izjave, s katerimi se strinjate.</translation>
+ <translation>S svojimi naslovi lahko podpisujete sporočila ali dogovore in s tem dokazujete, da na teh naslovih lahko prejemate kovance. Bodite previdni in ne podpisujte ničesar nejasnega ali naključnega, ker vas zlikovci preko ribarjenja (phishing) lahko prelisičijo, da na njih prepišete svojo identiteto. Podpisujte samo podrobno opisane izjave, s katerimi se strinjate.</translation>
</message>
<message>
<source>The Bitcoin address to sign the message with</source>
- <translation>Naslov Bitcoin, s katerim podpisujete sporočilo</translation>
+ <translation>Bitcoin-naslov, s katerim podpisujete sporočilo</translation>
</message>
<message>
<source>Choose previously used address</source>
@@ -2613,11 +2619,11 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Copy the current signature to the system clipboard</source>
- <translation>Kopiranje trenutnega podpisa na sistemsko odložišče.</translation>
+ <translation>Kopiranje trenutnega podpisa v sistemsko odložišče.</translation>
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Podpišite sporočilo, da dokažete lastništvo nad zgornjim naslovom.</translation>
+ <translation>Podpišite sporočilo, da dokažete lastništvo zgornjega naslova.</translation>
</message>
<message>
<source>Sign &amp;Message</source>
@@ -2629,7 +2635,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Clear &amp;All</source>
- <translation>Počisti &amp;vse </translation>
+ <translation>Počisti &amp;vse</translation>
</message>
<message>
<source>&amp;Verify Message</source>
@@ -2637,15 +2643,23 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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>Da preverite verodostojnost sporočila, spodaj vnesite: prejemnikov naslov, prejeto sporočilo (pazljivo skopirajte vse prelome vrstic, presledke, tabulatorje ipd.,) in prejeti podpis. Da se izognete napadom tipa man-in-the-middle, vedite, da iz veljavnega podpisa ne sledi nič drugega, kot tisto, kar je navedeno v sporočilu. Podpis samo potrjuje dejstvo, da ima podpisnik v lasti prejemni naslov, ne more pa dokazati vira nobene transakcije!</translation>
+ <translation>Da preverite verodostojnost sporočila, spodaj vnesite: prejemnikov naslov, prejeto sporočilo (pazljivo skopirajte vse prelome vrstic, presledke, tabulatorje itd.) in prejeti podpis. Da se izognete napadom tipa man-in-the-middle, vedite, da iz veljavnega podpisa ne sledi nič drugega, kot tisto, kar je navedeno v sporočilu. Podpis samo potrjuje dejstvo, da ima podpisnik v lasti prejemni naslov, ne more pa dokazati vira nobene transakcije!</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
- <translation>Naslov Bitcoin, s katerim je bilo sporočilo podpisano</translation>
+ <translation>Bitcoin-naslov, s katerim je bilo sporočilo podpisano</translation>
+ </message>
+ <message>
+ <source>The signed message to verify</source>
+ <translation>Podpisano sporočilo za preverbo</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>Podpis, ustvarjen ob podpisovanju sporočila</translation>
</message>
<message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Preverite, ali je bilo sporočilo v resnici podpisano z navedenim naslovom Bitcoin.</translation>
+ <translation>Preverite, ali je bilo sporočilo v resnici podpisano z navedenim bitcoin-naslovom.</translation>
</message>
<message>
<source>Verify &amp;Message</source>
@@ -2676,6 +2690,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Odklepanje denarnice je bilo preklicano.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Ni napak</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>Zasebni ključ vnešenega naslova ni na voljo.</translation>
</message>
@@ -2712,7 +2730,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<name>TrafficGraphWidget</name>
<message>
<source>KB/s</source>
- <translation>KiB/s</translation>
+ <translation>KB/s</translation>
</message>
</context>
<context>
@@ -2735,11 +2753,11 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>in memory pool</source>
- <translation>v memory pool-u</translation>
+ <translation>v čakalni vrsti</translation>
</message>
<message>
<source>not in memory pool</source>
- <translation>ni v memory pool-u</translation>
+ <translation>ni v čakalni vrsti</translation>
</message>
<message>
<source>abandoned</source>
@@ -2850,6 +2868,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Indeks izhoda</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(Certifikat ni bil overjen)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Trgovec</translation>
</message>
@@ -2945,7 +2967,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Received with</source>
- <translation>Prejeto s</translation>
+ <translation>Prejeto z</translation>
</message>
<message>
<source>Received from</source>
@@ -2953,7 +2975,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Sent to</source>
- <translation>Poslano</translation>
+ <translation>Poslano na</translation>
</message>
<message>
<source>Payment to yourself</source>
@@ -2977,7 +2999,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>Stanje transakcije. Zapeljite z miško čez to polje za prikaz števila potrdil. </translation>
+ <translation>Stanje transakcije. Zapeljite z miško čez to polje za prikaz števila potrdil.</translation>
</message>
<message>
<source>Date and time that the transaction was received.</source>
@@ -2997,7 +3019,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Amount removed from or added to balance.</source>
- <translation>Znesek spremembe stanja sredstev.</translation>
+ <translation>Višina spremembe dobroimetja.</translation>
</message>
</context>
<context>
@@ -3036,7 +3058,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Sent to</source>
- <translation>Poslano</translation>
+ <translation>Poslano na </translation>
</message>
<message>
<source>To yourself</source>
@@ -3174,7 +3196,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
- <translation>Ali ste prepričani da želite zapreti denarnico &lt;i&gt;%1&lt;/i&gt;?</translation>
+ <translation>Ste prepričani, da želite zapreti denarnico &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>
@@ -3196,7 +3218,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Fee bump error</source>
- <translation>Fee bump error</translation>
+ <translation>Napaka pri poviševanju provizije</translation>
</message>
<message>
<source>Increasing transaction fee failed</source>
@@ -3204,7 +3226,11 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Do you want to increase the fee?</source>
- <translation>Ali hočete povišati provizijo?</translation>
+ <translation>Ali želite povišati provizijo?</translation>
+ </message>
+ <message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Želite shraniti osnutek transakcije s povečano provizijo?</translation>
</message>
<message>
<source>Current fee:</source>
@@ -3223,6 +3249,14 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Confirm fee bump</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>Ne morem shraniti osnutka transakcije</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>DPBT skopirana</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Ne morem podpisati transakcije.</translation>
</message>
@@ -3286,11 +3320,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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>Obrezovanje: zadnja sinhronizacija denarnice presega obrezane podatke. Izvesti morate -reindex (v primeru obrezave morate znova naložiti celoten blockchain)</translation>
- </message>
- <message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>RPonovno skeniranje (rescans) v obrezovalnem načinu niso možni. Uporabiti boste morali -reindex, ki bo znova naložil celoten blockchain.</translation>
+ <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>
@@ -3310,7 +3340,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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 change-address. V keypool-u ni ključev.</translation>
+ <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>
@@ -3334,7 +3364,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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 bo iz prihodnosti. To je lahko posledica napačnega nastavitve datuma in časa vašega računalnika. Znova obnovijte bazo podatkov samo, če ste prepričani, da sta datum in čas računalnika pravilna</translation>
+ <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>
<message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
@@ -3342,11 +3372,11 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>To je transakcijska provizija, ki jo lahko zavržete, če je sprememba manjša od prahu na tej ravni</translation>
+ <translation>To je transakcijska provizija, ki jo lahko zavržete, če je znesek vračila manjši od prahu na tej ravni</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>
+ <translation>Ne morem ponovno obdelati blokov. Podatkovno bazo bo potrebno ponovno zgraditi z uporabo ukaza -reindex-chainstate.</translation>
</message>
<message>
<source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
@@ -3354,7 +3384,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>Opozorilo: Trenutno na omrežju ni videti konsenza! Videti je, kot da bi imeli nekateri rudarji težave.</translation>
+ <translation>Opozorilo: Trenutno na omrežju ni videti konsenza! Videti je, da imajo nekateri rudarji težave.</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>
@@ -3378,7 +3408,11 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Change index out of range</source>
- <translation>Indeks drobiža izven dovoljenega območja</translation>
+ <translation>Indeks vračila izven dovoljenega območja</translation>
+ </message>
+ <message>
+ <source>Config setting for %s only applied on %s network when in [%s] section.</source>
+ <translation>Konfiguracijske nastavitve za %s se upoštevajo le na omrežju %s v sekciji [%s].</translation>
</message>
<message>
<source>Copyright (C) %i-%i</source>
@@ -3389,6 +3423,14 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Podatkovna baza blokov je okvarjena</translation>
</message>
<message>
+ <source>Could not find asmap file %s</source>
+ <translation>Ne najdem asmap-datoteke %s</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>Razčlenjevanje asmap-datoteke %s je spodletelo</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Želite zdaj obnoviti podatkovno bazo blokov?</translation>
</message>
@@ -3445,6 +3487,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Začetni sanity check neuspešen. %s se zapira.</translation>
</message>
<message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Neveljavna pooblastila P2P: '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
<translation>Neveljavna količina za -%s=&lt;amount&gt;: '%s'</translation>
</message>
@@ -3466,11 +3512,11 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Unknown change type '%s'</source>
- <translation>Neznan tip drobiža '%s'</translation>
+ <translation>Neznan tip vračila '%s'</translation>
</message>
<message>
<source>Upgrading txindex database</source>
- <translation>Nadgrajujem txindex podatkovno bazo</translation>
+ <translation>Nadgrajujem podatkovno bazo txindex</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3510,7 +3556,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Transaction fee and change calculation failed</source>
- <translation>Izračun provizije za transakcijo in droviža ni uspel</translation>
+ <translation>Izračun provizije za transakcijo in vračila ni uspel</translation>
</message>
<message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
@@ -3554,7 +3600,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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 nepredviden način morate obnoviti bazo z uporabo -reindex. To bo ponovno naložilo celoten blockchain</translation>
+ <translation>Za vrnitev v neobrezan način morate obnoviti bazo z uporabo -reindex. To zahteva ponoven prenos celotne verige blokov.</translation>
</message>
<message>
<source>Error reading from database, shutting down.</source>
@@ -3562,7 +3608,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Error upgrading chainstate database</source>
- <translation>Napaka pri nadgradnji chainstate baze podatkov</translation>
+ <translation>Napaka pri posodobitvi baze podatkov stanja verige.</translation>
</message>
<message>
<source>Error: Disk space is low for %s</source>
@@ -3651,12 +3697,16 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Ne zmorem ustvariti začetnih ključev</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>Neznana vrednost -blockfilterindex %s.</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>Preverjam denarnice ...</translation>
</message>
<message>
<source>Warning: unknown new rules activated (versionbit %i)</source>
- <translation>Opozorilo: neznana nova pravila aktivirana (verzija %i)</translation>
+ <translation>Opozorilo: neznana nova pravila aktivirana (versionbit %i)</translation>
</message>
<message>
<source>Zapping all transactions from wallet...</source>
@@ -3676,7 +3726,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</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 stanje ali transakcije napačno, ga morate obnoviti iz varnostne kopije.</translation>
+ <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>
@@ -3684,7 +3734,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
- <translation>Napaka pri nalaganju denarnice %s. Ime denarnice je bilo že uporabljeno.</translation>
+ <translation>Napaka pri nalaganju denarnice %s. Ime denarnice (parameter -wallet) je podvojeno.</translation>
</message>
<message>
<source>Starting network threads...</source>
@@ -3708,7 +3758,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Transaction has too long of a mempool chain</source>
- <translation>Transakcija ima predolgo verigo spominov</translation>
+ <translation>Transakcija je del predolge verige nepotrjenih transakcij</translation>
</message>
<message>
<source>Transaction must have at least one recipient</source>
@@ -3732,7 +3782,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <translation>Opozorilo: zasebni ključi odkriti v denarnici %s z onemogočenimi zasebnimi ključi.</translation>
+ <translation>Opozorilo: zasebni ključi odkriti v denarnici {%s} z onemogočenimi zasebnimi ključi.</translation>
</message>
<message>
<source>Cannot write to data directory '%s'; check permissions.</source>
@@ -3748,7 +3798,7 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
</message>
<message>
<source>Cannot downgrade wallet</source>
- <translation>Ne morem </translation>
+ <translation>Ne morem</translation>
</message>
<message>
<source>Rescanning...</source>
diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts
deleted file mode 100644
index 08b00984c0..0000000000
--- a/src/qt/locale/bitcoin_sl_SI.ts
+++ /dev/null
@@ -1,1913 +0,0 @@
-<TS language="sl_SI" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Desni klik za urejanje naslovov ali oznak</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Ustvari nov naslov</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Novo</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Kopiraj trenutno izbrani naslov v odložišče</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Kopiraj</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>&amp;Zapri</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Izbriši trenutno označeni naslov iz seznama</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation>Iščite po naslovu ali oznaki</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Izvozi podatke v trenutnem zavihku v datoteko</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Izvozi</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>I&amp;zbriši</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Izberi naslov prejemnika kovancev</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Izberi naslov, na katerega želiš prejeti kovance</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>&amp;Izberi</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Imenik naslovov za pošiljanje</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Imenik naslovov za prejemanje</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>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. It is recommended to use a new receiving address for each transaction.</source>
- <translation>To so vaši Bitcoin naslovi za prejemanje. Priporočeno je, da za vsako transakcijo uporabite nov naslov.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Kopiraj naslov</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Kopiraj &amp;oznako</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Uredi</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Izvozi seznam naslovov</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Podatki ločenimi z vejico (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Podatkov ni bilo mogoče izvoziti.</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Oznaka</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Naslov</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(brez oznake)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Vnos gesla</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Vnesite geslo</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Novo geslo</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Ponovite novo geslo</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Pokaži geslo</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Vnesite novo geslo za dostop do denarnice. Prosimo, da uporabite geslo sestavljeno iz &lt;b&gt;desetih ali več&lt;/b&gt; naključnih znakov ali &lt;b&gt;osmih ali večih&lt;/b&gt; besed.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Šifriraj denarnico</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>To dejanje zahteva geslo za odklepanje vaše denarnice.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Odkleni denarnico</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>To dejanje zahteva geslo za dešifriranje vaše denarnice.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Odšifriraj denarnico</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Spremeni geslo</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Vnesite staro in novo geslo denarnice.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Potrdi šifriranje denarnice</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Opozorilo: V primeru izgube gesla šifrirane denarnice, boste &lt;b&gt;IZGUBILI VSE SVOJE BITCOINE&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Ali ste prepričani, da želite šifrirati svojo denarnico?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Denarnica šifrirana</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 se bo zaprl, da bi dokončal postopek šifriranja. Zapomnite si, da šifriranje vaše denarnice vaših ne more popolnoma zaščititi vaših bitcoinov pred krajami zlonamernih programov, ki bi lahko bili nameščeni na vašem računalniku.</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>POMEMBNO: Vse starejše varnostne kopije denarnice je potrebno zamenjati z novoizdelano, šifrirano, varnostno kopijo. Zaradi varnosti bodo stare varnostne kopije postale neuporabne takoj, ko začnete uporabljati novo, šifrirano denarnico.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Šifriranje denarnice ni uspelo</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Šifriranje denarnice ni uspelo zaradi notranje napake. Vaša denarnica ni bila šifrirana.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Navedeni gesli se ne ujemata.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Denarnice ni bilo mogoče odkleniti.</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Geslo za dešifriranje denarnice, ki ste ga vnesli, ni pravilno.</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Dešifriranje denarnice ni uspelo</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Geslo za dostop do denarnice je bilo uspešno spremenjeno.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Opozorilo: Vključena je tipka Caps Lock!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmaska</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Prepoved do</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Podpiši &amp;sporočilo ...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Dohitevam omrežje ...</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>Pre&amp;gled</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Vozlišče</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Oglejte si splošne informacije o vaši denarnici</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Transakcije</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Brskajte po zgodovini transakcij</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>I&amp;zhod</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Ustavite program</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;O nas%1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Prikaži informacije o %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>O &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Oglejte si informacije o Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Možnosti ...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Spremeni možnosti konfiguracije za %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Šifriraj denarnico ...</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>Shrani &amp;varnostno kopijo denarnice ...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Spremeni geslo ...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>Naslovi za po&amp;šiljanje ...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Naslovi za &amp;prejemanje...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Odpri &amp;URI ...</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation>Denarnica:</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>privzeta denarnica</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Kliknite, da onemogočite omrežno aktivnosti.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Omrežna aktivnost onemogočena.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Kliknite, da ponovno vključite omrežno aktivnost.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Sinhronizacija glav (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Poustvarjam kazalo blokov na disku ...</translation>
- </message>
- <message>
- <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>Namestniški strežnik je omogočen&lt;/b&gt;: %1</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Izvedite plačilo na naslov Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Shranite varnostno kopijo svoje denarnice na drugo lokacijo</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Spremenite geslo za šifriranje denarnice</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Razhroščevalno okno</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Odprite razhroščevalno in diagnostično konzolo</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Preveri sporočilo ...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Denarnica</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Pošlji</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>P&amp;rejmi</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Prikaži / Skrij</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Prikaži ali skrij glavno okno</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Šifrirajte zasebne ključe, ki se nahajajo v denarnici</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Podpišite poljubno sporočilo z enim svojih naslovov Bitcoin, da prejemniku sporočila dokažete, da je ta naslov v vaši lasti.</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Preverite, če je bilo prejeto sporočilo podpisano z določenim naslovom Bitcoin</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Datoteka</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Nastavitve</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Pomoč</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Orodna vrstica zavihkov</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Zahtevajte plačilo (ustvarite zahtevek s kodo QR in URI tipa bitcoin:)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Preglejte in uredite seznam naslovov, na katere ste kdaj poslali plačila</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Preglejte in uredite seznam naslovov, na katere ste kdaj prejeli plačila</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Izvedite plačilo iz zahtevka v datoteki ali iz URI tipa bitcoin:</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>Opcije &amp;ukazne vrstice</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n aktivna povezava v omrežje Bitcoin</numerusform><numerusform>%n aktivni povezavi v omrežje Bitcoin</numerusform><numerusform>%n aktivne povezave v omrežje Bitcoin</numerusform><numerusform>%n aktivnih povezav v omrežje Bitcoin</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Indeksirani bloki na disku ...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Obdelava blokov na disku ...</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>%n obdelan blok zgodovine transakcij.</numerusform><numerusform>%n obdelana bloka zgodovine transakcij.</numerusform><numerusform>%n obdelani bloki zgodovine transakcij.</numerusform><numerusform>%n obdelanih blokov zgodovine transakcij.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>imam še %1 zaostanka</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Zadnji prejeti blok je star %1.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Novejše transakcije še ne bodo vidne.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Napaka</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Opozorilo</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informacije</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Posodobljeno</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>%1 odjemalec</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Dohitevam omrežje ...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Datum: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Znesek: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Vrsta: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Oznaka: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Naslov: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Odlivi</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Prilivi</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>Denarnica je &lt;b&gt;šifrirana&lt;/b&gt; in trenutno &lt;b&gt;odklenjena&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>Denarnica je &lt;b&gt;šifrirana&lt;/b&gt; in trenutno &lt;b&gt;zaklenjena&lt;/b&gt;</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation>Izbira vhodnih kovancev</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Št.vhodov:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Št.bajtov:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Znesek:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Provizija:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Prah:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Po proviziji:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Vračilo:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>izberi vse/nič</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Drevesni prikaz</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Seznam</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Znesek</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Oznaka priliva</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Naslov priliva</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Datum</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Potrditve</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Potrjeno</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(brez oznake)</translation>
- </message>
- </context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Uredi naslov</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Oznaka</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>Oznaka, pod katero je spodnji naslov naveden v vašem imeniku naslovov.</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>Naslov tega vnosa v imeniku. Spremeniti ga je mogoče le pri vnosih iz imenika naslovov za pošiljanje.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Naslov</translation>
- </message>
- </context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Ustvarjena bo nova podatkovna mapa.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>ime</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>Mapa že obstaja. Dodajte %1, če tu želite ustvariti novo mapo.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Pot že obstaja, vendar ni mapa.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Na tem mestu ni mogoče ustvariti nove mape.</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>različica</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>O %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Možnosti ukazne vrstice</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Dobrodošli</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Dobrodošli v %1</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Uporabi privzeto podatkovno mapo</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Uporabi to podatkovno mapo:</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Napaka: Ni mogoče ustvariti mape "%1".</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Napaka</translation>
- </message>
- <message numerus="yes">
- <source>%n GB of free space available</source>
- <translation><numerusform>%n GiB prostega prostora na voljo</numerusform><numerusform>%n GiB prostega prostora na voljo</numerusform><numerusform>%n GiB prostega prostora na voljo</numerusform><numerusform>%n GiB prostega prostora na voljo</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>(of %n GB needed)</source>
- <translation><numerusform>(od potrebnih %n GiB)</numerusform><numerusform>(od potrebnih %n GiB)</numerusform><numerusform>(od potrebnih %n GiB)</numerusform><numerusform>(od potrebnih %n GiB)</numerusform></translation>
- </message>
-</context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Oblika</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Čas zadnjega bloka</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Skrij</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Odpri URl</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Vnesite zahtevek za plačilo iz URI ali pa ga naložite iz datoteke</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Izbiranje datoteke z zahtevkom za plačilo</translation>
- </message>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Možnosti</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Glavno</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Velikost &amp;predpomnilnika podatkovne baze</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MiB</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>Število programskih &amp;niti za preverjanje</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Naslov IP posredniškega strežnika (npr. IPv4: 127.0.0.1 ali IPv6: ::1)</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>Ko zaprete glavno okno programa, bo program tekel še naprej, okno pa bo zgolj minimirano. Program v tem primeru ustavite tako, da v meniju izberete ukaz Izhod.</translation>
- </message>
- <message>
- <source>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>Naslovi URL tretjih oseb (npr. raziskovalec blokov), ki bodo navedeni v kontekstnem meniju seznama transakcij. Niz %s iz naslova URL je nadomeščen s hash vrednostjo transakcije. Več zaporednih naslovov URL je med seboj ločenih z znakom |.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Aktivne opcije iz ukazne vrstice, ki preglasijo zgornje opcije:</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Ponastavi vse nastavitve programa na privzete vrednosti.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Ponastavi nastavitve</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Omrežje</translation>
- </message>
- <message>
- <source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = samodejno, &lt;0 = toliko procesorskih jeder naj ostane prostih)</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>&amp;Denarnica</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Napredne možnosti</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Omogoči upravljanje s kovanci</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>Če onemogočite trošenje drobiža iz še nepotrjenih transakcij, potem vrnjenega drobiža ne morete uporabiti, dokler plačilo ni vsaj enkrat potrjeno. Ta opcija vpliva tudi na izračun stanja sredstev.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>Omogoči &amp;trošenje drobiža iz še nepotrjenih plačil</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>Program samodejno odpre ustrezna vrata na usmerjevalniku. To deluje samo, če vaš usmerjevalnik podpira in ima omogočen UPnP.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Preslikaj vrata z uporabo &amp;UPnP</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Poveži se v omrežje Bitcoin preko posredniškega strežnika SOCKS5.</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Poveži se preko posredniškega strežnika SOCKS5 (privzeti strežnik):</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>Naslov &amp;IP posredniškega strežnika:</translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>&amp;Vrata:</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Vrata posredniškega strežnika (npr. 9050)</translation>
- </message>
- <message>
- <source>&amp;Window</source>
- <translation>O&amp;kno</translation>
- </message>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Po minimiranju okna samo prikaži ikono programa v pladnju.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimiraj na pladenj namesto na opravilno vrstico</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>Ob zapiranju okno zgolj m&amp;inimiraj</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Prikaz</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>&amp;Jezik uporabniškega vmesnika:</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Enota za prikaz zneskov:</translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Izberite privzeto mersko enoto za prikaz v uporabniškem vmesniku in pri pošiljanju kovancev.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Omogoči dodatno možnost podrobnega nadzora nad posameznimi kovanci v transakcijah.</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;Potrdi</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Prekliči</translation>
- </message>
- <message>
- <source>default</source>
- <translation>privzeto</translation>
- </message>
- <message>
- <source>none</source>
- <translation>nič</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Potrditev ponastavitve</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Za uveljavitev sprememb je potreben ponoven zagon programa.</translation>
- </message>
- <message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation>Program bo zaustavljen. Želite nadaljevati z izhodom?</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Napaka</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Ta sprememba zahteva ponoven zagon programa.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Vnešeni naslov posredniškega strežnika ni veljaven.</translation>
- </message>
-</context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Oblika</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>Prikazani podatki so morda zastareli. Program ob vzpostavitvi povezave samodejno sinhronizira denarnico z omrežjem Bitcoin, a trenutno ta proces še ni zaključen.</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Opazovano:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Na voljo:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Skupni znesek vaših sredstev, s katerimi lahko prosto razpolagate</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Nepotrjeno:</translation>
- </message>
- <message>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Skupni znesek sredstev s katerimi še ne razpolagate prosto, ker so del še nepotrjenih transakcij.</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Nedozorelo:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>Nedozorel narudarjeni znesek</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Stanje sredstev</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Skupaj:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Trenutna vsota vseh vaših sredstev</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>Trenutno stanje vaših sredstev na opazovanih naslovih</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Na voljo:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Nedavne transakcije</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Nepotrjene transakcije na opazovanih naslovih</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Nedozoreli narudarjeni znesek na opazovanih naslovih</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>Trenutno skupno stanje sredstev na opazovanih naslovih</translation>
- </message>
-</context>
-<context>
- <name>PaymentServer</name>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>Ime agenta</translation>
- </message>
- <message>
- <source>Node/Service</source>
- <translation>Naslov</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Oddano</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Prejeto</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Znesek</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Vnesite naslov Bitcoin (npr. %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>Nič</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>Neznano</translation>
- </message>
- <message>
- <source>%1 ms</source>
- <translation>%1 ms</translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 in %2</translation>
- </message>
- <message>
- <source>%1 B</source>
- <translation>%1 B</translation>
- </message>
- <message>
- <source>%1 KB</source>
- <translation>%1 KiB</translation>
- </message>
- <message>
- <source>%1 MB</source>
- <translation>%1 MiB</translation>
- </message>
- <message>
- <source>%1 GB</source>
- <translation>%1 GiB</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>neznano</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>Neznano</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Različica odjemalca</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Informacije</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Razhroščevalno okno</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Splošno</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>BerkeleyDB različica v rabi</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Čas zagona</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Omrežje</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Ime</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Število povezav</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Veriga blokov</translation>
- </message>
- <message>
- <source>Current number of blocks</source>
- <translation>Trenutno število blokov</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Prejeto</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Oddano</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Soležniki</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <translation>Izberite soležnika, o katerem si želite ogledati podrobnejše informacije.</translation>
- </message>
- <message>
- <source>Direction</source>
- <translation>Smer povezave</translation>
- </message>
- <message>
- <source>Version</source>
- <translation>Različica</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>Ime agenta</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Storitve</translation>
- </message>
- <message>
- <source>Ban Score</source>
- <translation>Kazenske točke</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Trajanje povezave</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Nazadje oddano</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Nazadnje prejeto</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Odzivni čas</translation>
- </message>
- <message>
- <source>Time Offset</source>
- <translation>Časovni odklon</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Čas zadnjega bloka</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Odpri</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Konzola</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Omrežni promet</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Promet</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Dohodnih:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Odhodnih:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Razhroščevalni dnevnik</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Počisti konzolo</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation>privzeta denarnica</translation>
- </message>
- <message>
- <source>via %1</source>
- <translation>preko %1</translation>
- </message>
- <message>
- <source>never</source>
- <translation>nikoli</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Dohodna</translation>
- </message>
- <message>
- <source>Outbound</source>
- <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>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>&amp;Znesek:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Oznaka:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Sporočilo:</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>Neobvezno sporočilo kot priponka zahtevku za plačilo, ki bo prikazano, ko bo zahtevek odprt. Opomba: Opravljeno plačilo.prek omrežja Bitcoin tega sporočila ne bo vsebovalo.</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation>Oznaka novega sprejemnega naslova.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>S tem obrazcem ustvarite nov zahtevek za plačilo. Vsa polja so &lt;b&gt;neobvezna&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>Zahtevani znesek. Če ne zahtevate določenega zneska, pustite prazno ali nastavite vrednost na 0.</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Počisti vsa polja.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Počisti</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>Zgodovina zahtevkov za plačilo</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Zahtevaj plačilo</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Prikaz izbranega zahtevka. (Isto funkcijo opravi dvojni klik na zapis.)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Pokaži</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Odstrani označene vnose iz seznama</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Odstrani</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>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Kopiraj &amp;naslov</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Shrani sliko ...</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Naslov</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Oznaka</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Denarnica</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Label</source>
- <translation>Oznaka</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(brez oznake)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Pošlji</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Upravljanje s kovanci</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Vhodi ...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>samodejno izbrani</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Premalo sredstev!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Št.vhodov:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Št.bajtov:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Znesek:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Provizija:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Po proviziji:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Vračilo:</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>Če to vključite, nato pa vnesete neveljaven naslov, ali pa pustite polje prazno, bo vrnjen drobiž poslan na novo ustvarjen naslov.</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Naslov za vračilo drobiža po meri</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Provizija:</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Izberi ...</translation>
- </message>
- <message>
- <source>collapse fee-settings</source>
- <translation>Skrije nastavitve provizije</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>na KiB</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Skrij</translation>
- </message>
- <message>
- <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
- <translation>Dokler bo v blokih še dovolj prostora za vse nastajajoče transakcije, zadostuje, če plačate samo minimalno provizijo. Ko pa se bo količina vseh transakcij povečala do meja zmogljivosti omrežja, se lahko zgodi, da vaša transakcija brez večje provizije nikoli ne bo potrjena.</translation>
- </message>
- <message>
- <source>(read the tooltip)</source>
- <translation>(oglejte si namig)</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Priporočena:</translation>
- </message>
- <message>
- <source>Custom:</source>
- <translation>Po meri:</translation>
- </message>
- <message>
- <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(Samodejni obračun provizije še ni pripravljen. Po navadi izračun traja nekaj blokov ...)</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Pošlji več prejemnikom hkrati</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>Dodaj &amp;prejemnika</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Počisti vsa polja.</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Prah:</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Počisti &amp;vse </translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Stanje:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Potrdi pošiljanje</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>&amp;Pošlji</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Provizija transakcije</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(brez oznake)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>&amp;Znesek:</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>Prejemnik &amp;plačila:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Oznaka:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Izberite enega od že uporabljenih naslovov</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Plačilo je navadne vrste.</translation>
- </message>
- <message>
- <source>The Bitcoin address to send the payment to</source>
- <translation>Naslov Bitcoin, na katerega bo plačilo poslano</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Prilepite naslov iz odložišča</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Izpraznite vsebino polja</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>
- <message>
- <source>S&amp;ubtract fee from amount</source>
- <translation>O&amp;dštej provizijo od zneska</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Sporočilo:</translation>
- </message>
- <message>
- <source>This is an unauthenticated payment request.</source>
- <translation>Zahtevek za plačilo je neoverjen.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation>Zahtevek za plačilo je overjen.</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Če vnesete oznako za zgornji naslov, se bo skupaj z naslovom shranila v imenk že uporabljenih naslovov</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>Sporočilo, ki ste ga pripeli na URI tipa bitcoin:. Shranjeno bo skupaj s podatki o transakciji. Opomba: Sporočilo ne bo poslano preko omrežja Bitcoin.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Prejemnik:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Opomba:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>Dokler to okno ne izgine, ne zaustavljajte računalnika.</translation>
- </message>
-</context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Podpiši / preveri sporočilo</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Podpiši sporočilo</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>S svojimi naslovi lahko podpisujete sporočila ali pogodbe in s tem dokazujete, da na teh naslovih lahko prejemate kovance. Bodite previdni in ne podpisujte ničesar nejasnega ali naključnega, ker vas zlikovci preko ribarjenja (phishing) lahko prelisičijo, da na njih prepišete svojo identiteto. Podpisujte samo podrobno opisane izjave, s katerimi se strinjate.</translation>
- </message>
- <message>
- <source>The Bitcoin address to sign the message with</source>
- <translation>Naslov Bitcoin, s katerim podpisujete sporočilo</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Izberite enega od že uporabljenih naslovov</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Prilepite naslov iz odložišča</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Vnesite sporočilo, ki ga želite podpisati</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Podpis</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Kopiranje trenutnega podpisa na sistemsko odložišče.</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Podpišite sporočilo, da dokažete lastništvo nad zgornjim naslovom.</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Podpiši &amp;sporočilo</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Počisti vsa polja za vnos v oknu za podpisovanje</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Počisti &amp;vse </translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Preveri sporočilo</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>Da preverite verodostojnost sporočila, spodaj vnesite: prejemnikov naslov, prejeto sporočilo (pazljivo skopirajte vse prelome vrstic, presledke, tabulatorje ipd.,) in prejeti podpis. Da se izognete napadom tipa man-in-the-middle, vedite, da iz veljavnega podpisa ne sledi nič drugega, kot tisto, kar je navedeno v sporočilu. Podpis samo potrjuje dejstvo, da ima podpisnik v lasti prejemni naslov, ne more pa dokazati vira nobene transakcije!</translation>
- </message>
- <message>
- <source>The Bitcoin address the message was signed with</source>
- <translation>Naslov Bitcoin, s katerim je bilo sporočilo podpisano</translation>
- </message>
- <message>
- <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Preverite, ali je bilo sporočilo v resnici podpisano z navedenim naslovom Bitcoin.</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Preveri &amp;sporočilo</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Počisti vsa polja za vnos v oknu za preverjanje</translation>
- </message>
- </context>
-<context>
- <name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[testnet]</translation>
- </message>
-</context>
-<context>
- <name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>KiB/s</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>V tem podoknu so prikazane podrobnosti o transakciji</translation>
- </message>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Label</source>
- <translation>Oznaka</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(brez oznake)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Podatki ločenimi z vejico (*.csv)</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Oznaka</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Naslov</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Podatkov ni bilo mogoče izvoziti.</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- <message>
- <source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Merska enota za prikaz zneskov. Kliknite za izbiro druge enote.</translation>
- </message>
-</context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Izvozi podatke v trenutnem zavihku v datoteko</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>Corrupted block database detected</source>
- <translation>Podatkovna baza blokov je okvarjena</translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Želite zdaj obnoviti podatkovno bazo blokov?</translation>
- </message>
- <message>
- <source>Error initializing block database</source>
- <translation>Napaka pri inicializaciji podatkovne baze blokov</translation>
- </message>
- <message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Napaka pri inicializaciji okolja podatkovne baze denarnice %s!</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Napaka pri nalaganju podatkovne baze blokov</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Napaka pri odpiranju podatkovne baze blokov</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Opozorilo: Premalo prostora na disku!</translation>
- </message>
- <message>
- <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>Ni mogoče poslušati na nobenih vratih. Če to zares želite, uporabite opcijo -listen=0.</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>Uvažam ...</translation>
- </message>
- <message>
- <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>Izvornega bloka ni mogoče najti ali pa je neveljaven. Preverite, če ste izbrali pravo podatkovno mapo za izbrano omrežje.</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>Na voljo ni dovolj deskriptorjev datotek.</translation>
- </message>
- <message>
- <source>Prune cannot be configured with a negative value.</source>
- <translation>Negativne vrednosti parametra funkcije obrezovanja niso sprejemljive.</translation>
- </message>
- <message>
- <source>Prune mode is incompatible with -txindex.</source>
- <translation>Funkcija obrezovanja ni združljiva z opcijo -txindex.</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Preverjam celovitost blokov ...</translation>
- </message>
- <message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Napaka: Ni mogoče sprejemati dohodnih povezav (vrnjena napaka: %s)</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Informacije</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>Signing transaction failed</source>
- <translation>Transakcije ni bilo mogoče podpisati.</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>Program je eksperimentalne narave.</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Znesek je pramajhen</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Transkacija je prevelika</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation>Na tem računalniku ni bilo mogoče vezati naslova %s (vrnjena napaka: %s)</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Opozorilo</translation>
- </message>
- <message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Brišem vse transakcije iz denarnice ...</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>Transakcija mora imeti vsaj enega prejemnika.</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Neznano omrežje določeno v -onlynet: '%s'.</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Premalo sredstev</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Nalagam kazalo blokov ...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Nalagam denarnico ...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Ne morem </translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Ponovno pregledujem verigo ...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Nalaganje končano</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Napaka</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_sn.ts b/src/qt/locale/bitcoin_sn.ts
index 731fbb0da5..a4c24ce077 100644
--- a/src/qt/locale/bitcoin_sn.ts
+++ b/src/qt/locale/bitcoin_sn.ts
@@ -126,7 +126,7 @@
<name>CoinControlDialog</name>
<message>
<source>Amount</source>
- <translation>Marii </translation>
+ <translation>Marii</translation>
</message>
<message>
<source>Date</source>
@@ -184,7 +184,7 @@
<name>QObject</name>
<message>
<source>Amount</source>
- <translation>Marii </translation>
+ <translation>Marii</translation>
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
@@ -212,7 +212,7 @@
</message>
<message>
<source>N/A</source>
- <translation>Hapana </translation>
+ <translation>Hapana</translation>
</message>
</context>
<context>
@@ -222,7 +222,7 @@
<name>RPCConsole</name>
<message>
<source>N/A</source>
- <translation>Hapana </translation>
+ <translation>Hapana</translation>
</message>
</context>
<context>
@@ -236,7 +236,7 @@
</message>
<message>
<source>Amount</source>
- <translation>Marii </translation>
+ <translation>Marii</translation>
</message>
<message>
<source>Label</source>
@@ -273,9 +273,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -292,7 +289,7 @@
</message>
<message>
<source>Amount</source>
- <translation>Marii </translation>
+ <translation>Marii</translation>
</message>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts
new file mode 100644
index 0000000000..da3551e241
--- /dev/null
+++ b/src/qt/locale/bitcoin_sq.ts
@@ -0,0 +1,774 @@
+<TS language="sq" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>Kliko me të djathtën për të ndryshuar adresën ose etiketen.</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>Krijo një adresë të re</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;E re</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>Kopjo adresën e zgjedhur në memorjen e sistemit </translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;Kopjo</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>Fshi adresen e selektuar nga lista</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;Delete</source>
+ <translation>&amp;Fshi</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Zgjidh adresen ku do te dergoni monedhat</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Zgjidh adresën ku do të merrni monedhat</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>Zgjidh</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Duke derguar adresen</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Duke marr adresen</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>Këto janë Bitcoin adresat e juaja për të dërguar pagesa. Gjithmon kontrolloni shumën dhe adresën pranuese para se të dërgoni monedha.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Kopjo adresen</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Kopjo &amp;Etiketë</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Ndrysho</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Eksporto listën e adresave</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Skedar i ndarë me pikëpresje(*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Eksportimi dështoj</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Gabim gjatë ruajtjes së listës së adresave në %1. Ju lutem provoni prapë.</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>(pa etiketë)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>Futni fjalëkalimin</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>Fjalëkalimi i ri</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>Përsërisni fjalëkalimin e ri</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Kripto portofolin</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Ky veprim ka nevojë per fjalëkalimin e portofolit tuaj që të hapë portofolin.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Hap portofolin.</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Ky veprim kërkon frazkalimin e portofolit tuaj që të dekriptoj portofolin.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Dekripto portofolin</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Ndrysho fjalëkalimin</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Konfirmoni enkriptimin e portofolit</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Jeni te sigurt te enkriptoni portofolin tuaj?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Portofoli u enkriptua</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Enkriptimi i portofolit dështoi</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Enkriptimi i portofolit dështoi për shkak të një gabimi të brëndshëm. portofoli juaj nuk u enkriptua.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Frazkalimet e plotësuara nuk përputhen.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>ç'kyçja e portofolit dështoi</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Frazkalimi i futur për dekriptimin e portofolit nuk ishte i saktë.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Dekriptimi i portofolit dështoi</translation>
+ </message>
+ </context>
+<context>
+ <name>BanTableModel</name>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>Duke u sinkronizuar me rrjetin...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;Përmbledhje</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>Trego një përmbledhje te përgjithshme të portofolit</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;Transaksionet</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>Shfleto historinë e transaksioneve</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>Mbyllni aplikacionin</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>&amp;Opsione</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>Ndrysho frazkalimin e përdorur per enkriptimin e portofolit</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;Dergo</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;Merr</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Shfaq / Fsheh</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;Skedar</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>&amp;Konfigurimet</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>&amp;Ndihmë</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>Shiriti i mjeteve</translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 Pas</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Problem</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Informacion</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation>I azhornuar</translation>
+ </message>
+ <message>
+ <source>Catching up...</source>
+ <translation>Duke u azhornuar...</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Dërgo transaksionin</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>Transaksion në ardhje</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation>Portofoli po &lt;b&gt; enkriptohet&lt;/b&gt; dhe është &lt;b&gt; i ç'kyçur&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>Portofoli po &lt;b&gt; enkriptohet&lt;/b&gt; dhe është &lt;b&gt; i kyçur&lt;/b&gt;</translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Coin Selection</source>
+ <translation>Zgjedhja e monedhes</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Shuma:</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Sasia</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Kopjo adresën</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>po</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>jo</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(pa etiketë)</translation>
+ </message>
+ </context>
+<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation>Ndrysho Adresën</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;Etiketë</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;Adresa</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>Adresë e re dërgimi</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Ndrysho adresën pritëse</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>ndrysho adresën dërguese</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Nuk mund të ç'kyçet portofoli.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Krijimi i çelësit të ri dështoi.</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>name</source>
+ <translation>emri</translation>
+ </message>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation>versioni</translation>
+ </message>
+ </context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Welcome</source>
+ <translation>Miresevini</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Problem</translation>
+ </message>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation>Formilarë</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>Options</source>
+ <translation>Opsionet</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation>Portofol</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Problem</translation>
+ </message>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Form</source>
+ <translation>Formilarë</translation>
+ </message>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>Sasia</translation>
+ </message>
+ <message>
+ <source>%1 and %2</source>
+ <translation>%1 dhe %2</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>i/e panjohur</translation>
+ </message>
+</context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>&amp;Information</source>
+ <translation>Informacion</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation>&amp;Hap</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>asnjehere</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>i/e panjohur</translation>
+ </message>
+</context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Amount:</source>
+ <translation>Shuma:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etiketë:</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>Pastro</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>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Portofol</translation>
+ </message>
+</context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiketë</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(pa etiketë)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>Dërgo Monedha</translation>
+ </message>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation>Fonde te pamjaftueshme</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Shuma:</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation>Dërgo marrësve të ndryshëm njëkohësisht</translation>
+ </message>
+ <message>
+ <source>Balance:</source>
+ <translation>Balanca:</translation>
+ </message>
+ <message>
+ <source>Confirm the send action</source>
+ <translation>Konfirmo veprimin e dërgimit</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>konfirmo dërgimin e monedhave</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Shuma e paguar duhet të jetë më e madhe se 0.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(pa etiketë)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ <message>
+ <source>A&amp;mount:</source>
+ <translation>Sh&amp;uma:</translation>
+ </message>
+ <message>
+ <source>Pay &amp;To:</source>
+ <translation>Paguaj &amp;drejt:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etiketë:</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Ngjit nga memorja e sistemit</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Pay To:</source>
+ <translation>Paguaj drejt:</translation>
+ </message>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Ngjit nga memorja e sistemit</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Open until %1</source>
+ <translation>Hapur deri më %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/I pakonfirmuar</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 konfirmimet</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>i/e panjohur</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>transaksionit</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Sasia</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ <message>
+ <source>This pane shows a detailed description of the transaction</source>
+ <translation>Ky panel tregon një përshkrim të detajuar të transaksionit</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Lloji</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiketë</translation>
+ </message>
+ <message>
+ <source>Open until %1</source>
+ <translation>Hapur deri më %1</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>I/E konfirmuar(%1 konfirmime)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>I krijuar por i papranuar</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Marrë me</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Dërguar drejt</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Pagesë ndaj vetvetes</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minuar</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(p/a)</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(pa etiketë)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Received with</source>
+ <translation>Marrë me</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Dërguar drejt</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minuar</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Kopjo adresën</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Skedar i ndarë me pikëpresje(*.csv)</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Data</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Lloji</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiketë</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Adresë</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Eksportimi dështoj</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletController</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>Dërgo Monedha</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletView</name>
+ <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>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Insufficient funds</source>
+ <translation>Fonde te pamjaftueshme</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>Rikerkim</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_sr.ts b/src/qt/locale/bitcoin_sr.ts
index cb395fdd0d..fecdb44c86 100644
--- a/src/qt/locale/bitcoin_sr.ts
+++ b/src/qt/locale/bitcoin_sr.ts
@@ -334,14 +334,6 @@
<translation>Мењање лозинке којом се шифрује новчаник</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Прозор за отклањање грешке</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Отвори конзолу за отклањање грешака и дијагностику</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Верификовање поруке...</translation>
</message>
@@ -402,10 +394,6 @@
<translation>Прегледајте листу коришћених адреса и етикета за пријем уплата</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Отворите биткоин: URI или захтев за плаћање</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Опције командне линије</translation>
</message>
@@ -749,10 +737,6 @@
<translation>верзија</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Приближно %1</translation>
</message>
@@ -993,6 +977,10 @@
<translation>Налепница</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Poruka</translation>
+ </message>
+ <message>
<source>Wallet</source>
<translation>Новчаник</translation>
</message>
@@ -1008,6 +996,10 @@
<translation>Налепница</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Poruka</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(без налепнице)</translation>
</message>
@@ -1115,13 +1107,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Da</translation>
- </message>
-</context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -1141,6 +1126,18 @@
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>Otvoreno do %1</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/nepotvrdjeno</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 potvrde</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>datum</translation>
</message>
@@ -1149,6 +1146,18 @@
<translation>nepoznato</translation>
</message>
<message>
+ <source>label</source>
+ <translation>етикета</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Poruka</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>transakcije</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Износ</translation>
</message>
@@ -1167,17 +1176,125 @@
<translation>datum</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>tip</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Налепница</translation>
</message>
<message>
+ <source>Open until %1</source>
+ <translation>Otvoreno do %1</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Potvrdjena (%1 potvrdjenih)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Generisan ali nije prihvaćen</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Primljen sa</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Primljeno od</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Poslat ka</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Isplata samom sebi</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minirano</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n/a)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(без налепнице)</translation>
</message>
- </context>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Status vaše transakcije. Predjite mišem preko ovog polja da bi ste videli broj konfirmacija</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Datum i vreme primljene transakcije.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Tip transakcije</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Iznos odbijen ili dodat balansu.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Sve</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Danas</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>ove nedelje</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Ovog meseca</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Prošlog meseca</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Ove godine</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Opseg...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Primljen sa</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Poslat ka</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Vama - samom sebi</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minirano</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Drugi</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Min iznos</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>Копирај адресу</translation>
</message>
@@ -1195,6 +1312,10 @@
<translation>Копирај идентификациони број трансакције</translation>
</message>
<message>
+ <source>Edit label</source>
+ <translation>promeni naziv</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Фајл раздојен тачком (*.csv)</translation>
</message>
@@ -1207,6 +1328,10 @@
<translation>datum</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>tip</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Налепница</translation>
</message>
@@ -1218,7 +1343,15 @@
<source>Exporting Failed</source>
<translation>Извоз Неуспешан</translation>
</message>
- </context>
+ <message>
+ <source>Range:</source>
+ <translation>Opseg:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>do</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
@@ -1249,6 +1382,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Извези податке из одабране картице у фајлj</translation>
</message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Backup новчаника</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_sr@latin.ts b/src/qt/locale/bitcoin_sr@latin.ts
index 06826ad18b..a80c5a0891 100644
--- a/src/qt/locale/bitcoin_sr@latin.ts
+++ b/src/qt/locale/bitcoin_sr@latin.ts
@@ -83,7 +83,7 @@
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>Zarezom odvojena datoteka (*.csv) </translation>
+ <translation>Zarezom odvojena datoteka (*.csv)</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -322,14 +322,6 @@
<translation>Promenite pristupnu frazu za enkiptovanje novčanika</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Prozor za otklanjanje grešaka</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Otvori konzolu za dijagnostiku i otklanjanje grešaka</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Proveri poruku...</translation>
</message>
@@ -557,6 +549,10 @@
<translation>Oznaka</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Poruka</translation>
+ </message>
+ <message>
<source>Wallet</source>
<translation>Novčanik</translation>
</message>
@@ -572,6 +568,10 @@
<translation>Oznaka</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Poruka</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(bez oznake)</translation>
</message>
@@ -607,9 +607,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -621,22 +618,122 @@
<context>
<name>TransactionDesc</name>
<message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/nepotvrdjeno</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 potvrdjeno/ih</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Stanje/Status</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>Izvor</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Generisano</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>Od</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>nepoznato</translation>
</message>
<message>
+ <source>To</source>
+ <translation>Kome</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>sopstvena adresa</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>samo za gledanje</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>etiketa</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Kredit</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>nije prihvaceno</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Zaduzenje</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>Ukupno zaduzenje</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Totalni kredit</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Taksa transakcije</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>Neto iznos</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Poruka</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Komentar</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID Transakcije</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Trgovac</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Informacije debugovanja</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transakcije</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>Unosi</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Kolicina</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>tacno</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>netacno</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
</context>
@@ -647,10 +744,38 @@
<translation>Datum</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Tip</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Oznaka</translation>
</message>
<message>
+ <source>Received with</source>
+ <translation>Primljeno uz</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Primljeno od</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Poslat</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Placanje samom sebi</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Iskopano</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>samo za gledanje</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(bez oznake)</translation>
</message>
@@ -658,14 +783,30 @@
<context>
<name>TransactionView</name>
<message>
+ <source>Received with</source>
+ <translation>Primljeno uz</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Poslat</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Iskopano</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
- <translation>Zarezom odvojena datoteka (*.csv) </translation>
+ <translation>Zarezom odvojena datoteka (*.csv)</translation>
</message>
<message>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>Tip</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Oznaka</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts
index a3f8fd8f3a..e626b1a930 100644
--- a/src/qt/locale/bitcoin_sv.ts
+++ b/src/qt/locale/bitcoin_sv.ts
@@ -70,6 +70,10 @@
<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>
@@ -133,6 +137,10 @@ Försök igen.</translation>
<translation>Upprepa ny lösenfras</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Visa lösenfras</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Kryptera plånbok</translation>
</message>
@@ -173,10 +181,30 @@ Försök igen.</translation>
<translation>Plånbok krypterad</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>Ange den nya lösenfrasen för plånboken. &lt;br/&gt; Använd en lösenfras på &lt;b&gt;tio eller fler slumpmässiga tecken&lt;/b&gt;, eller &lt;b&gt;åtta eller fler ord&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Ange den gamla lösenfrasen och den nya lösenfrasen för plånboken.</translation>
+ </message>
+ <message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
<translation>Kom ihåg att kryptering av din plånbok inte helt kan skydda dig från stöld av dina bitcoins om skadlig kod infekterat din dator.</translation>
</message>
<message>
+ <source>Wallet to be encrypted</source>
+ <translation>Plånbok som ska krypteras</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Din plånbok kommer att krypteras.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Din plånbok är nu krypterad.</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>VIKTIGT: Alla tidigare säkerhetskopior du har skapat av plånboksfilen ska ersättas med den nyss skapade, krypterade plånboksfilen. Av säkerhetsskäl kommer tidigare säkerhetskopior av den okrypterade plånboksfilen att bli oanvändbara när du börjar använda den nya, krypterade plånboken.</translation>
</message>
@@ -299,6 +327,14 @@ Försök igen.</translation>
<translation>Öppna &amp;URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Skapa plånbok...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Skapa ny plånbok</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Plånbok:</translation>
</message>
@@ -339,14 +375,6 @@ Försök igen.</translation>
<translation>Byt lösenfras för kryptering av plånbok</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Felsökningsfönster</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Öppna felsöknings- och diagnostikkonsolen</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Verifiera meddelande...</translation>
</message>
@@ -407,10 +435,6 @@ Försök igen.</translation>
<translation>Visa listan med använda mottagaradresser och etiketter</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Öppna en bitcoin: URI eller betalningsbegäran</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Kommandoradsalternativ</translation>
</message>
@@ -527,6 +551,10 @@ Försök igen.</translation>
<translation>Fel: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Varning: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Datum: %1
@@ -748,10 +776,38 @@ Försök igen.</translation>
</context>
<context>
<name>CreateWalletActivity</name>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Skapar plånboken &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Plånboken kunde inte skapas</translation>
+ </message>
</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Skapa plånbok</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Namn på plånboken</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>Kryptera plånboken. Plånboken krypteras med en lösenfras som du själv väljer.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Kryptera plånbok</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Skapa</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -837,10 +893,6 @@ Försök igen.</translation>
<translation>version</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Om %1</translation>
</message>
@@ -913,13 +965,17 @@ Försök igen.</translation>
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
- <translation><numerusform>%n GB fritt utrymme kvar</numerusform><numerusform>%n GB fritt utrymme kvar</numerusform></translation>
+ <translation><numerusform>%n GB fritt utrymme kvar</numerusform><numerusform>%n GB ledigt utrymme kvar</numerusform></translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
- <translation><numerusform>(av %n GB behövs)</numerusform><numerusform>(av %n GB behövs)</numerusform></translation>
+ <translation><numerusform>(av %n GB behövs)</numerusform><numerusform>(av de %n GB som behövs)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB behövs för hela kedjan)</numerusform><numerusform>(%n GB behövs för hela kedjan)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -932,7 +988,7 @@ Försök igen.</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>Att försöka spendera bitcoin som påverkas av transaktioner som ännu inte visas kommer inte accepteras av nätverket. </translation>
+ <translation>Att försöka spendera bitcoin som påverkas av transaktioner som ännu inte visas kommer inte accepteras av nätverket.</translation>
</message>
<message>
<source>Number of blocks left</source>
@@ -974,29 +1030,17 @@ Försök igen.</translation>
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Öppna URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Öppna betalningsbegäran från URI eller fil</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Välj betalningsbegäransfil</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Välj betalningsbegäransfil som ska öppnas</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
<message>
+ <source>Open wallet failed</source>
+ <translation>Det gick inte att öppna plånboken</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>Standardplånbok</translation>
</message>
@@ -1149,11 +1193,11 @@ Försök igen.</translation>
</message>
<message>
<source>Proxy &amp;IP:</source>
- <translation>Proxy-&amp;IP: </translation>
+ <translation>Proxy-&amp;IP:</translation>
</message>
<message>
<source>&amp;Port:</source>
- <translation>&amp;Port: </translation>
+ <translation>&amp;Port:</translation>
</message>
<message>
<source>Port of the proxy (e.g. 9050)</source>
@@ -1201,7 +1245,7 @@ Försök igen.</translation>
</message>
<message>
<source>User Interface &amp;language:</source>
- <translation>Användargränssnittets &amp;språk: </translation>
+ <translation>Användargränssnittets &amp;språk:</translation>
</message>
<message>
<source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
@@ -1209,7 +1253,7 @@ Försök igen.</translation>
</message>
<message>
<source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Måttenhet att visa belopp i: </translation>
+ <translation>&amp;Måttenhet att visa belopp i:</translation>
</message>
<message>
<source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
@@ -1374,18 +1418,6 @@ Försök igen.</translation>
<translation>'bitcoin://' är inte en accepterad URI. Använd 'bitcoin:' istället.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Du använder en URL enligt BIP70, vilket inte kommer att stödjas i framtiden.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Hämtningsadressen för betalningsbegäran är ogiltig: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Det går inte att behandla betalningsbegäran eftersom stöd för BIP70 inte var aktiverat vid kompilering.</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>Ogiltig betalningsadress %1</translation>
</message>
@@ -1397,66 +1429,6 @@ Försök igen.</translation>
<source>Payment request file handling</source>
<translation>Hantering av betalningsbegäransfil</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Betalningsbegäransfilen kan inte läsas! Detta kan orsakas av en ogiltig betalningsbegäransfil.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Betalningsbegäran avslogs</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Betalningsbegärans nätverk matchar inte klientens nätverk.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Betalningsbegäran löpte ut.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Betalningsbegäran är inte initierad.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Overifierade betalningsbegäranden till anpassade betalningsskript stöds inte.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Ogiltig betalningsbegäran.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Begärt belopp på %1 är för litet (betraktas som damm).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Återbetalning från %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Betalningsbegäran %1 är för stor (%2 byte, tillåts %3 byte).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Kommunikationsfel med %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Betalningsbegäran kan inte parsas!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Felaktigt svar från server %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Fel vid nätverksbegäran</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Betalningen bekräftad</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1630,10 +1602,6 @@ Försök igen.</translation>
<translation>&amp;Information</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Felsökningsfönster</translation>
- </message>
- <message>
<source>General</source>
<translation>Allmänt</translation>
</message>
@@ -1965,6 +1933,10 @@ Försök igen.</translation>
<translation>Ett valfritt belopp att begära. Lämna tomt eller ange noll för att inte begära ett specifikt belopp.</translation>
</message>
<message>
+ <source>&amp;Create new receiving address</source>
+ <translation>S&amp;kapa ny mottagaradress</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Rensa alla formulärfälten</translation>
</message>
@@ -2170,10 +2142,6 @@ Försök igen.</translation>
<translation>Varning: Avgiftsuppskattning är för närvarande inte möjlig.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>Fäll ihop avgiftsinställningarna</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>
@@ -2286,6 +2254,10 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>%1 (%2 block)</translation>
</message>
<message>
+ <source> from wallet '%1'</source>
+ <translation>från plånbok: '%1'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 till %2</translation>
</message>
@@ -2346,10 +2318,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Transaktionen gick inte att skapa!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Transaktionen avvisades med följande orsak: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>En avgift högre än %1 anses vara en absurd hög avgift.</translation>
</message>
@@ -2401,10 +2369,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Välj tidigare använda adresser</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Detta är en normal betalning.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Bitcoin-adress att sända betalning till</translation>
</message>
@@ -2464,17 +2428,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<source>Memo:</source>
<translation>PM:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Ange en etikett för denna adress för att lägga till den i din adressbok</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -3203,10 +3156,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Omskanningar kan inte göras i gallrat läge. Du måste använda -reindex vilket kommer ladda ner hela blockkedjan igen.</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>
@@ -3387,6 +3336,10 @@ 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>
@@ -3495,6 +3448,10 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Port måste anges med -whitelist: '%s'</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Gallringsläge är inkompatibelt med -blockfilterindex.</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Minskar -maxconnections från %d till %d, på grund av systembegränsningar.</translation>
</message>
@@ -3573,10 +3530,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Detta är transaktionsavgiften du kan komma att betala om avgiftsuppskattning inte är tillgänglig.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Denna produkt innehåller mjukvara utvecklad av OpenSSL Project för användning i OpenSSL Toolkit %s och kryptografisk mjukvara utvecklad av Eric Young samt UPnP-mjukvara skriven av Thomas Bernard.</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 längd på strängen för nätverksversion (%i) överskrider maxlängden (%i). Minska numret eller storleken på uacomments.</translation>
</message>
@@ -3602,11 +3555,11 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
</message>
<message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Det här är minimiavgiften du kommer betala för varje transaktion. </translation>
+ <translation>Det här är minimiavgiften du kommer betala för varje transaktion.</translation>
</message>
<message>
<source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Det här är transaktionsavgiften du kommer betala om du skickar en transaktion. </translation>
+ <translation>Det här är transaktionsavgiften du kommer betala om du skickar en transaktion.</translation>
</message>
<message>
<source>Transaction amounts must not be negative</source>
@@ -3662,7 +3615,7 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
</message>
<message>
<source>Done loading</source>
- <translation>Klar med laddning</translation>
+ <translation>Inläsning klar</translation>
</message>
</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_szl.ts b/src/qt/locale/bitcoin_szl.ts
index 0b4706383c..3fb191c50f 100644
--- a/src/qt/locale/bitcoin_szl.ts
+++ b/src/qt/locale/bitcoin_szl.ts
@@ -334,14 +334,6 @@
<translation>Pōmiyń hasło użyte do szyfrowaniŏ portmanyja</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>Ôkno &amp;debugowaniŏ</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Ôdewrzij kōnsolã debugowaniŏ i diagnostyki</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Weryfikuj wiadōmość...</translation>
</message>
@@ -402,10 +394,6 @@
<translation>Pokŏż wykŏz adres i etyket użytych do ôdbiyraniŏ</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Ôdewrzij URI bitcoin: abo żōndanie płatu</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Ôp&amp;cyje piski nakŏzań</translation>
</message>
@@ -784,10 +772,6 @@
<translation>wersyjŏ</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Ô %1</translation>
</message>
@@ -917,25 +901,9 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Ôdewrzij URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Ôdewrzij żōndanie płatu z URI abo zbioru</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Ôtwōrz żōndanie płatu ze zbioru</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Ôbier zbiōr żōndaniŏ płatu do ôdewrzyniŏ</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1172,27 +1140,7 @@
<source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
<translation>'bitcoin://' to niyma nŏleżne URI. Użyj 'bitcoin:'.</translation>
</message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Nec żōndaniŏ płatu niy ôdpadŏ necu klijynta.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Niyzweryfikowane żōndaniŏ płatu do włŏsnych skryptōw płatu sōm niypodpiyrane.</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Feler kōmunikacyje z %1: %2</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Feler żōndaniŏ necu</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Płat przituplowany</translation>
- </message>
-</context>
+ </context>
<context>
<name>PeerTableModel</name>
<message>
@@ -1297,10 +1245,6 @@
<translation>Wersyjŏ klijynta</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Ôkno debugowaniŏ</translation>
- </message>
- <message>
<source>Using BerkeleyDB version</source>
<translation>Używanie wersyje BerkeleyDB</translation>
</message>
@@ -1338,7 +1282,7 @@
</message>
<message>
<source>Wallet: </source>
- <translation>Portmanyj: </translation>
+ <translation>Portmanyj:</translation>
</message>
<message>
<source>Received</source>
@@ -1656,10 +1600,6 @@
<translation>&amp;Etyketa:</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>To je normalny płat.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Adresa Bitcoin, na kerõ chcesz posłać płat</translation>
</message>
@@ -1685,13 +1625,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
-</context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_ta.ts b/src/qt/locale/bitcoin_ta.ts
index 3fcdc6453a..85f7db346f 100644
--- a/src/qt/locale/bitcoin_ta.ts
+++ b/src/qt/locale/bitcoin_ta.ts
@@ -2,20 +2,24 @@
<context>
<name>AddressBookPage</name>
<message>
+ <source>Right-click to edit address or label</source>
+ <translation>முகவரியை மாற்ற ரைட் கிளிக் செய்யவும்</translation>
+ </message>
+ <message>
<source>Create a new address</source>
- <translation>புதிய முகவரியை உருவாக்கவும்</translation>
+ <translation>புதிய முகவரியை உருவாக்கு</translation>
</message>
<message>
<source>&amp;New</source>
- <translation>&amp;புதிய</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;நகல்</translation>
+ <translation>&amp;காபி</translation>
</message>
<message>
<source>C&amp;lose</source>
@@ -31,11 +35,11 @@
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>தற்போதைய தாவலில் தரவை ஒரு கோப்பிற்கு ஏற்றுமதி செய்க</translation>
+ <translation>தற்போதைய டாபில் உள்ள தகவலை ஒரு பைலிற்கு ஏக்ஸ்போர்ட் செய்க</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation>&amp;ஏற்றுமதி</translation>
+ <translation>&amp;எக்ஸ்போர்ட்</translation>
</message>
<message>
<source>&amp;Delete</source>
@@ -43,11 +47,15 @@
</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;ர்வுசெய் </translation>
</message>
<message>
<source>Sending addresses</source>
@@ -59,23 +67,27 @@
</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>
+ <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>
+ <translation>&amp;காபி முகவரி</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>&amp; லேபிள் நகலெடு</translation>
+ <translation>காபி &amp;லேபிள்</translation>
</message>
<message>
<source>&amp;Edit</source>
- <translation>&amp;தொகு</translation>
+ <translation>&amp;எடிட்</translation>
</message>
<message>
<source>Export Address List</source>
- <translation>முகவரி பட்டியல் ஏற்றுமதி</translation>
+ <translation>முகவரி பட்டியல் ஏக்ஸ்போர்ட் செய்க </translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
@@ -83,11 +95,11 @@
</message>
<message>
<source>Exporting Failed</source>
- <translation>ஏற்றுமதி தோல்வியடைந்தது</translation>
+ <translation>ஏக்ஸ்போர்ட் தோல்வியடைந்தது</translation>
</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>
@@ -124,8 +136,12 @@
<translation>புதிய கடவுச்சொற்றொடரைக் கோருக</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <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>
@@ -164,6 +180,30 @@
<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>வாலட்டை பாதுகாக்க புதிய கடவுச்சொல்லை உல்லிடவும். பத்து அல்லது அதற்கு மேற்பட்ட எழுத்துகள் அல்லது எட்டு அல்லது அதற்கு மேற்பட்ட எழுத்துக்களை கடவுச்சொல்லாக பயன்படுத்தவும்.</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>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>குறியாக்கம் செய்யப்பட வேண்டிய வால்லட்</translation>
+ </message>
+ <message>
+ <source>Your wallet is about 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>
@@ -286,6 +326,14 @@
<translation>&amp;URI-ஐ திற</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>வாலட்டை உருவாக்கு...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>புதிய வாலட்டை உருவாக்கு</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>கைப்பை:</translation>
</message>
@@ -326,14 +374,6 @@
<translation>பணப்பை குறியாக்கத்திற்காக பயன்படுத்தப்படும் கடவுச்சொற்றொடரை மாற்றவும்</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp; பிழைத்திருத்த சாளரம்</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>பிழைத்திருத்த மற்றும் கண்டறிதல் பணியகம் திறக்க</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;செய்தியை சரிசெய்...</translation>
</message>
@@ -394,13 +434,13 @@
<translation>பயன்படுத்திய முகவரிகள் மற்றும் லேபிள்களின் பட்டியலைக் காட்டு</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>ஒரு Bitcoin திறக்க: URI அல்லது பணம் கோரிக்கை</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp; கட்டளை வரி விருப்பங்கள்</translation>
</message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>பிட்காயின் வலையமைப்புடன் %n செயலில் உள்ள இணைப்புகள்</numerusform><numerusform>பிட்காயின் வலையமைப்புடன் %n செயலில் உள்ள இணைப்புகள்</numerusform></translation>
+ </message>
<message>
<source>Indexing blocks on disk...</source>
<translation>வட்டில் தொகுதிகளை குறியாக்குகிறது ...</translation>
@@ -409,6 +449,10 @@
<source>Processing blocks on disk...</source>
<translation>வட்டில் தொகுதிகள் செயலாக்கப்படுகின்றன ...</translation>
</message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>பரிவர்த்தனை வரலாற்றில் %n ப்லாக் செயலாக்கப்பட்டது.</numerusform><numerusform>பரிவர்த்தனை வரலாற்றில் %n ப்லாக்ககள் செயலாக்கப்பட்டன.</numerusform></translation>
+ </message>
<message>
<source>%1 behind</source>
<translation>%1 பின்னால்</translation>
@@ -446,10 +490,34 @@
<translation>முகவரிகள் பெறுதல்</translation>
</message>
<message>
+ <source>Open Wallet</source>
+ <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>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>சாத்தியமான Bitcoin கட்டளை-வரி விருப்பங்களைக் கொண்ட பட்டியலைப் பெற %1 உதவிச் செய்தியைக் காட்டு</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>அடிப்படை வாலட்</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation>வாலட் எதுவும் இல்லை</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;சாளரம்</translation>
</message>
@@ -482,6 +550,10 @@
<translation>பிழை: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>எச்சரிக்கை: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>தேதி: %1
@@ -494,12 +566,24 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>வாலட்: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>வகை: %1
</translation>
</message>
<message>
+ <source>Label: %1
+</source>
+ <translation>லேபிள்: %1
+</translation>
+ </message>
+ <message>
<source>Address: %1
</source>
<translation>முகவரி: %1
@@ -691,10 +775,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <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>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>வாலட் உருவாக்கம் எச்சரிக்கை</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>வாலட்டை உருவாக்கு</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>வாலட் பெயர்</translation>
+ </message>
+ <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>இந்த வாலட்டிற்கு ப்ரைவேட் கீஸை முடக்கு. முடக்கப்பட்ட ப்ரைவேட் கீஸ் கொண்ட வாலட்டிற்கு ப்ரைவேட் கீஸ் இருக்காது மற்றும் எச்டி ஸீட் அல்லது இம்போர்ட் செய்யப்பட்ட ப்ரைவேட் கீஸ் இருக்கக்கூடாது. பார்க்க-மட்டும் உதவும் வாலட்டிற்கு இது ஏற்றது.</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>காலியான வாலட்டை உருவாக்கு. காலியான வாலட்டிற்கு ஆரம்பத்தில் ப்ரைவேட் கீஸ் மற்றும் ஸ்கிரிப்ட் இருக்காது. ப்ரைவேட் கீஸ் மற்றும் முகவரிகளை இம்போர்ட் செய்து கொள்ளலாம், அல்லது எச்டி ஸீடை பின்னர், அமைத்து கொள்ளலாம்.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>காலியான வாலட்டை உருவாக்கு</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>உருவாக்கு</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -780,10 +912,6 @@
<translation>பதிப்பு</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-பிட்)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>%1 பற்றி</translation>
</message>
@@ -811,6 +939,10 @@
<translation>நீங்கள் சரி என்பதைக் கிளிக் செய்தால் %1 ஆரம்பத்தில் %4 இல் ஆரம்பிக்கப்பட்ட %3 இன் ஆரம்ப பரிவர்த்தனைகளைத் தொடங்கும் போது முழு %4 தொகுதி சங்கிலி (%2GB) பதிவிறக்க மற்றும் செயலாக்கத் தொடங்கும்.</translation>
</message>
<message>
+ <source>Reverting this setting requires re-downloading the entire blockchain. It is faster to download the full chain first and prune it later. Disables some advanced features.</source>
+ <translation>இந்த அமைப்பை மாற்றியமைக்க முழு பிளாக்செயினையும் மீண்டும் டவுன்லோட் செய்ய வேண்டும். முதலில் முழு செயினையும் டவுன்லோட் செய்த பின்னர் ப்ரூன் செய்வது வேகமான செயல் ஆகும். சில மேம்பட்ட அம்சங்களை முடக்கும்.</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>
@@ -831,6 +963,10 @@
<translation>Bitcoin</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>
@@ -854,6 +990,14 @@
<source>Error</source>
<translation>பிழை</translation>
</message>
+ <message numerus="yes">
+ <source>%n GB of free space available</source>
+ <translation><numerusform>%n ஜிபி அளவு காலியாக உள்ளது</numerusform><numerusform>%n ஜிபி அளவு காலியாக உள்ளது</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation><numerusform>(%n ஜிபி தேவை)</numerusform><numerusform>(%n ஜிபி தேவை)</numerusform></translation>
+ </message>
</context>
<context>
<name>ModalOverlay</name>
@@ -909,30 +1053,30 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>URI-ஐ திற</translation>
+ <source>URI:</source>
+ <translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Open payment request from URI or file</source>
- <translation>URI அல்லது கோப்பிலிருந்து பணம் செலுத்துவதற்கான கோரிக்கையைத் திறக்கவும்</translation>
+ <source>Open wallet failed</source>
+ <translation>வாலட் திறத்தல் தோல்வியுற்றது</translation>
</message>
<message>
- <source>URI:</source>
- <translation>URI:</translation>
+ <source>Open wallet warning</source>
+ <translation>வாலட் திறத்தல் எச்சரிக்கை</translation>
</message>
<message>
- <source>Select payment request file</source>
- <translation>பணம் கோரிக்கை கோப்பைத் தேர்ந்தெடுக்கவும்</translation>
+ <source>default wallet</source>
+ <translation>அடிப்படை வாலட்</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>திறக்க கட்டணம் கோரிக்கை கோப்பைத் தேர்ந்தெடுக்கவும்</translation>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>வாலட் திறத்தல் &lt;b&gt;%1&lt;/b&gt;...</translation>
</message>
</context>
<context>
- <name>OpenWalletActivity</name>
- </context>
-<context>
<name>OptionsDialog</name>
<message>
<source>Options</source>
@@ -1301,16 +1445,12 @@
<translation>'bitcoin: //' சரியான URI அல்ல. அதற்கு பதிலாக 'பிட்கின்:' பயன்படுத்தவும்.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>நீங்கள் எதிர்காலத்தில் ஆதரிக்கப்படாத BIP70 URL ஐப் பயன்படுத்துகிறீர்கள்.</translation>
+ <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>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>பணம் செலுத்தும் கோரிக்கை URL ஐ பெறுகிறது: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>கட்டண கோரிக்கையை செயல்படுத்த முடியவில்லை, ஏனெனில் BIP70 ஆதரவு தொகுக்கப்படவில்லை.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>இந்த பிழையை நீங்கள் பெறுகிறீர்கள் என்றால், வணிகரிடம் பிப்21 இணக்கமான யுஆர்எல் லை வழங்குமாறு கேட்க வேண்டும்.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1324,66 +1464,6 @@
<source>Payment request file handling</source>
<translation>பணம் கோரிக்கை கோப்பு கையாளுதல்</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>கட்டண கோரிக்கை கோப்பு படிக்க முடியாது! இது தவறான கட்டண கோரிக்கை கோப்பால் ஏற்படலாம்.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>கட்டணம் கோரிக்கை நிராகரிக்கப்பட்டது</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>வாடிக்கையாளர் நெட்வொர்க்குடன் கட்டண கோரிக்கை பிணையம் பொருந்தவில்லை.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>கட்டணம் கோரிக்கை காலாவதியானது.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>கட்டணம் கோரிக்கை ஆரம்பிக்கப்படவில்லை.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>தனிப்பயன் கட்டண ஸ்கிரிப்டுகளுக்கான சரிபார்க்கப்படாத கட்டண கோரிக்கைகள் ஆதரிக்கப்படவில்லை.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>தவறான கட்டண கோரிக்கை.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>%1 இன் கோரப்பட்ட கட்டணம் அளவு மிகவும் குறைவாக உள்ளது (தூசி கருதப்படுகிறது).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>%1 இலிருந்து திரும்பப்பெறவும்</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>கட்டணம் கோரிக்கை %1 மிக அதிகமாக உள்ளது (%2 பைட்டுகள், அனுமதிக்கப்பட்ட %3 பைட்டுகள்).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>%1: %2 உடன் தொடர்புகொள்வதில் பிழை</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>கட்டண கோரிக்கையை பாகுபடுத்த முடியாது!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>%1 சேவையகத்திலிருந்து தவறான பதில்</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>நெட்வொர்க் கோரிக்கை பிழை</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>கட்டணம் ஒப்புக் கொண்டது</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1510,6 +1590,10 @@
<translation>QR குறியீட்டில் யு.ஆர்.ஐ குறியாக்கப் பிழை.</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>க்யு ஆர் கோட் சப்போர்ட் இல்லை</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>QR குறியீடு சேமிக்கவும்</translation>
</message>
@@ -1533,10 +1617,6 @@
<translation>&amp;தகவல்</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>பிழைத்திருத்த சாளரம்</translation>
- </message>
- <message>
<source>General</source>
<translation>பொது</translation>
</message>
@@ -1868,6 +1948,10 @@
<translation>கோரிக்கைக்கு விருப்பமான தொகை. ஒரு குறிப்பிட்ட தொகையை கோர வேண்டாம் இந்த வெற்று அல்லது பூஜ்ஜியத்தை விடு.</translation>
</message>
<message>
+ <source>&amp;Create new receiving address</source>
+ <translation>&amp;புதிய பிட்காயின் பெறும் முகவரியை உருவாக்கு</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>படிவத்தின் அனைத்து துறையையும் அழி.</translation>
</message>
@@ -2073,10 +2157,6 @@
<translation>எச்சரிக்கை: கட்டணம் மதிப்பீடு தற்போது சாத்தியமில்லை.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>கட்டண சரிவுகளை சரி செய்ய வேண்டும்</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>
@@ -2129,10 +2209,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>ஒரு மிக குறைந்த கட்டணம் ஒரு உறுதி பரிவர்த்தனை விளைவாக (உதவிக்குறிப்பு வாசிக்க)</translation>
</message>
<message>
+ <source>Confirmation time target:</source>
+ <translation>உறுதிப்படுத்தும் நேர இலக்கு:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>மாற்று-கட்டணத்தை இயக்கு</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>மாற்று-கட்டணத்தின் (பிப்-125) மூலம், ஒரு பரிவர்த்தனையின் கட்டணத்தை அனுப்பிய பின் அதை அதிகரிக்கலாம். இது இல்லை என்றால், பரிவர்த்தனையின் தாமத அபாயத்தை ஈடுசெய்ய அதிக கட்டணம் பரிந்துரைக்கப்படலாம்.</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>அழி &amp;அனைத்து</translation>
+ </message>
+ <message>
<source>Balance:</source>
<translation>இருப்பு:</translation>
</message>
<message>
+ <source>Confirm the send action</source>
+ <translation>அனுப்பும் செயலை உறுதிப்படுத்து</translation>
+ </message>
+ <message>
<source>S&amp;end</source>
<translation>&amp;அனுப்பு</translation>
</message>
@@ -2165,9 +2265,101 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>மாற்றத்தை நகலெடுக்கவும்</translation>
</message>
<message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 ப்ளாக்ஸ்)</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation>வாலட்டில் இருந்து '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 இருந்து '%2'</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 இருந்து %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>நீங்கள் நிச்சயமாக அனுப்ப விரும்புகிறீர்களா?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>அல்லது</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>நீங்கள் கட்டணத்தை பின்னர் அதிகரிக்கலாம் (என்கிறது மாற்று கட்டணம், பிப்-125).</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>தயவு செய்து, உங்கள் பரிவர்த்தனையை சரிபார்க்கவும்.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>பரிமாற்ற கட்டணம்</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>சிக்னல் செய்யவில்லை மாற்று-கட்டணம், பிப்-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <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>The recipient address is not valid. Please recheck.</source>
+ <translation>பெறுநரின் முகவரி தவறானது. மீண்டும் சரிபார்க்கவும்.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>அனுப்ப வேண்டிய தொகை 0வை விட பெரியதாக இருக்க வேண்டும்.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>தொகை உங்கள் இருப்பையைவிட அதிகமாக உள்ளது.</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>நகல் முகவரி காணப்பட்டது: முகவரிகள் ஒவ்வொன்றும் ஒரு முறை மட்டுமே பயன்படுத்தப்பட வேண்டும்.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>பரிவர்த்தனை உருவாக்கம் தோல்வியடைந்தது!</translation>
+ </message>
+ <message>
<source>Payment request expired.</source>
<translation>கட்டணம் கோரிக்கை காலாவதியானது.</translation>
</message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>%n பிளாக் உறுதிப்படுத்தலைத் தொடங்க மதிப்பிடப்பட்டுள்ளது.</numerusform><numerusform>%n பிளாக்குள் உறுதிப்படுத்தலைத் தொடங்க மதிப்பிடப்பட்டுள்ளது.</numerusform></translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>எச்சரிக்கை: தவறான பிட்காயின் முகவரி</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>எச்சரிக்கை: தெரியாத மாற்று முகவரி</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <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>
+ </message>
<message>
<source>(no label)</source>
<translation>(லேபிள் இல்லை)</translation>
@@ -2180,47 +2372,224 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>&amp;தொகை:</translation>
</message>
<message>
+ <source>Pay &amp;To:</source>
+ <translation>செலுத்து &amp;கொடு:</translation>
+ </message>
+ <message>
<source>&amp;Label:</source>
<translation>&amp;சிட்டை:</translation>
</message>
<message>
+ <source>Choose previously used address</source>
+ <translation>முன்பு பயன்படுத்திய முகவரியைத் தேர்வுசெய்</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>கட்டணத்தை அனுப்ப பிட்காயின் முகவரி</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
<message>
+ <source>Paste address from clipboard</source>
+ <translation>கிளிப்போர்டிலிருந்து முகவரியை பேஸ்ட் செய்யவும்</translation>
+ </message>
+ <message>
<source>Alt+P</source>
<translation>Alt+P</translation>
</message>
<message>
+ <source>Remove this entry</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>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>கட்டணத்தை தொகையிலிருந்து வி&amp;லக்கு</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>மீதம் உள்ள தொகையை பயன்படுத்தவும்</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>செய்தி:</translation>
</message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
<message>
- <source>Yes</source>
- <translation>ஆம்</translation>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>இது ஒரு அங்கீகரிக்கப்படாத கட்டண கோரிக்கை.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>இது ஒரு அங்கீகரிக்கப்பட்ட கட்டண கோரிக்கை.</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <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>
+ <translation>பிட்காயினுடன் இணைக்கப்பட்ட செய்தி: உங்கள் எதிர்கால குறிப்புக்காக பரிவர்த்தனையுடன் யூஆர்ஐ சேமிக்கப்படும். குறிப்பு: இந்த செய்தி பிட்காயின் வலையமைப்பிற்கு அனுப்பப்படாது.</translation>
+ </message>
+ <message>
+ <source>Pay To:</source>
+ <translation>பணம் செலுத்து:</translation>
+ </message>
+ <message>
+ <source>Memo:</source>
+ <translation>குறிப்பாணை:</translation>
</message>
</context>
<context>
<name>ShutdownWindow</name>
- </context>
+ <message>
+ <source>%1 is shutting down...</source>
+ <translation>%1 ஷட் டவுன் செய்யப்படுகிறது...</translation>
+ </message>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation>இந்த விண்டோ மறைந்து போகும் வரை கணினியை ஷட் டவுன் வேண்டாம்.</translation>
+ </message>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>கையொப்பங்கள் - ஒரு செய்தியை கையொப்பமிடுதல் / சரிபார்த்தல்</translation>
+ </message>
+ <message>
+ <source>&amp;Sign Message</source>
+ <translation>&amp;செய்தியை கையொப்பமிடுங்கள்</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>மற்றவர்களுக்கு அனுப்பப்பட்ட பிட்காயின்களைப் நீங்கள் பெறலாம் என்பதை நிரூபிக்க உங்கள் முகவரிகளுடன் செய்திகள் / ஒப்பந்தங்களில் கையொப்பமிடலாம். தெளிவற்ற அல்லது சீரற்ற எதையும் கையொப்பமிடாமல் கவனமாக இருங்கள், ஏனெனில் ஃபிஷிங் தாக்குதல்கள் உங்கள் அடையாளத்தை அவர்களிடம் கையொப்பமிட்டு ஏமாற்ற முயற்சிக்கும். நீங்கள் ஒப்புக்கொள்ளும் முழுமையான மற்றும் விரிவான அறிக்கைகளில் மட்டுமே கையொப்பமிடுங்கள்.</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation>செய்தியை கையொப்பமிட பிட்காயின் முகவரி</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>முன்பு பயன்படுத்திய முகவரியைத் தேர்வுசெய்</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
<message>
+ <source>Paste address from clipboard</source>
+ <translation>கிளிப்போர்டிலிருந்து முகவரியை பேஸ்ட் செய்யவும்</translation>
+ </message>
+ <message>
<source>Alt+P</source>
<translation>Alt+P</translation>
</message>
<message>
+ <source>Enter the message you want to sign here</source>
+ <translation>நீங்கள் கையொப்பமிட வேண்டிய செய்தியை இங்கே உள்ளிடவும்</translation>
+ </message>
+ <message>
<source>Signature</source>
<translation>கையொப்பம்</translation>
</message>
- </context>
+ <message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>தற்போதைய கையொப்பத்தை கிளிப்போர்டுக்கு காபி செய்</translation>
+ </message>
+ <message>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation>இந்த பிட்காயின் முகவரி உங்களுக்கு சொந்தமானது என்பதை நிரூபிக்க செய்தியை கையொப்பமிடுங்கள்</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation>கையொப்பம் &amp;செய்தி</translation>
+ </message>
+ <message>
+ <source>Reset all sign message fields</source>
+ <translation>எல்லா கையொப்ப செய்தி உள்ளீடுகளை ரீசெட் செய்யவும்</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>அழி &amp;அனைத்து</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation>&amp;செய்தியைச் சரிபார்க்கவும்</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation>செய்தி கையொப்பமிடப்பட்ட பிட்காயின் முகவரி</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>குறிப்பிட்ட பிட்காயின் முகவரியுடன் கையொப்பமிடப்பட்டதா என்பதை உறுதிப்படுத்த இந்த செய்தியைச் சரிபார்க்கவும்</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation>சரிபார்க்கவும் &amp;செய்தி</translation>
+ </message>
+ <message>
+ <source>Reset all verify message fields</source>
+ <translation>எல்லா செய்தியை சரிபார்க்கும் உள்ளீடுகளை ரீசெட் செய்யவும்</translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>கையொப்பத்தை உருவாக்க "செய்தியை கையொப்பமிடு" என்பதை கிளிக் செய்யவும்</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>உள்ளிட்ட முகவரி தவறானது.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>முகவரியைச் சரிபார்த்து மீண்டும் முயற்சிக்கவும்.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>உள்ளிட்ட முகவரி எந்த ஒரு கீயை குறிக்கவில்லை.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>வாலட் திறத்தல் ரத்து செய்யப்பட்டது.</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>உள்ளிட்ட முகவரிக்கான ப்ரைவேட் கீ கிடைக்கவில்லை.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>செய்தியை கையொப்பமிடுதல் தோல்வியுற்றது.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>செய்தி கையொப்பமிடப்பட்டது.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>கையொப்பத்தை டிகோட் செய்ய இயலவில்லை.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>கையொப்பத்தை சரிபார்த்து மீண்டும் முயற்சிக்கவும்.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>கையொப்பம் செய்தியுடன் பொருந்தவில்லை.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>செய்தி சரிபார்ப்பு தோல்வியுற்றது.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>செய்தி சரிபார்க்கப்பட்டது.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
<message>
@@ -2230,25 +2599,173 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</context>
<context>
<name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>மேலும் %n பிளாக்க்கிற்கு திறந்துவைக்கப்பட்டுள்ளது</numerusform><numerusform>மேலும் %n பிளாக்குகளில் திறந்துவைக்கப்பட்டுள்ளது</numerusform></translation>
+ </message>
+ <message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>%1 உறுதிப்படுத்தல்களுடன் ஒரு பரிவர்த்தனை முரண்பட்டது</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, %1</source>
+ <translation>0/உறுதிப்படுத்தப்படாதது, %1</translation>
+ </message>
+ <message>
+ <source>in memory pool</source>
+ <translation>மெமரி பூலில் உள்ளது</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>மெமரி பூலில் இல்லை</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>கைவிடப்பட்டது</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/உறுதிப்படுத்தப்படாதது</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 உறுதிப்படுத்தல்</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>தற்போதைய நிலை</translation>
+ </message>
<message>
<source>Date</source>
<translation>தேதி</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>மூலம்</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>உருவாக்கப்பட்டது</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>இருந்து</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>தெரியாத</translation>
</message>
<message>
+ <source>To</source>
+ <translation>இதற்கு அனுப்பு</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>சொந்த முகவரி</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>பார்க்க-மட்டும்</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>லேபிள்</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>கடன்</translation>
+ </message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>மேலும் %n பிளாக்குகளில் முதிர்ச்சியடைகிறது</numerusform><numerusform>மேலும் %n பிளாக்குகளில் முதிர்ச்சியடைகிறது</numerusform></translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>ஏற்கப்படவில்லை</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>டெபிட்</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>மொத்த டெபிட்</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>முழு கடன்</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>பரிமாற்ற கட்டணம்</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation>நிகர தொகை</translation>
+ </message>
+ <message>
<source>Message</source>
<translation>செய்தி</translation>
</message>
<message>
+ <source>Comment</source>
+ <translation>கருத்து</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>பரிவர்த்தனை ஐடி</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation>பரிவர்த்தனையின் முழு அளவு</translation>
+ </message>
+ <message>
+ <source>Transaction virtual size</source>
+ <translation>பரிவர்த்தனையின் மெய்நிகர் அளவு</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>வெளியீட்டு அட்டவணை</translation>
+ </message>
+ <message>
+ <source> (Certificate was not verified)</source>
+ <translation>(சான்றிதழ் சரிபார்க்கப்படவில்லை)</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>வணிகர்</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>டிபக் தகவல்</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>பரிவர்த்தனை</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>உள்ளீடுகள்</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>தொகை</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>ஆம்</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>இல்லை</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
+ <message>
+ <source>This pane shows a detailed description of the transaction</source>
+ <translation>இந்த பலகம் பரிவர்த்தனை பற்றிய விரிவான விளக்கத்தைக் காட்டுகிறது</translation>
+ </message>
</context>
<context>
<name>TransactionTableModel</name>
@@ -2257,21 +2774,161 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>தேதி</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>வகை</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>லேபிள்</translation>
</message>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>மேலும் %n பிளாக்க்கிற்கு திறந்துவைக்கப்பட்டுள்ளது</numerusform><numerusform>மேலும் %n பிளாக்குகளில் திறந்துவைக்கப்பட்டுள்ளது</numerusform></translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>உறுதிப்படுத்தப்படாதது</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation>கைவிடப்பட்டது</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>உறுதிப்படுத்துகிறது (%1 ன் %2 பரிந்துரைக்கப்பட்ட உறுதிப்படுத்தல்கல்)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation>முரண்பாடு</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>உருவாக்கப்பட்டது ஆனால் ஏற்றுக்கொள்ளப்படவில்லை</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>உடன் பெறப்பட்டது</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>பெறப்பட்டது இதனிடமிருந்து</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>அனுப்பப்பட்டது</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>உனக்கே பணம் செலுத்து</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>மைன் செய்யப்பட்டது</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>பார்க்க-மட்டும்</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(பொருந்தாது)</translation>
+ </message>
<message>
<source>(no label)</source>
<translation>(லேபிள் இல்லை)</translation>
</message>
- </context>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>பரிவர்த்தனையின் நிலை. உறுதிப்படுத்தல்களின் எண்ணிக்கையைக் காட்ட இந்த உள்ளீட்டில் பார்க்க.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>பரிவர்த்தனை பெறப்பட்ட தேதி மற்றும் நேரம்.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>பரிவர்த்தனையின் வகை.</translation>
+ </message>
+ <message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>இந்த பரிவர்த்தனையில் பார்க்க மட்டும் உள்ள முகவரி உள்ளதா இல்லையா.</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>பயனர்-வரையறுக்கப்பட்ட நோக்கம்/பரிவர்த்தனையின் நோக்கம்.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>மீதியிலிருந்து நீக்கப்பட்ட அல்லது மீதிக்கு சேர்க்கப்பட்ட தொகை</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>அனைத்தும்</translation>
+ </message>
+ <message>
<source>Today</source>
<translation>இன்று</translation>
</message>
<message>
+ <source>This week</source>
+ <translation>இந்த வாரம்</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>இந்த மாதம்</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>சென்ற மாதம்</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>இந்த வருடம்</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>எல்லை...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>உடன் பெறப்பட்டது</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>அனுப்பப்பட்டது</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>உங்களுக்கே</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>மைன் செய்யப்பட்டது</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>மற்ற</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>தேடுவதற்காக முகவரி, பரிவர்த்தனை ஐடி அல்லது லேபிளை உள்ளிடவும்</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>குறைந்தபட்ச தொகை</translation>
+ </message>
+ <message>
+ <source>Abandon transaction</source>
+ <translation>பரிவர்த்தனையை கைவிடவும்</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>பரிவர்த்தனையின் கட்டணத்தை உயர்த்துக</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>முகவரி முகவரியை நகலெடுக்கவும்</translation>
</message>
@@ -2288,6 +2945,26 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>பரிவர்த்தனை ஐடியை நகலெடு</translation>
</message>
<message>
+ <source>Copy raw transaction</source>
+ <translation>மூல பரிவர்த்தனையை காபி செய்</translation>
+ </message>
+ <message>
+ <source>Copy full transaction details</source>
+ <translation>முழு பரிவர்த்தனை விவரங்களையும் காபி செய்</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>லேபிளை திருத்து</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>பரிவர்த்தனையின் விவரங்களைக் காட்டு</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>பரிவர்த்தனையின் வரலாற்றை எக்ஸ்போர்ட் செய்</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>கமா பிரிக்கப்பட்ட கோப்பு</translation>
</message>
@@ -2296,10 +2973,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>உறுதியாக</translation>
</message>
<message>
+ <source>Watch-only</source>
+ <translation>பார்க்க-மட்டும்</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>தேதி</translation>
</message>
<message>
+ <source>Type</source>
+ <translation>வகை</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>லேபிள்</translation>
</message>
@@ -2308,26 +2993,110 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>முகவரி</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ஐடி</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>ஏற்றுமதி தோல்வியடைந்தது</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>பரிவர்த்தனை வரலாற்றை %1 க்கு சேவ் செய்வதில் பிழை ஏற்பட்டது.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>எக்ஸ்போர்ட் வெற்றிகரமாக முடிவடைந்தது</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>பரிவர்த்தனை வரலாறு வெற்றிகரமாக %1 க்கு சேவ் செய்யப்பட்டது.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>எல்லை:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>இதற்கு அனுப்பு</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
- </context>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation>அளவுகளைக் காண்பிக்கும் அலகு. மற்றொரு அலகு தேர்ந்தெடுக்க கிளிக் செய்யவும்.</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
- </context>
+ <message>
+ <source>Close wallet</source>
+ <translation>வாலட்டை மூடு</translation>
+ </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>
+ </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>
+</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>எந்த வாலட்டும் லோட் செய்யப்படவில்லை.</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
<source>Send Coins</source>
<translation>நாணயங்களை அனுப்பவும்</translation>
</message>
- </context>
+ <message>
+ <source>Fee bump error</source>
+ <translation>கட்டணம் ஏற்றத்தில் பிழை</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>பரிவர்த்தனை கட்டணம் அதிகரித்தல் தோல்வியடைந்தது</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>கட்டணத்தை அதிகரிக்க விரும்புகிறீர்களா?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>தற்போதைய கட்டணம்:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>அதிகரித்தல்:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>புதிய கட்டணம்:</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation>கட்டண ஏற்றத்தை உறுதிப்படுத்தவும்</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>பரிவர்த்தனையில் கையொப்பமிட முடியவில்லை.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>பரிவர்த்தனையை கமிட் செய்ய முடியவில்லை</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>இயல்புநிலை வாலட்</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
@@ -2338,12 +3107,424 @@ 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>
- </context>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>பேக்அப் வாலட்</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>வாலட் தகவல் (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>பேக்அப் தோல்வியுற்றது</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>வாலட் தகவல்களை %1 சேவ் செய்வதில் பிழை ஏற்பட்டது</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>பேக்அப் வெற்றிகரமாக முடிவடைந்தது</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>வாலட் தகவல்கள் வெற்றிகரமாக %1 சேவ் செய்யப்பட்டது.</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>ரத்து</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>எம்ஐடி சாப்ட்வேர் விதிமுறைகளின் கீழ் பகிர்ந்தளிக்கப்படுகிறது, அதனுடன் கொடுக்கப்பட்டுள்ள %s அல்லது %s பைல் ஐ பார்க்கவும்</translation>
+ </message>
+ <message>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation>ப்ரூனிங் குறைந்தபட்சம் %d MiB க்கு கீழே கட்டமைக்கப்பட்டுள்ளது. அதிக எண்ணிக்கையைப் பயன்படுத்தவும்.</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>ப்ரூன்: கடைசி வாலட் ஒத்திசைவு ப்ரூன் தரவுக்கு அப்பாற்பட்டது. நீங்கள் -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>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>HTTP சேவையகத்தைத் தொடங்க முடியவில்லை. விவரங்களுக்கு debug.log ஐ பார்க்கவும்.</translation>
+ </message>
+ <message>
+ <source>The %s developers</source>
+ <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>
+ <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>
+ </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>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>%s பயனுள்ளதாக இருந்தால் தயவுசெய்து பங்களியுங்கள். இந்த சாஃட்வேர் பற்றிய கூடுதல் தகவலுக்கு %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>பிளாக் டேட்டாபேசில் எதிர்காலத்தில் இருந்து தோன்றும் ஒரு பிளாக் உள்ளது. இது உங்கள் கணினியின் தேதி மற்றும் நேரம் தவறாக அமைக்கப்பட்டதன் காரணமாக இருக்கலாம். உங்கள் கணினியின் தேதி மற்றும் நேரம் சரியானதாக இருந்தால் மட்டுமே பிளாக் டேட்டாபேசை மீண்டும் உருவாக்கவும்</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>இது ஒரு வெளியீட்டுக்கு முந்தைய சோதனை கட்டமைப்பாகும் - உங்கள் சொந்த ஆபத்தில் பயன்படுத்தவும் - மைனிங் அல்லது வணிக பயன்பாடுகளுக்கு பயன்படுத்த வேண்டாம்</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>இது பரிவர்த்தனைக் கட்டணம் ஆகும் அதன் வேறுபாடு தூசியை விட சிறியதாக இருந்தால் நீங்கள் அதை நிராகரிக்கலாம்.</translation>
+ </message>
+ <message>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>பிளாக்களை இயக்க முடியவில்லை. -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>ப்ரீ-போர்க் நிலைக்கு டேட்டாபேசை ரீவைண்ட் செய்ய முடியவில்லை. நீங்கள் பிளாக்செயினை மீண்டும் டவுன்லோட் செய்ய வேண்டும்</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>எச்சரிக்கை: பிட்காயின் நெட்ஒர்க் முழுமையாக ஒப்புக்கொள்ளவில்லை! சில மைனர்கள் சிக்கல்களை சந்திப்பதாகத் தெரிகிறது.</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>எச்சரிக்கை: நாங்கள் எங்கள் பீர்களுடன் முழுமையாக உடன்படுவதாகத் தெரியவில்லை! நீங்கள் அப்க்ரேட் செய்ய வேண்டியிருக்கலாம், அல்லது மற்ற நோடுகள் அப்க்ரேட் செய்ய வேண்டியிருக்கலாம்.</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>
+ <message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>தீர்க்க முடியாது -%s முகவரி: '%s'</translation>
+ </message>
+ <message>
+ <source>Change index out of range</source>
+ <translation>குறியீட்டை வரம்பிற்கு வெளியே மாற்றவும்</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>பதிப்புரிமை (ப) %i-%i</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation>சிதைந்த பிளாக் டேட்டாபேஸ் கண்டறியப்பட்டது</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>இப்போது பிளாக் டேட்டாபேஸை மீண்டும் உருவாக்க விரும்புகிறீர்களா?</translation>
+ </message>
+ <message>
+ <source>Error initializing block database</source>
+ <translation>பிளாக் டேட்டாபேஸ் துவக்குவதில் பிழை!</translation>
+ </message>
+ <message>
+ <source>Error initializing wallet database environment %s!</source>
+ <translation>வாலட் டேட்டாபேஸ் சூழல் %s துவக்குவதில் பிழை!</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>%s லோட் செய்வதில் பிழை</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>லோட் செய்வதில் பிழை %s: ப்ரைவேட் கீஸ் உருவாக்கத்தின் போது மட்டுமே முடக்கப்படும்</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>லோட் செய்வதில் பிழை %s: வாலட் சிதைந்தது</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>லோட் செய்வதில் பிழை %s: வாலட்டிற்கு %s புதிய பதிப்பு தேவை</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation>பிளாக் டேட்டாபேஸை லோட் செய்வதில் பிழை</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation>பிளாக் டேட்டாபேஸை திறப்பதில் பிழை</translation>
+ </message>
+ <message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation>எந்த போர்டிலும் கேட்க முடியவில்லை. இதை நீங்கள் கேட்க விரும்பினால் -லிசென்= 0 வை பயன்படுத்தவும்.</translation>
+ </message>
+ <message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>துவக்கத்தின் போது வாலட்டை ரீஸ்கேன் செய்வதில் தோல்வி</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>இம்போர்ட் செய்யப்படுகிறது...</translation>
+ </message>
+ <message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>தவறான பி2பி அனுமதி: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>-%s=&lt;amount&gt;: '%s' கான தவறான தொகை</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation>-discardfee கான தவறான தொகை=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation>தவறான தொகை -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>குறிப்பிடப்பட்ட பிளாக் டைரக்டரி "%s" இல்லை.</translation>
+ </message>
+ <message>
+ <source>Unknown address type '%s'</source>
+ <translation>தெரியாத முகவரி வகை '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation>தெரியாத மாற்று வகை '%s'</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>txindex தகவல்தளத்தை மேம்படுத்துதல்</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>பி2பி முகவரிகள் லோட் செய்யப்படுகிறது...</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is too low!</source>
+ <translation>பிழை: டிஸ்க் ஸ்பேஸ் மிகக் குறைவாக உள்ளது!</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>தடைப்பட்டியல் லோட் செய்யப்படுகிறது...</translation>
+ </message>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation>போதுமான ஃபைல் டிஸ்கிரிப்டார் கிடைக்கவில்லை.</translation>
+ </message>
+ <message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation>ப்ரூனை எதிர்மறை மதிப்புகளுடன் கட்டமைக்க முடியாது.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation>ப்ரூன் பயன்முறை -txindex உடன் பொருந்தாது.</translation>
+ </message>
+ <message>
+ <source>Replaying blocks...</source>
+ <translation>பிளாக்குகள் மீண்டும் இயக்குகிறது...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>பிளாக்குகள் ரீவைன்ட் செய்யப்படுகிறது...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation>சோர்ஸ் கோட் %s இலிருந்து கிடைக்கிறது.</translation>
+ </message>
+ <message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>பரிவர்த்தனையின் கட்டணம் மற்றும் மீதிபண கணக்கீடு தோல்வியுற்றது</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation>கீஸை உருவாக்க முடியவில்லை</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>UTXO தகவல்தளம் மேம்படுத்தப்படுகிறது</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>பிளாக்குகள் சரிபார்க்கப்படுகிறது...</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>வாலட் மீண்டும் எழுத படவேண்டும்: முடிக்க %s ஐ மறுதொடக்கம் செய்யுங்கள்</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</source>
+ <translation>கட்டணம் கழிக்கப்பட்ட பின்னர் பரிவர்த்தனை தொகை அனுப்ப மிகவும் சிறியது</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation>டேட்டாபேசிலிருந்து படிப்பதில் பிழை, ஷட் டவுன் செய்யப்படுகிறது.</translation>
+ </message>
+ <message>
+ <source>Error upgrading chainstate database</source>
+ <translation>செயின்ஸ்டேட் தகவல்தளத்தை மேம்படுத்துவதில் பிழை</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is low for %s</source>
+ <translation>பிழை: டிஸ்க் ஸ்பேஸ் %s க்கு குறைவாக உள்ளது</translation>
+ </message>
+ <message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>தவறான -onion முகவரி அல்லது ஹோஸ்ட்நேம்: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>தவறான -proxy முகவரி அல்லது ஹோஸ்ட்நேம்: '%s'</translation>
+ </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>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>ப்ரூன் பயன்முறை -blockfilterindex உடன் பொருந்தாது.</translation>
+ </message>
+ <message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation>கணினி வரம்புகள் காரணமாக -maxconnections %d இலிருந்து %d ஆகக் குறைக்கப்படுகிறது.</translation>
+ </message>
+ <message>
+ <source>Section [%s] is not recognized.</source>
+ <translation>பிரிவு [%s] கண்டறியப்படவில்லை.</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation>கையொப்பமிடும் பரிவர்த்தனை தோல்வியடைந்தது</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>குறிப்பிடப்பட்ட -walletdir "%s" இல்லை</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>குறிப்பிடப்பட்ட -walletdir "%s" ஒரு டைரக்டரி அல்ல</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation>கட்டணம் செலுத்த பரிவர்த்தனை தொகை மிகவும் குறைவு</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>இது ஒரு ஆராய்ச்சி மென்பொருள்.</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>பரிவர்த்தனை தொகை மிகக் குறைவு</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>பரிவர்த்தனை மிகப் பெரிது</translation>
+ </message>
+ <message>
+ <source>Unable to create the PID file '%s': %s</source>
+ <translation>PID பைலை உருவாக்க முடியவில்லை '%s': %s</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation>ஆரம்ப கீகளை உருவாக்க முடியவில்லை</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>வாலட்(களை) சரிபார்க்கிறது...</translation>
+ </message>
+ <message>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <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>
+ <message>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>கட்டண மதிப்பீடுகள் இல்லாதபோது நீங்கள் செலுத்த வேண்டிய பரிவர்த்தனைக் கட்டணம் இதுவாகும்.</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation>%s மிக அதிகமாக அமைக்கப்பட்டுள்ளது!</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>நெட்ஒர்க் த்ரெட் ஆரம்பமாகிறது...</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>ஒவ்வொரு பரிவர்த்தனைக்கும் நீங்கள் செலுத்த வேண்டிய குறைந்தபட்ச பரிவர்த்தனைக் கட்டணம் இதுவாகும்.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>நீங்கள் ஒரு பரிவர்த்தனையை அனுப்பும்பொழுது நீங்கள் செலுத்த வேண்டிய பரிவர்த்தனைக் கட்டணம் இதுவாகும்.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>பரிவர்த்தனை தொகை எதிர்மறையாக இருக்கக்கூடாது</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>பரிவர்த்தனைக்கு குறைந்தபட்சம் ஒரு பெறுநர் இருக்க வேண்டும்</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation>போதுமான பணம் இல்லை</translation>
</message>
- </context>
+ <message>
+ <source>Loading block index...</source>
+ <translation>பிளாக் குறியீடு லோட் செய்யபடுகிறது...</translation>
+ </message>
+ <message>
+ <source>Loading wallet...</source>
+ <translation>வாலட் லோடிங் செய்யப்படுகிறது...</translation>
+ </message>
+ <message>
+ <source>Cannot downgrade wallet</source>
+ <translation>வாலட்டை தரமிறக்க முடியாது</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>ரீஸ்கேன்னிங்...</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation>லோடிங் முடிந்தது</translation>
+ </message>
+</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_te.ts b/src/qt/locale/bitcoin_te.ts
index c52827cea0..6080d2e4dc 100644
--- a/src/qt/locale/bitcoin_te.ts
+++ b/src/qt/locale/bitcoin_te.ts
@@ -31,11 +31,11 @@
</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>
- <translation>ప్రస్తుతం ఉన్న సమాచారాన్ని ఫైల్ లోనికి ఎగుమతి చేసుకోండి </translation>
+ <translation>ప్రస్తుతం ఉన్న సమాచారాన్ని ఫైల్ లోనికి ఎగుమతి చేసుకోండి</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -51,7 +51,7 @@
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>నాణెం అందుకోవటానికి చిరునామాను ఎంచుకోండి </translation>
+ <translation>నాణెం అందుకోవటానికి చిరునామాను ఎంచుకోండి</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -325,9 +325,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -432,7 +429,7 @@
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>ప్రస్తుతం ఉన్న సమాచారాన్ని ఫైల్ లోనికి ఎగుమతి చేసుకోండి </translation>
+ <translation>ప్రస్తుతం ఉన్న సమాచారాన్ని ఫైల్ లోనికి ఎగుమతి చేసుకోండి</translation>
</message>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_th.ts b/src/qt/locale/bitcoin_th.ts
index cfb4b298f3..e28c987893 100644
--- a/src/qt/locale/bitcoin_th.ts
+++ b/src/qt/locale/bitcoin_th.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>
@@ -128,6 +132,10 @@
<translation>ทำซ้ำข้อความรหัสใหม่</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>ดูวลี</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>กระเป๋าสตางค์ เข้ารหัส</translation>
</message>
@@ -151,6 +159,14 @@
<source>Change passphrase</source>
<translation>เปลี่ยน ข้อความรหัสผ่าน</translation>
</message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>ยืนยันการเข้ารหัสกระเป๋าเงิน</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>คุณแน่ใจหรือว่าต้องการเข้ารหัสกระเป๋าเงินของคุณ?</translation>
+ </message>
</context>
<context>
<name>BanTableModel</name>
@@ -238,6 +254,10 @@
<translation>เปิด &amp;URI</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>สร้าง Wallet</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>กำลังทำดัชนี ที่เก็บบล็อก ใหม่ ในดิสก์...</translation>
</message>
@@ -254,14 +274,6 @@
<translation>เปลี่ยนรหัสผ่านที่ใช้สำหรับการเข้ารหัสกระเป๋าเงิน</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;หน้าต่าง Debug</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>เปิด แผลงควบคุม debugging และ diagnostic</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;ยืนยันข้อความ...</translation>
</message>
@@ -322,10 +334,6 @@
<translation>แสดงรายการ ที่เก็บเงินที่จะรับ bitcoin เข้า และป้ายชื่อ ที่ใช้ไปแล้ว</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>เปิด bitcoin: URI หรือ การเรียกเก็บเงิน (การเรียกให้ชำระเงิน)</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;ตัวเลือก Command-line</translation>
</message>
@@ -435,7 +443,11 @@
<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>
- </context>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>เกิดข้อผิดพลาดร้ายแรง Bitcoin ไม่สามารถดำเนินการต่อได้อย่างปลอดภัยอีกต่อไปและจะยกเลิก</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -507,6 +519,22 @@
<translation>ยืนยันแล้ว</translation>
</message>
<message>
+ <source>Copy address</source>
+ <translation>คัดลอกที่อยู่</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>คัดลอกป้ายกำกับ</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>คัดลอกจำนวนเงิน</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>คัดลอก ID ธุรกรรม</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(ไม่มีฉลาก)</translation>
</message>
@@ -516,7 +544,19 @@
</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>เข้ารหัสกระเป๋าเงิน</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>ทำกระเป๋าเงินเปล่า</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>สร้าง</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -570,10 +610,6 @@
<translation>เวอร์ชั่น</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-บิท)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>เกี่ยวกับ %1</translation>
</message>
@@ -609,6 +645,14 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>ประมาณ %1 GB ของข้อมูลจะเก็บในไดเร็กทอรี่</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>The wallet เก็บใว้ในไดเร็กทอรี่</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" cannot be created.</source>
<translation>ข้อผิดพลาด: ไดเร็กทอรี่ข้อมูลที่ต้องการ "%1" ไม่สามารถสร้างได้</translation>
</message>
@@ -635,22 +679,10 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>เปิด URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>เปิด การเรียกการชำระเงิน จาก URI หรือ ไฟล์</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>เลือก ไฟล์การเรียกการชำระเงิน</translation>
- </message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
</context>
@@ -825,7 +857,15 @@
<source>&amp;Label:</source>
<translation>&amp;ชื่อ:</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>คัดลอกป้ายกำกับ</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>คัดลอกจำนวนเงิน</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -895,6 +935,10 @@
<translation>เศษ:</translation>
</message>
<message>
+ <source>Copy amount</source>
+ <translation>คัดลอกจำนวนเงิน</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(ไม่มีฉลาก)</translation>
</message>
@@ -907,9 +951,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -950,6 +991,22 @@
<context>
<name>TransactionView</name>
<message>
+ <source>Copy address</source>
+ <translation>คัดลอกที่อยู่</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>คัดลอกป้ายกำกับ</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>คัดลอกจำนวนเงิน</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>คัดลอก ID ธุรกรรม</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>ไฟล์ที่คั่นด้วยจุลภาค (* .csv)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts
index a4a9f9e6f4..1677446993 100644
--- a/src/qt/locale/bitcoin_tr.ts
+++ b/src/qt/locale/bitcoin_tr.ts
@@ -70,6 +70,10 @@
<translation>Bunlar ödeme göndermek için gereken Bitcoin adreslerinizdir. Para göndermeden önce her zaman miktarı ve alıcı adresi kontrol edin.</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>Adresi Kopyala</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Yeni parolayı tekrarla</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Show passphrase</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Cüzdanı Şifrele</translation>
</message>
@@ -172,10 +180,30 @@
<translation>Cüzdan Şifrelendi</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>Cüzdanınızı şifrelemenin, bitcoinlerinizin bilgisayara bulaşan kötücül bir yazılım tarafından çalınmaya karşı tamamen koruyamayacağını unutmayınız.</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>ÖNEMLİ: Yeni oluşturduğunuz şifrelenmiş cüzdan dosyasını önceki yedeklenmiş cüzdan dosyasıyla değiştirmeniz gerekmektedir. Güvenlik sebeplerinden dolayı yeni, şifrelenmiş cüzdanınızı kullanmaya başlar başlamaz önceki şifrelenmemiş cüzdan yedekleri kullanılmaz hale gelecektir.</translation>
</message>
@@ -298,6 +326,14 @@
<translation>URI'yi aç</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>Cüzdan:</translation>
</message>
@@ -338,14 +374,6 @@
<translation>Cüzdan şifrelemesi için kullanılan parolayı değiştir</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Hata ayıklama penceresi</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Hata giderme konsolunu aç</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>Onay mesajı...</translation>
</message>
@@ -406,10 +434,6 @@
<translation>Kullanılan alış adreslerinin ve etiketlerinin listesini göster</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Bir bitcoin: bağlantısı ya da ödeme talebi aç</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>Komut satırı ayarları</translation>
</message>
@@ -458,6 +482,26 @@
<translation>Güncel</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>Cüzdanı Aç</translation>
</message>
@@ -482,6 +526,10 @@
<translation>varsayılan cüzdan</translation>
</message>
<message>
+ <source>No wallets available</source>
+ <translation>No wallets available</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>Pencere</translation>
</message>
@@ -490,6 +538,14 @@
<translation>Küçült</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 istemci</translation>
</message>
@@ -506,6 +562,10 @@
<translation>Hata: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Warning: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Tarih %1</translation>
@@ -557,6 +617,10 @@
<translation>HD anahtar üretimi &lt;b&gt;pasif&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>Cüzdan &lt;b&gt;şifrelenmiştir&lt;/b&gt; ve şu anda &lt;b&gt;kilidi açıktır&lt;/b&gt;</translation>
</message>
@@ -722,10 +786,58 @@
</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>
@@ -811,10 +923,6 @@
<translation>versiyon</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>Hakkında %1</translation>
</message>
@@ -838,6 +946,10 @@
<translation>Bu programın ilk kez başlatılmasından dolayı %1 yazılımının verilerini nerede saklayacağını seçebilirsiniz.</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>Bu başlangıç senkronizasyonu çok zorlayıcıdır ve bilgisayarınızdaki daha önce fark edilmemiş olan donanım sorunlarını ortaya çıkarabilir. %1'i her çalıştırdığınızda, kaldığı yerden devam edecektir.</translation>
</message>
@@ -859,6 +971,10 @@
</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>Bu dizinde en az %1 GB lık veri depolanacak ve zamanla büyüyecek.</translation>
</message>
@@ -890,7 +1006,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(gereken %n GB alandan)</numerusform><numerusform>(gereken %n GB alandan)</numerusform></translation>
</message>
- </context>
+ <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>
@@ -899,7 +1019,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>Son işlemler henüz görünmeyebilir ve bu nedenle cüzdanınızın bakiyesi yanlış olabilir. Bu bilgiler, aşağıda detaylandırıldığı gibi, cüzdanınız bitcoin ağı ile senkronizasyonunu tamamladığında doğru olacaktır. </translation>
+ <translation>Son işlemler henüz görünmeyebilir ve bu nedenle cüzdanınızın bakiyesi yanlış olabilir. Bu bilgiler, aşağıda detaylandırıldığı gibi, cüzdanınız bitcoin ağı ile senkronizasyonunu tamamladığında doğru olacaktır.</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
@@ -937,37 +1057,49 @@
<source>Hide</source>
<translation>Gizle</translation>
</message>
- </context>
-<context>
- <name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>URI Aç</translation>
+ <source>Esc</source>
+ <translation>Esc</translation>
</message>
<message>
- <source>Open payment request from URI or file</source>
- <translation>Dosyadan veya URI'den ödeme talebi aç</translation>
+ <source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
+ <translation>%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>URI:</source>
- <translation>URI:</translation>
+ <source>Unknown. Syncing Headers (%1, %2%)...</source>
+ <translation>Unknown. Syncing Headers (%1, %2%)...</translation>
</message>
+</context>
+<context>
+ <name>OpenURIDialog</name>
<message>
- <source>Select payment request file</source>
- <translation>Ödeme talebi dosyasını seç</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Open bitcoin URI</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Açılacak ödeme talebi dosyasını seç</translation>
+ <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>varsayılan cüzdan</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>
@@ -1059,6 +1191,10 @@
<translation>Bu ayarları geri değiştirmek tüm blok zinciri'nin indirilmesini gerektirir.</translation>
</message>
<message>
+ <source>MiB</source>
+ <translation>MiB</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = otomatik, &lt;0 = bu kadar çekirdeği kullanma)</translation>
</message>
@@ -1183,6 +1319,10 @@
<translation>&amp;Üçüncü parti işlem URL'leri</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>Tamam</translation>
</message>
@@ -1329,8 +1469,16 @@
<translation>'bitcoin://' geçerli bir protokol değil. Onun yerine 'bitcoin:' kullanınız.</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Ödeme isteği URL'si hatalı: %1</translation>
+ <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>
@@ -1344,66 +1492,6 @@
<source>Payment request file handling</source>
<translation>Ödeme talebi dosyası yönetimi</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Ödeme talebi dosyası okunamıyor! Bunun nedeni geçersiz bir ödeme talebi dosyası olabilir.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Ödeme talebi reddedildi</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Ödeme talebi ağı, istemci ağıyla eşleşmiyor.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Ödeme talebinin geçerlilik süresi bitti.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Ödeme talebi başlatılmadı.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Özel ödeme betiklerine, doğrulanmamış ödeme talepleri desteklenmez.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Geçersiz ödeme talebi.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Talep edilen %1 ödeme tutarı çok küçüktür (toz olarak kabul edilir).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>%1 adresinden geri ödeme</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>%1 ödeme talebi çok büyük (%2 bayt, üst sınır %3 bayt).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>%1 ile iletişimde hata: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Ödeme talebi ayrıştırılamaz!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>%1 sunucusundan hatalı yanıt</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Ağ hatası</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Ödeme kabul edildi</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1520,7 +1608,7 @@
</message>
<message>
<source>Error: Cannot parse configuration file: %1.</source>
- <translation>Hata: %1 yapılandırma dosyası ayrıştırılamadı. </translation>
+ <translation>Hata: %1 yapılandırma dosyası ayrıştırılamadı.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1554,6 +1642,10 @@
<translation>URI'nin QR koduna kodlanmasında hata oluştu.</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>QR kodu kaydet</translation>
</message>
@@ -1577,10 +1669,6 @@
<translation>&amp;Bilgi</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Hata giderme penceresi</translation>
- </message>
- <message>
<source>General</source>
<translation>Genel</translation>
</message>
@@ -1593,6 +1681,18 @@
<translation>Veri konumu</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>Başlangıç zamanı</translation>
</message>
@@ -1689,6 +1789,10 @@
<translation>Kullanıcı Yazılımı</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>Güncel veri klasöründen %1 hata ayıklama kütük dosyasını açar. Büyük kütük dosyaları için bu birkaç saniye alabilir.</translation>
</message>
@@ -1900,6 +2004,18 @@
<translation>Seçiminize dayalı talep edilecek tutar. Belli bir tutar talep etmemek için bunu boş bırakın veya sıfır değerini kullanın.</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>Formdaki tüm alanları temizle.</translation>
</message>
@@ -1908,6 +2024,10 @@
<translation>Temizle</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>Yerli segwit (Bech32) adresi oluştur</translation>
</message>
@@ -2093,12 +2213,20 @@
<translation>Seçiniz...</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>Uyarı: Ücret tahmini şu anda mümkün değildir.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>ücret-ayarlarını-küçült</translation>
+ <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>
@@ -2137,10 +2265,30 @@
<translation>Toz:</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>Doğrulama süresi hedefi:</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>Hepsini sil</translation>
</message>
@@ -2189,18 +2337,46 @@
<translation>%1 (%2 blok)</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'den %2'e</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>Göndermek istediğinize emin misiniz?</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>ya da</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>Lütfen, işleminizi gözden geçirin.</translation>
</message>
@@ -2209,14 +2385,42 @@
<translation>Gönderim ücreti</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>Toplam Tutar</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>Coin gönderimini onaylayın</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Alıcı adresi geçerli değildir. Lütfen tekrar kontrol ediniz.</translation>
</message>
@@ -2241,10 +2445,6 @@
<translation>İşlem oluşturma başarısız!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>İşlem şu nedenden dolayı reddedildi: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>%1 tutarından yüksek bir ücret saçma derecede yüksek bir ücret olarak kabul edilir.</translation>
</message>
@@ -2296,10 +2496,6 @@
<translation>Önceden kullanılmış adres seç</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Bu, normal bir ödemedir.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Ödemenin yollanacağı Bitcoin adresi</translation>
</message>
@@ -2320,6 +2516,10 @@
<translation>Bu ögeyi kaldır</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>Ücret yollanan tutardan alınacaktır. Alıcı tutar alanına girdiğinizden daha az bitcoin alacaktır. Eğer birden çok alıcı seçiliyse ücret eşit olarak bölünecektir.</translation>
</message>
@@ -2359,17 +2559,6 @@
<source>Memo:</source>
<translation>Not:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Adres defterinize eklemek için bu adrese bir etiket giriniz</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Evet</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2457,6 +2646,14 @@
<translation>İletinin imzalanmasında kullanılan Bitcoin adresi</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>Belirtilen Bitcoin adresi ile imzalandığını doğrulamak için iletiyi kontrol et</translation>
</message>
@@ -2489,6 +2686,10 @@
<translation>Cüzdan kilidinin açılması iptal edildi.</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>Girilen adres için özel anahtar mevcut değildir.</translation>
</message>
@@ -2663,6 +2864,10 @@
<translation>Çıktı indeksi</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation> (Certificate was not verified)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Tüccar</translation>
</message>
@@ -2985,7 +3190,15 @@
<source>Close wallet</source>
<translation>Cüzdanı Kapat</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>
+</context>
<context>
<name>WalletFrame</name>
<message>
@@ -3000,6 +3213,10 @@
<translation>Coin gönder</translation>
</message>
<message>
+ <source>Fee bump error</source>
+ <translation>Fee bump error</translation>
+ </message>
+ <message>
<source>Increasing transaction fee failed</source>
<translation>İşlem ücreti artırma başarısız oldu</translation>
</message>
@@ -3008,6 +3225,10 @@
<translation>Ücreti artırmak istiyor musunuz?</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>Şimdiki ücret:</translation>
</message>
@@ -3020,6 +3241,18 @@
<translation>Yeni ücret:</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>İşlem imzalanamıyor.</translation>
</message>
@@ -3086,10 +3319,6 @@
<translation>Budama: son cüzdan eşleşmesi budanmış verilerin ötesine gitmektedir. -reindex kullanmanız gerekmektedir (Budanmış düğüm ise tüm blok zincirini tekrar indirmeniz gerekir.)</translation>
</message>
<message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Tekrar taramalar budanmış kipte mümkün değildir. Tüm blok zincirini tekrar indirecek olan -reindex seçeneğini kullanmanız gerekecektir.</translation>
- </message>
- <message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>Hata: Ölümcül dahili bir hata meydana geldi, ayrıntılar için debug.log dosyasına bakınız</translation>
</message>
@@ -3106,10 +3335,18 @@
<translation>%s ekip</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>%s veri dizininde kilit elde edilemedi. %s muhtemelen hâlihazırda çalışmaktadır.</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>%s dosyasının okunması sırasında bir hata meydana geldi! Tüm anahtarlar doğru bir şekilde okundu, ancak işlem verileri ya da adres defteri ögeleri hatalı veya eksik olabilir.</translation>
</message>
@@ -3130,6 +3367,14 @@
<translation>Bu kararlı sürümden önceki bir deneme sürümüdür. - risklerini bilerek kullanma sorumluluğu sizdedir - bitcoin oluşturmak ya da ticari uygulamalar için kullanmayınız</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>Veritabanını çatallama öncesi duruma geri sarmak mümkün değil. Blok zincirini tekrar indirmeniz gerekmektedir</translation>
</message>
@@ -3162,6 +3407,10 @@
<translation>Aralık dışında değişiklik indeksi</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>
@@ -3170,6 +3419,14 @@
<translation>Bozuk blok veritabanı tespit edildi</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>Blok veritabanını şimdi yeniden inşa etmek istiyor musunuz?</translation>
</message>
@@ -3227,6 +3484,10 @@
<translation>Başlatma sınaması başarısız oldu. %s kapatılıyor.</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>-%s=&lt;tutar&gt; için geçersiz tutar: '%s'</translation>
</message>
@@ -3236,13 +3497,21 @@
</message>
<message>
<source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation> -fallbackfee=&lt;tutar&gt; için geçersiz tutar: '%s'</translation>
+ <translation>-fallbackfee=&lt;tutar&gt; için geçersiz tutar: '%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>Bilinmeyen adres türü '%s'</translation>
</message>
<message>
+ <source>Unknown change type '%s'</source>
+ <translation>Unknown change type '%s'</translation>
+ </message>
+ <message>
<source>Upgrading txindex database</source>
<translation>txindex veritabanı yükseltiliyor</translation>
</message>
@@ -3251,6 +3520,10 @@
<translation>P2P adresleri yükleniyor...</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>Ban listesi yükleniyor...</translation>
</message>
@@ -3335,6 +3608,10 @@
<translation>Zincirdurumu veritabanı yükseltme hatası</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>Hatalı -onion adresi ya da host adı: '%s'</translation>
</message>
@@ -3355,10 +3632,18 @@
<translation>-whitebind: '%s' ile bir port belirtilmesi lazımdır</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>Sistem sınırlamaları sebebiyle -maxconnections %d değerinden %d değerine düşürülmüştür.</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>İşlemin imzalanması başarısız oldu</translation>
</message>
@@ -3375,6 +3660,12 @@
<translation>Belirtilen -walletdir "%s" bir dizin değildir</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>İşlemdeki bitcoin tutarı ücreti ödemek için çok düşük</translation>
</message>
@@ -3395,10 +3686,18 @@
<translation>Bu bilgisayarda %s ögesine bağlanılamadı (bağlanma %s hatasını verdi)</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>Başlangıç anahtarları üretilemiyor</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>Unknown -blockfilterindex value %s.</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>Cüzdan(lar) onaylanıyor...</translation>
</message>
@@ -3419,10 +3718,6 @@
<translation>İşlem ücret tahminleri mevcut olmadığında ödeyebileceğiniz işlem ücreti budur.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Bu ürün OpenSSL Projesi tarafından geliştirilen OpenSSL araç takımınında kullanılmak üzere yazılan yazılımları %s Eric Young tarafından yazılmış şifreleme yazılımını ve Thomas Bernard tarafından yazılmış UPnP yazılımını içerir.</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ğ sürümü zincirinin toplam boyutu (%i) en yüksek boyutu geçmektedir (%i). Kullanıcı aracı açıklamasının sayısı veya boyutunu azaltınız.</translation>
</message>
@@ -3475,10 +3770,18 @@
<translation>Yetersiz Bakiye</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>İşlem ücreti hesaplama başarısız. Fallbackfee özelliği devre dışı. Lütfen bir kaç blok için bekleyiniz yada -fallbackfee özelliğini aktif ediniz.</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>Veriler klasöre yazılamıyor '%s'; yetkilendirmeyi kontrol edin.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_tr_TR.ts b/src/qt/locale/bitcoin_tr_TR.ts
deleted file mode 100644
index bf2dae99dc..0000000000
--- a/src/qt/locale/bitcoin_tr_TR.ts
+++ /dev/null
@@ -1,1518 +0,0 @@
-<TS language="tr_TR" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Adresi veya etiketi düzenlemek için sağ tıklayın</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Yeni adres oluştur</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Yeni</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Seçili adresi panoya kopyala</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Kopyala</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>K&amp;apat</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Seçili adresi listeden sil</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>Seçili sekmedeki veriyi dosya olarak dışa aktar</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Dışa Aktar</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Sil</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>koinlerin gönderileceği adresi seçin</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Alıcı adresi seçiniz</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>Seçim</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Gönderilen Adresler</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Alınan 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 ödeme göndermek için gereken Bitcoin adreslerinizdir. Para göndermeden önce her zaman miktarı ve alıcı adresi kontrol edin.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Bunlar ödeme almak için kullanılacak Bitcoin adreslerinizdir. Her işlem için yeni bir ödeme alma adresi kullanılması tavsiye edilir.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>Adresi Kopyala</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Kopyala ve Etiketle</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>Düzenle</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Adres Listesini Dışar Aktar</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Virgül ile ayrılmış dosya (*.csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Dışa Aktarma Başarısız</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Adres listesini %1'e kaydederken bir hata oluştu. Lütfen tekrar deneyin.</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>Passphrase Dialog</source>
- <translation>Parola Diyaloğu</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Parolayı girin</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Yeni parola</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Yeni parolayı tekrarla</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Şifreyi göster</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Yeni parolayı cüzdana girin.&lt;br/&gt;Lütfen &lt;b&gt;on yada daha fazla karakter&lt;/b&gt; veya &lt;b&gt;sekiz yada daha fazla kelime&lt;/b&gt;içeren bir parola kullanın. </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şlem, cüzdan kilidinizi açmak için parolanıza ihtiyaç duyuyor</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Cüzdanı Kilitle</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Bu işlem, cüzdan kilidinizi açmak için parolanıza ihtiyaç duyuyor</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Cüzdanın Şifresini Çöz</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Parolayı değiştir</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Eski ve yeni parolanızı cüzdana girin.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Cüzdan Şifrelemesini Onaylayın</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Uyarı: Eğer cüzdanınızı şifreleyip parolanızı kaybederseniz (unutursanız) , &lt;b&gt;BÜTÜN BITCOIN'LERINIZI KAYBEDECEKSINIZ&lt;/b&gt;!</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>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 Şifreleme işlemini bitirmek için kapatılacak. Şunu unutmayın ki şampiyon galatasaray ve şifrelemek, bitcoinlerinizin bilgisayarınıza bulaşan malware yazılımları tarafından çalınmasını tamamen engelleyemez.</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>ÖNEMLİ: Yeni oluşturduğunuz şifrelenmiş cüzdan dosyasını önceki yedeklenmiş cüzdan dosyasıyla değiştirmeniz gerekmektedir. Güvenlik sebeplerinden dolayı yeni, şifrelenmiş cüzdanınızı kullanmaya başlar başlamaz önceki şifrelenmemiş cüzdan yedekleri kullanılmaz hale gelecektir.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Cüzdan şifreleme başarısız oldu</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Cüzdan şifreleme dahili bir hata nedeniyle başarısız oldu. Cüzdanınız şifrelenemedi.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Girilen parolalar eşleşmiyor.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Cüzdan Kilidi Açma Hatası</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Dikkat! Caps Lock tuşunuz açık!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- </context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>İmza &amp;mesaj</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Ağ ile bağlantı kuruluyor...</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;‮‮‭İşlemler</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>İşlem geçmişinize göz atın</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>Çıkış</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Başvuruyu iptal edin</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>Hakkında%1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>%1 hakkındaki bilgileri görüntüle</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Qt Hakkında</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Qt hakkındaki bilgileri görüntüleyin</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Seçenekler</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Cüzdan Şifreleme</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Cüzdan Yedekleme</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>Gönderme adresleri</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Alış adresleri</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>URI'yi aç</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Ağ etkinliği devre dışı.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Ağ aktivitesini tekrar başlatmak için tıklayın.</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Bloklar disk üzerinde yeniden indeksleniyor...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Bitcoin adresine madeni para gönderin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Cüzdanınızı başka bir lokasyona yedekleyin</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Hata giderme konsolunu aç</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>Onay mesajı...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin
-</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Cüzdan</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>Gönder</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>Al</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>Göster / Gizle</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Ayarlar</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Kullanılan gönderim adreslerinin ve etiketlerinin listesini göster</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Kullanılan alış adreslerinin ve etiketlerinin listesini göster</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>Komut satırı ayarları</translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Bloklar disk üzerinde indeksleniyor...</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>Date: %1
-</source>
- <translation>Tarih %1</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>HD anahtar üretimi&lt;b&gt;aktif&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>HD anahtar üretimi &lt;b&gt;pasif&lt;/b&gt;</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Bytes:</source>
- <translation>Bayt</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Ücret:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Ücretten sonra kalan:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Değişen:</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Listeleme modu</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Tarih</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Onaylamalar</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Kabul edilen</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 fee</source>
- <translation>Ücreti kopyala</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 kilitli)</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>
- </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>
- <message>
- <source>New sending address</source>
- <translation>Yeni gönderim adresi</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Alış adresini düzenleyin</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Gönderim adresini düzenleyin</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>Girilen adres "%1" Bitcoin adresiyle eşleşmiyor.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Yeni anahtar üretimi başarısız.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>name</source>
- <translation>isim</translation>
- </message>
- </context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>versiyon</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>Hakkında %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Komut satırı ayarları</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>Form</source>
- <translation>Form</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Kalan blokların sayısı</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Bilinmiyor...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Son blok zamanı</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>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Ayarlar</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Ana Menü</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Veritabanı önbelleğinin boyutu</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Proxy bağlantısı IP adresleri (örneğin IPv4: 127.0.0.1 / IPv6: ::1)</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Konfigürasyon dosyasını aç</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Bütün ayarları varsayılana çevir</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>Ağ</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>Cüzdan</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Proxy portu (örneğin 9050)</translation>
- </message>
- <message>
- <source>&amp;Window</source>
- <translation>Pencere</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>Kullanıcı arayüzü dili</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>Client restart required to activate changes.</source>
- <translation>Değişikliklerin aktif edilebilmesi için yeniden başlatma gerekiyor.</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Konfigürasyon ayarları</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>Konfigürasyon dosyası GUI ayarlarını geçersiz kılmak için gelişmiş kullanıcı ayarlarını değiştirir. Ek olarak, herhangi bir komut satırı seçeneği konfigürasyon dosyasını geçersiz kılar.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Hata</translation>
- </message>
- <message>
- <source>The configuration file could not be opened.</source>
- <translation>Konfigürasyon dosyası açılamadı.</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Bu değişiklik istemcinin yeniden başlatılmasını gerektirir.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Sağlanan proxy adresi geçerli değil.</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>Gösterilen bilgi geçerli olmayabilir. Bağlantı tekrar sağlandıktan sonra cüzdanınız otomatik olarak senkronize olacaktır. Henüz senkronize olma işlemi tamamlanmadı.</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Sadece görüntülenebilir:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Kullanılabilir:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Mevcut harcanabilir tutarınız</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Bekleyen:</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Toplam:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Toplam mevcut miktarınız</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>Sadece görüntülenebilir adreslerdeki mevcut miktarınız</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Harcanabilir:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Yakın zamanda yapılmış işlemler</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Sadece görüntülenebilir adreslerdeki doğrulanmamış işlemler</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>Sadece görüntülenebilir adreslerdeki mevcut toplam miktar</translation>
- </message>
-</context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Ödeme isteği hatası</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Ödeme isteği URL'si hatalı: %1</translation>
- </message>
- <message>
- <source>Invalid payment address %1</source>
- <translation>Hatalı ödeme adresi %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Ağ hatası</translation>
- </message>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>Sent</source>
- <translation>Gönder</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Alındı</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Bitcoin adresinizi girin (örneğin %1)</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>Yok</translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 ve %2</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>bilinmiyor</translation>
- </message>
-</context>
-<context>
- <name>QObject::QObject</name>
- <message>
- <source>Error: %1</source>
- <translation>Hata: %1</translation>
- </message>
-</context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Görüntüyü kaydet</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>&amp;Görüntüyü kopyala</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>QR kodu kaydet</translation>
- </message>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>Yok</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Arayüz versiyonu</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Bilgi</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Hata giderme penceresi</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Genel</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>Kullanılan BerkeleyDB versiyonu</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Başlangıç zamanı</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Ağ</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>İsim</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Bağlantı sayısı</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Blok zinciri</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Bellek kullanımı</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Yeniden başlat</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Alındı</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Gönder</translation>
- </message>
- <message>
- <source>Whitelisted</source>
- <translation>Beyaz listede</translation>
- </message>
- <message>
- <source>Version</source>
- <translation>Versiyon</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Servisler</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Bağlantı süresi</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Son gönderim</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Son alış</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Ping süresi</translation>
- </message>
- <message>
- <source>Ping Wait</source>
- <translation>Ping bekliyor</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Son blok zamanı</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Aç</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>&amp;Konsol</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>&amp;Ağ trafiği</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Toplam</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Konsolu temizle</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;saat</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;gün</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;hafta</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;yıl</translation>
- </message>
- <message>
- <source>&amp;Disconnect</source>
- <translation>&amp;Bağlantı kesildi</translation>
- </message>
- <message>
- <source>Network activity disabled</source>
- <translation>Ağ aktivitesi pasif</translation>
- </message>
- <message>
- <source>never</source>
- <translation>asla</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Gelen</translation>
- </message>
- <message>
- <source>Outbound</source>
- <translation>Giden</translation>
- </message>
- <message>
- <source>Yes</source>
- <translation>Evet</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Hayır</translation>
- </message>
- <message>
- <source>Unknown</source>
- <translation>Bilinmiyor</translation>
- </message>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Etiket</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Mesaj</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Temizle</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Göster</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Sil</translation>
- </message>
- <message>
- <source>Copy URI</source>
- <translation>URI'yi kopyala</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Etiketi kopyala</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Mesajı kopyala</translation>
- </message>
- </context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>QR kod</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>URI'yi kopyala</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Adresi Kopyala</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Görüntüyü kaydet</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation>Ödeme bilgisi</translation>
- </message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>adres</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>etiket</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mesaj</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>Message</source>
- <translation>Mesaj</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(etiket yok)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation>(mesaj yok)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Coin gönder</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>Otomatik seçildi</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bayt</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Ücret:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Ücretten sonra kalan:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Değişen:</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Gönderim ücreti:</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Seçiniz...</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>kilobyte başına</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Gizle</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Önerilen:</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Hepsini sil</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Ücreti kopyala</translation>
- </message>
- <message>
- <source>%1 (%2 blocks)</source>
- <translation>%1 (%2 blok)</translation>
- </message>
- <message>
- <source>%1 to %2</source>
- <translation>%1'den %2'e</translation>
- </message>
- <message>
- <source>Are you sure you want to send?</source>
- <translation>Göndermek istediğinize emin misiniz?</translation>
- </message>
- <message>
- <source>or</source>
- <translation>ya da</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Gönderim ücreti</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation>Coin gönderimini onaylayın</translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation>Uyarı: Hatalı Bitcoin adresi</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(etiket yok)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Etiket</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Panodaki adresi yapıştırın</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Mesaj:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Evet</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Panodaki adresi yapıştırın</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>İmza</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>İmza &amp;Mesaj</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Hepsini sil</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation>Girilen adres hatalı.</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Adresi kontrol ettikten sonra lütfen tekrar deneyin.</translation>
- </message>
- <message>
- <source>Please check the signature and try again.</source>
- <translation>İmzanızı kontrol ettikten sonra lütfen tekrar deneyin.</translation>
- </message>
- <message>
- <source>Message verification failed.</source>
- <translation>Mesaj onayı hatalı.</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation>Mesaj onaylandı.</translation>
- </message>
-</context>
-<context>
- <name>SplashScreen</name>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Status</source>
- <translation>Durum</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Tarih</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Kaynak</translation>
- </message>
- <message>
- <source>Generated</source>
- <translation>Oluşturuldu</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>bilinmiyor</translation>
- </message>
- <message>
- <source>label</source>
- <translation>etiket</translation>
- </message>
- <message>
- <source>not accepted</source>
- <translation>kabul edilmedi</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Gönderim ücreti</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mesaj</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Yorum</translation>
- </message>
- <message>
- <source>Transaction total size</source>
- <translation>Gönderimin toplam boyutu</translation>
- </message>
- <message>
- <source>Debug information</source>
- <translation>Hata giderme bilgisi</translation>
- </message>
- <message>
- <source>true</source>
- <translation>doğru</translation>
- </message>
- <message>
- <source>false</source>
- <translation>anlış</translation>
- </message>
-</context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation>Tarih</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tip</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>etiket</translation>
- </message>
- <message>
- <source>Confirmed (%1 confirmations)</source>
- <translation>Onaylandı (%1 onaylanan)</translation>
- </message>
- <message>
- <source>Generated but not accepted</source>
- <translation>Oluşturuldu fakat kabul edilmedi</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>ile alındı</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Kazıldı</translation>
- </message>
- <message>
- <source>(n/a)</source>
- <translation>(yok)</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(etiket yok)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation>Hepsi</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Bugün</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>Bu hafta</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>Bu Ay</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>Son ay</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>Bu yıl</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>ile alındı</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Kazıldı</translation>
- </message>
- <message>
- <source>Other</source>
- <translation>Diğerleri</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Adresi kopyala</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Etiketi kopyala</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Virgül ile ayrılmış dosya (*.csv)</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Kabul edilen</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Tarih</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Tip</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 Aktarma Başarısız</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Coin gönder</translation>
- </message>
- <message>
- <source>New fee:</source>
- <translation>Yeni ücret:</translation>
- </message>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Çıkar</translation>
- </message>
- <message>
- <source>Backup Wallet</source>
- <translation>Cüzdanı yedekle</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>Yedekleme başarısız</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Yedekleme tamamlandı</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Çekirdeği</translation>
- </message>
- <message>
- <source>Copyright (C) %i-%i</source>
- <translation>Copyright (C) %i-%i</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Hata: Disk boyutu düşük!</translation>
- </message>
- <message>
- <source>Loading P2P addresses...</source>
- <translation>P2P adresleri yükleniyor...</translation>
- </message>
- <message>
- <source>Loading banlist...</source>
- <translation>Ban listesi yükleniyor...</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Bloklar Onaylanıyor...</translation>
- </message>
- <message>
- <source>Wallet needed to be rewritten: restart %s to complete</source>
- <translation>%s tamamlanması için cüzdanın yeniden başlatılması gerekiyor</translation>
- </message>
- <message>
- <source>Error reading from database, shutting down.</source>
- <translation>Veritabanı okuma hatası, kapatıldı.</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Bilgi</translation>
- </message>
- <message>
- <source>Invalid -onion address or hostname: '%s'</source>
- <translation>Hatalı -onion adresi ya da host adı: '%s'</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>Bu deneysel bir yazılımdır.</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>İşlem çok büyük</translation>
- </message>
- <message>
- <source>Verifying wallet(s)...</source>
- <translation>Cüzdan(lar) onaylanıyor...</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Uyarı</translation>
- </message>
- <message>
- <source>Starting network threads...</source>
- <translation>Bağlantı konuları başlıyor</translation>
- </message>
- <message>
- <source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation>Cüzdan minimum değişim ücretinden daha düşük olan ödemeyi önleyecektir</translation>
- </message>
- <message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Her işlem için minimum işlem ücretiniz budur</translation>
- </message>
- <message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Bir işlem göndermeniz durumunda işlem ücretiniz budur</translation>
- </message>
- <message>
- <source>Transaction amounts must not be negative</source>
- <translation>İşlem miktarı negatif olmamalı</translation>
- </message>
- <message>
- <source>Transaction has too long of a mempool chain</source>
- <translation>İşlem çok uzun bir bellek havuzu zincirine sahip</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>İşlemin en az bir alıcıya sahip olmalı</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Belirsiz ağ belirtildi -onlynet: '%s'</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Yetersiz Bakiye</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Blok indeksi yükleniyor</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Cüzdan Bekleniyor...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Cüzdan indirgenememektedir</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Tekrar taranıyor...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Yükleme tamamlandı</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Hata</translation>
- </message>
-</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 0c01a25d93..ca8839fee3 100644
--- a/src/qt/locale/bitcoin_uk.ts
+++ b/src/qt/locale/bitcoin_uk.ts
@@ -3,39 +3,39 @@
<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;Новый</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;Копировать</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>
- <translation>Экспортировать данные текущей вкладки в файл</translation>
+ <translation>Експортувати дані з поточної вкладки в файл</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -43,199 +43,227 @@
</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>
- <translation>&amp;Выбрать</translation>
+ <translation>&amp;Вибрати</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>Це ваші адреси 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>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>Копировать &amp;адрес</translation>
+ <translation>&amp;Скопіювати адресу</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>Копировать &amp;метку</translation>
+ <translation>Скопіювати &amp;мітку</translation>
</message>
<message>
<source>&amp;Edit</source>
- <translation>&amp;Правка</translation>
+ <translation>&amp;Редагувати</translation>
</message>
<message>
<source>Export Address List</source>
- <translation>Экспортировать список адресов</translation>
+ <translation>Експортувати список адрес</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>Текст, разделённый запятыми (*.csv)</translation>
+ <translation>Файли (*.csv) розділеі комами</translation>
</message>
<message>
<source>Exporting Failed</source>
- <translation>Экспорт не удался</translation>
+ <translation>Помилка експорту</translation>
</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>
<name>AddressTableModel</name>
<message>
<source>Label</source>
- <translation>Метка</translation>
+ <translation>Мітка</translation>
</message>
<message>
<source>Address</source>
- <translation>Адрес</translation>
+ <translation>Адреса</translation>
</message>
<message>
<source>(no label)</source>
- <translation>(нет метки)</translation>
+ <translation>(немає мітки)</translation>
</message>
</context>
<context>
<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>
- <translation>Новый пароль</translation>
+ <translation>Новий пароль</translation>
</message>
<message>
<source>Repeat new passphrase</source>
- <translation>Повторите новый пароль</translation>
+ <translation>Повторіть пароль</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <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>
- <translation>Для выполнения операции требуется пароль от вашего кошелька.</translation>
+ <translation>Ця операція потребує пароль для розблокування гаманця.</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation>Разблокировать бумажник</translation>
+ <translation>Розблокувати гаманець</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Данная операция требует введения пароля для расшифровки вашего бумажника.</translation>
+ <translation>Ця операція потребує пароль для розшифрування гаманця.</translation>
</message>
<message>
<source>Decrypt wallet</source>
- <translation>Расшифровать бумажник</translation>
+ <translation>Розшифрувати гаманець</translation>
</message>
<message>
<source>Change passphrase</source>
- <translation>Изменить пароль</translation>
+ <translation>Змінити пароль</translation>
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation>Подтвердить шифрование кошелька</translation>
+ <translation>Підтвердіть шифрування гаманця</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Предупреждение: если вы зашифруете бумажник и потеряете пароль, вы &lt;b&gt;ПОТЕРЯЕТЕ ВСЕ ВАШИ БИТКОИНЫ&lt;/b&gt;!</translation>
+ <translation>Увага: Якщо ви зашифруєте гаманець і забудете пароль, ви &lt;b&gt;ВТРАТИТЕ ВСІ СВОЇ БІТКОІНИ&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Вы уверены, что хотите зашифровать ваш кошелёк?</translation>
+ <translation>Ви дійсно хочете зашифрувати свій гаманець?</translation>
</message>
<message>
<source>Wallet encrypted</source>
- <translation>Кошелёк зашифрован</translation>
+ <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;десяти або більше випадкових символів&lt;/b&gt;, або &lt;b&gt; вісім або більше слів&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Введіть стару та нову парольну фразу для гаманця.</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>
<message>
+ <source>Wallet to be encrypted</source>
+ <translation>Гаманець який потрібно зашифрувати</translation>
+ </message>
+ <message>
+ <source>Your wallet is about 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>
<message>
<source>Wallet encryption failed</source>
- <translation>Не удалось зашифровать бумажник</translation>
+ <translation>Не вдалося зашифрувати гаманець</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Сбой шифрования кошелька из-за внутренней ошибки. Ваш кошелёк не был зашифрован.</translation>
+ <translation>Виникла помилка під час шифрування гаманця. Ваш гаманець не було зашифровано.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
- <translation>Введённые пароли не совпадают.</translation>
+ <translation>Введені паролі не співпадають.</translation>
</message>
<message>
<source>Wallet unlock failed</source>
- <translation>Разблокировка бумажника не удалась</translation>
+ <translation>Не вдалося розблокувати гаманець</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Введений пароль є невірним.</translation>
+ <translation>Введено невірний пароль.</translation>
</message>
<message>
<source>Wallet decryption failed</source>
- <translation>Расшифровка кошелька не удалась</translation>
+ <translation>Не вдалося розшифрувати гаманець</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
- <translation>Пароль бумажника успешно изменён.</translation>
+ <translation>Пароль було успішно змінено.</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
- <translation>Внимание: Caps Lock включен!</translation>
+ <translation>Увага: ввімкнено Caps Lock!</translation>
</message>
</context>
<context>
<name>BanTableModel</name>
<message>
<source>IP/Netmask</source>
- <translation>IP/Маска подсети</translation>
+ <translation>IP/Маска підмережі</translation>
</message>
<message>
<source>Banned Until</source>
- <translation>Заблокировано до</translation>
+ <translation>Заблоковано до</translation>
</message>
</context>
<context>
<name>BitcoinGUI</name>
<message>
<source>Sign &amp;message...</source>
- <translation>Подписать &amp;сообщение...</translation>
+ <translation>Підписати &amp;повідомлення</translation>
</message>
<message>
<source>Synchronizing with network...</source>
- <translation>Синхронизация с сетью...</translation>
+ <translation>Синхронізація з мережею...</translation>
</message>
<message>
<source>&amp;Overview</source>
- <translation>&amp;Обзор</translation>
+ <translation>&amp;Огляд</translation>
</message>
<message>
<source>Show general overview of wallet</source>
@@ -243,23 +271,23 @@
</message>
<message>
<source>&amp;Transactions</source>
- <translation>&amp;Транзакции</translation>
+ <translation>&amp;Транзакції</translation>
</message>
<message>
<source>Browse transaction history</source>
- <translation>Просмотр истории транзакций</translation>
+ <translation>Переглянути історію транзакцій</translation>
</message>
<message>
<source>E&amp;xit</source>
- <translation>В&amp;ыход</translation>
+ <translation>&amp;Вихід</translation>
</message>
<message>
<source>Quit application</source>
- <translation>Закрыть приложение</translation>
+ <translation>Вийти</translation>
</message>
<message>
<source>&amp;About %1</source>
- <translation>&amp;Около %1</translation>
+ <translation>П&amp;ро %1</translation>
</message>
<message>
<source>Show information about %1</source>
@@ -267,27 +295,27 @@
</message>
<message>
<source>About &amp;Qt</source>
- <translation>O &amp;Qt</translation>
+ <translation>&amp;Про Qt</translation>
</message>
<message>
<source>Show information about Qt</source>
- <translation>Показать информацию о Qt</translation>
+ <translation>Показати інформацію про Qt</translation>
</message>
<message>
<source>&amp;Options...</source>
- <translation>&amp;Параметры</translation>
+ <translation>&amp;Параметри</translation>
</message>
<message>
<source>Modify configuration options for %1</source>
- <translation>Изменить параметры конфигурации для %1</translation>
+ <translation>Редагувати параметри для %1</translation>
</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>
@@ -298,8 +326,16 @@
<translation>Відкрити &amp;URI</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Створити Гаманець...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Створити новий гаманець</translation>
+ </message>
+ <message>
<source>Wallet:</source>
- <translation>Кошелёк</translation>
+ <translation>Гаманець:</translation>
</message>
<message>
<source>Click to disable network activity.</source>
@@ -319,7 +355,7 @@
</message>
<message>
<source>Reindexing blocks on disk...</source>
- <translation>Переиндексация блоков на диске...</translation>
+ <translation>Переіндексація блоків на диску ...</translation>
</message>
<message>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
@@ -338,14 +374,6 @@
<translation>Змінити пароль, який використовується для шифрування гаманця</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Окно отладки</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Відкрити консоль зневадження і діагностики</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>П&amp;еревірити повідомлення...</translation>
</message>
@@ -371,7 +399,7 @@
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Підтвердіть, що Ви є власником повідомлення підписавши його Вашою Bitcoin-адресою </translation>
+ <translation>Підтвердіть, що Ви є власником повідомлення підписавши його Вашою Bitcoin-адресою</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
@@ -391,7 +419,7 @@
</message>
<message>
<source>Tabs toolbar</source>
- <translation>Панель вкладок</translation>
+ <translation>Панель дій</translation>
</message>
<message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
@@ -406,10 +434,6 @@
<translation>Показати список адрес і міток, що були використані для отримання</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Відкрити bitcoin: URI чи запит платежу</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>П&amp;араметри командного рядка</translation>
</message>
@@ -443,7 +467,7 @@
</message>
<message>
<source>Error</source>
- <translation>Ошибка</translation>
+ <translation>Помилка</translation>
</message>
<message>
<source>Warning</source>
@@ -458,6 +482,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>&amp;Адреси для відправлення</translation>
</message>
@@ -466,6 +498,10 @@
<translation>&amp;Адреси для отримання</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Відкрити біткоін URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Відкрити гаманець</translation>
</message>
@@ -479,7 +515,7 @@
</message>
<message>
<source>Close wallet</source>
- <translation>закрити Гаманець</translation>
+ <translation>Закрити гаманець</translation>
</message>
<message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
@@ -495,15 +531,15 @@
</message>
<message>
<source>&amp;Window</source>
- <translation>&amp;Окно</translation>
+ <translation>&amp;Вікно</translation>
</message>
<message>
<source>Minimize</source>
- <translation>Сворачивать</translation>
+ <translation>Згорнути</translation>
</message>
<message>
<source>Zoom</source>
- <translation>Збільшення</translation>
+ <translation>Збільшити</translation>
</message>
<message>
<source>Main Window</source>
@@ -526,6 +562,10 @@
<translation>Помилка: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>Попередження: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>Дата: %1
@@ -678,7 +718,7 @@
</message>
<message>
<source>Copy transaction ID</source>
- <translation>Копіювати ID транзакції </translation>
+ <translation>Копіювати ID транзакції</translation>
</message>
<message>
<source>Lock unspent</source>
@@ -734,7 +774,7 @@
</message>
<message>
<source>(no label)</source>
- <translation>(нет метки)</translation>
+ <translation>(без мітки)</translation>
</message>
<message>
<source>change from %1 (%2)</source>
@@ -747,10 +787,58 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <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>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Попередження створення гаманця</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Створити Гаманець</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Назва Гаманця</translation>
+ </message>
+ <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>Create</source>
+ <translation>Створити</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -833,11 +921,7 @@
<name>HelpMessageDialog</name>
<message>
<source>version</source>
- <translation>версії</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-бітний)</translation>
+ <translation>версія</translation>
</message>
<message>
<source>About %1</source>
@@ -867,6 +951,10 @@
<translation>Після натискання кнопки «OK» %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>
@@ -908,7 +996,7 @@
</message>
<message>
<source>Error</source>
- <translation>Ошибка</translation>
+ <translation>Помилка</translation>
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
@@ -966,6 +1054,14 @@
<translation>Приховати</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 синхронізується. Буде завантажено заголовки та блоки та перевірено їх до досягнення кінця ланцюга блоків.</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>Невідомо. Синхронізація заголовків (%1, %2%) ...</translation>
</message>
@@ -973,28 +1069,24 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Відкрити URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Відкрити запит платежу з URI або файлу</translation>
+ <source>Open bitcoin URI</source>
+ <translation>Відкрити біткоін URI</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
<message>
- <source>Select payment request file</source>
- <translation>Виберіть файл запиту платежу</translation>
+ <source>Open wallet failed</source>
+ <translation>Помилка відкриття гаманця</translation>
</message>
<message>
- <source>Select payment request file to open</source>
- <translation>Виберіть файл запиту платежу</translation>
+ <source>Open wallet warning</source>
+ <translation>Попередження відкриття гаманця</translation>
</message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
<message>
<source>default wallet</source>
<translation>гаманець за змовчуванням</translation>
@@ -1132,11 +1224,11 @@
</message>
<message>
<source>Accept connections from outside.</source>
- <translation>Принимать входящие соединения.</translation>
+ <translation>Приймати з'єднання ззовні.</translation>
</message>
<message>
<source>Allow incomin&amp;g connections</source>
- <translation>Разрешить входящие подключения</translation>
+ <translation>Дозволити вхідні з'єднання</translation>
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
@@ -1264,7 +1356,7 @@
</message>
<message>
<source>Error</source>
- <translation>Ошибка</translation>
+ <translation>Помилка</translation>
</message>
<message>
<source>The configuration file could not be opened.</source>
@@ -1373,16 +1465,16 @@
<translation>'bitcoin://' не вірний URI. Використовуйте 'bitcoin:'.</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Ви використовуєте BIP70 посилання, яке в майбутньому не буде підтримуватись.</translation>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>Неможливо обробити платіжний запит, оскільки не підтритується BIP70.</translation>
</message>
<message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>URL запиту платежу є некоректним: %1</translation>
+ <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>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Неможливо обробити платіжний запит, оскільки вимкнено підтримку BIP70.</translation>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Якщо ви отримали цю помилку, ви повинні попросити продавця надати URI, сумісний з BIP21.</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1396,68 +1488,6 @@
<source>Payment request file handling</source>
<translation>Обробка файлу запиту платежу</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Неможливо прочитати файл запиту платежу! Ймовірно, файл пошкоджено.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Запит платежу відхилено</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Мережа запиту платежу не є мережею клієнта.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Запит платежу прострочено.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Запит платежу не ініціалізовано.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>
-70/5000
-Неперевірені запити на оплату до індивідуальних платіжних скриптів не підтримуються.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Помилка в запиті платежу.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Сума запиту платежу для %1 занадто мала (вважається пилом)</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Відшкодування з %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Запит платежу %1 занадто великий (%2 байт, дозволено %3 байт).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Помилка зв'язку з %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Неможливо розпізнати запит платежу!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Погана відповідь від сервера %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Помилка мережевого запиту</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Платіж підтверджено</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1608,6 +1638,10 @@
<translation>Помилка кодування URI в QR-код.</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>Підтримка QR-коду недоступна.</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>Зберегти QR-код</translation>
</message>
@@ -1631,10 +1665,6 @@
<translation>&amp;Інформація</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Вікно зневадження</translation>
- </message>
- <message>
<source>General</source>
<translation>Загальна</translation>
</message>
@@ -1755,6 +1785,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>
@@ -1966,12 +2000,24 @@
<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>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Очистити всі поля в формі</translation>
</message>
<message>
<source>Clear</source>
- <translation>Очистить</translation>
+ <translation>Очистити</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>
@@ -2058,7 +2104,7 @@
</message>
<message>
<source>Label</source>
- <translation>Метка</translation>
+ <translation>Мітка</translation>
</message>
<message>
<source>Message</source>
@@ -2066,7 +2112,7 @@
</message>
<message>
<source>Wallet</source>
- <translation>Кошелёк</translation>
+ <translation>Гаманець</translation>
</message>
</context>
<context>
@@ -2077,7 +2123,7 @@
</message>
<message>
<source>Label</source>
- <translation>Метка</translation>
+ <translation>Мітка</translation>
</message>
<message>
<source>Message</source>
@@ -2085,7 +2131,7 @@
</message>
<message>
<source>(no label)</source>
- <translation>(нет метки)</translation>
+ <translation>(без мітки)</translation>
</message>
<message>
<source>(no message)</source>
@@ -2171,16 +2217,12 @@
<translation>Попередження: оцінка розміру комісії наразі неможлива.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>згорнути налаштування оплат</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>Вкажіть комісію за кБ (1,000 байт) віртуального розміру транзакції.
-Примітка: Так як комісія нараховується за байт, комісія "100 сатоші за кБ" для транзакції розміром 500 байт (пів 1 кБ) буде приблизно 50 сатоші. </translation>
+Примітка: Так як комісія нараховується за байт, комісія "100 сатоші за кБ" для транзакції розміром 500 байт (пів 1 кБ) буде приблизно 50 сатоші.</translation>
</message>
<message>
<source>per kilobyte</source>
@@ -2219,6 +2261,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>
@@ -2287,14 +2333,38 @@ 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>С&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>
+ <translation>Створює частково підписану транзакцію Bitcoin (PSBT) для використання, наприклад, офлайн-гаманець %1 або гаманця, сумісного з PSBT.</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation>з гаманця '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 до '%2'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<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>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>
+ </message>
+ <message>
<source>or</source>
<translation>або</translation>
</message>
@@ -2308,7 +2378,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Transaction fee</source>
- <translation>Комиссия</translation>
+ <translation>Комісія</translation>
</message>
<message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
@@ -2319,10 +2389,34 @@ 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>Confirm transaction proposal</source>
+ <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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Неприпустима адреса отримувача. Будь ласка, перевірте.</translation>
</message>
@@ -2347,10 +2441,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Транзакцію не виконано!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Транзакцію відхилено з наступної причини: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Комісія більша, ніж %1, вважається абсурдно високою.</translation>
</message>
@@ -2380,7 +2470,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>(no label)</source>
- <translation>(нет метки)</translation>
+ <translation>(без мітки)</translation>
</message>
</context>
<context>
@@ -2402,10 +2492,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Обрати ранiш використовувану адресу</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Це звичайний платіж.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>Адреса Bitcoin для відправлення платежу</translation>
</message>
@@ -2426,6 +2512,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>
@@ -2465,17 +2555,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Memo:</source>
<translation>Нотатка:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Введіть мітку для цієї адреси для додавання її в адресну книгу</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Так</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2563,6 +2642,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Адреса Bitcoin, якою було підписано це повідомлення</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>
</message>
@@ -2595,8 +2682,12 @@ 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>
+ <translation>Приватний ключ для введеної адреси недоступний.</translation>
</message>
<message>
<source>Message signing failed.</source>
@@ -2769,6 +2860,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>
@@ -2824,7 +2919,7 @@ 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 numerus="yes">
<source>Open for %n more block(s)</source>
@@ -2892,7 +2987,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>(no label)</source>
- <translation>(нет метки)</translation>
+ <translation>(без мітки)</translation>
</message>
<message>
<source>Transaction status. Hover over this field to show number of confirmations.</source>
@@ -2999,7 +3094,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Copy transaction ID</source>
- <translation>Скопіювати ID транзакції </translation>
+ <translation>Скопіювати ID транзакції</translation>
</message>
<message>
<source>Copy raw transaction</source>
@@ -3092,6 +3187,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>закрити Гаманець</translation>
</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>
+ </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>
@@ -3122,6 +3221,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>
@@ -3138,6 +3241,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>
@@ -3204,10 +3315,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Неможливо провести повторне сканування зі скороченим ланцюжком. Вам необхідно використати -reindex для завантаження повного ланцюжка блоків.</translation>
- </message>
- <message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>Помилка: Сталася фатальна помилка (детальніший опис наведено в debug.log)</translation>
</message>
@@ -3308,6 +3415,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
<translation>Ви хочете перебудувати базу даних блоків зараз?</translation>
</message>
@@ -3341,7 +3456,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Error opening block database</source>
- <translation>Помилка відкриття блоку бази даних </translation>
+ <translation>Помилка відкриття блоку бази даних</translation>
</message>
<message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
@@ -3364,6 +3479,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Невдала перевірка правильності ініціалізації. %s закривається.</translation>
</message>
<message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Помилка P2P доступу: '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
<translation>Невірна сума -%s=&lt;amount&gt;: '%s'</translation>
</message>
@@ -3380,6 +3499,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Зазначений каталог блоків "%s" не існує.</translation>
</message>
<message>
+ <source>Unknown address type '%s'</source>
+ <translation>Невідомий тип адреси '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation>Невідомий тип решти '%s'</translation>
+ </message>
+ <message>
<source>Upgrading txindex database</source>
<translation>Оновлення txindex бази</translation>
</message>
@@ -3388,6 +3515,10 @@ 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>
@@ -3397,7 +3528,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Prune cannot be configured with a negative value.</source>
- <translation>Розмір скороченого ланцюжка блоків не може бути від'ємним. </translation>
+ <translation>Розмір скороченого ланцюжка блоків не може бути від'ємним.</translation>
</message>
<message>
<source>Prune mode is incompatible with -txindex.</source>
@@ -3457,7 +3588,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>Залишок від суми транзакції зі сплатою комісії занадто малий </translation>
+ <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>
@@ -3496,6 +3627,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>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Використання скороченого ланцюжка блоків несумісне з параметром -blockfilterindex.</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Зменшення значення -maxconnections з %d до %d із-за обмежень системи.</translation>
</message>
@@ -3553,8 +3688,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
@@ -3573,10 +3712,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Це комісія за транзакцію, яку ви можете сплатити, коли кошторисна вартість недоступна.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Цей продукт включає в себе програмне забезпечення, розроблене проектом OpenSSL для використання в OpenSSL Toolkit %s та криптографічне програмне забезпечення, написане Еріком Янгом та програмне забезпечення UPnP, написане Томасом Бернардом.</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation>Загальна довжина рядку мережевої версії (%i) перевищує максимально допустиму (%i). Зменшіть число чи розмір коментарів клієнта користувача.</translation>
</message>
@@ -3626,7 +3761,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Insufficient funds</source>
- <translation>Недостаточно средств</translation>
+ <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>
@@ -3634,7 +3769,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
- <translation>Оцінка комісії не вдалася. Fallbackfee вимкнено. Зачекайте кілька блоків або ввімкніть -fallbackfee. </translation>
+ <translation>Оцінка комісії не вдалася. Fallbackfee вимкнено. Зачекайте кілька блоків або ввімкніть -fallbackfee.</translation>
</message>
<message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
@@ -3646,23 +3781,23 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Loading block index...</source>
- <translation>Загрузка индекса блоков...</translation>
+ <translation>Завантаження індексу блоків...</translation>
</message>
<message>
<source>Loading wallet...</source>
- <translation>Загрузка электронного кошелька...</translation>
+ <translation>Завантаження гаманця...</translation>
</message>
<message>
<source>Cannot downgrade wallet</source>
- <translation>Не удаётся понизить версию электронного кошелька</translation>
+ <translation>Не вдається знити версію гаманця</translation>
</message>
<message>
<source>Rescanning...</source>
- <translation>Сканирование...</translation>
+ <translation>Сканування...</translation>
</message>
<message>
<source>Done loading</source>
- <translation>Загрузка завершена</translation>
+ <translation>Завантаження завершено</translation>
</message>
</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_uk_UA.ts b/src/qt/locale/bitcoin_uk_UA.ts
deleted file mode 100644
index d10ac6dd1c..0000000000
--- a/src/qt/locale/bitcoin_uk_UA.ts
+++ /dev/null
@@ -1,239 +0,0 @@
-<TS language="uk_UA" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Create a new address</source>
- <translation>Створіть нову адресу</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Нова</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Копіювати</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>&amp;Закрити</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Експортувати</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Видалити</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Оберіть адресу на яку буде надіслано монети</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Оберіть адресу на яку Ви будете отримувати монети</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Зкопіювати адресу</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Змінити</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Експортувати список адрес</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Address</source>
- <translation>Адреса</translation>
- </message>
- </context>
-<context>
- <name>AskPassphraseDialog</name>
- <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 password</source>
- <translation>Показати пароль</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>
- </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>
- <message>
- <source>Decrypt wallet</source>
- <translation>Розшифрувати гаманець</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Змінити пароль</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Введіть старий пароль і новий пароль гаманця.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Підтвердіть шифрування гаманця</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Чи ви справді бажаєте зашифрувати гаманець?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Гаманець зашифровано</translation>
- </message>
- </context>
-<context>
- <name>BanTableModel</name>
- </context>
-<context>
- <name>BitcoinGUI</name>
- </context>
-<context>
- <name>CoinControlDialog</name>
- </context>
-<context>
- <name>EditAddressDialog</name>
- </context>
-<context>
- <name>FreespaceChecker</name>
- </context>
-<context>
- <name>HelpMessageDialog</name>
- </context>
-<context>
- <name>Intro</name>
- </context>
-<context>
- <name>ModalOverlay</name>
- </context>
-<context>
- <name>OpenURIDialog</name>
- </context>
-<context>
- <name>OptionsDialog</name>
- </context>
-<context>
- <name>OverviewPage</name>
- </context>
-<context>
- <name>PaymentServer</name>
- </context>
-<context>
- <name>PeerTableModel</name>
- </context>
-<context>
- <name>QObject</name>
- </context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- </context>
-<context>
- <name>RPCConsole</name>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- </context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>Адреса</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- </context>
-<context>
- <name>SendCoinsEntry</name>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- </context>
-<context>
- <name>SplashScreen</name>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Address</source>
- <translation>Адреса</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Експортувати</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- </context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ur.ts b/src/qt/locale/bitcoin_ur.ts
index f780487c24..b76551fc6f 100644
--- a/src/qt/locale/bitcoin_ur.ts
+++ b/src/qt/locale/bitcoin_ur.ts
@@ -155,7 +155,7 @@
</message>
<message>
<source>&amp;Address</source>
- <translation> پتہ</translation>
+ <translation>پتہ</translation>
</message>
</context>
<context>
@@ -261,9 +261,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts
index d264fd5f62..4afabdb325 100644
--- a/src/qt/locale/bitcoin_uz@Cyrl.ts
+++ b/src/qt/locale/bitcoin_uz@Cyrl.ts
@@ -45,10 +45,74 @@
<source>&amp;Delete</source>
<translation>&amp;Ўчириш</translation>
</message>
- </context>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Тангаларни жўнатиш учун манзилни танланг</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Тангаларни қабул қилиш учун манзилни танланг</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>&amp;Танлаш</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Жўнатиладиган манзиллар</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <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>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>Манзилдан &amp;нусха олиш</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Нусха олиш ва ёрлиқ</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Таҳрирлаш</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Манзил рўйхатини экспорт қилиш</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Вергул билан ажратилган файл (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Экспорт қилиб бўлмади</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Манзил рўйхатини %1.га сақлашда хатолик юз берди. Яна уриниб кўринг.</translation>
+ </message>
+</context>
<context>
<name>AddressTableModel</name>
- </context>
+ <message>
+ <source>Label</source>
+ <translation>Ёрлиқ</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Манзил</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(Ёрлиқ мавжуд эмас)</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
<message>
@@ -67,7 +131,83 @@
<source>Repeat new passphrase</source>
<translation>Янги махфий сузни такрорланг</translation>
</message>
- </context>
+ <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>
+ <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>
+ <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>Диққат: Агар сиз ҳамёнингизни кодласангиз ва махфий сўзингизни унутсангиз, сиз &lt;b&gt;БАРЧА BITCOIN ПУЛЛАРИНГИЗНИ ЙЎҚОТАСИЗ&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Ҳамёнингизни кодлашни ростдан хоҳлайсизми?</translation>
+ </message>
+ <message>
+ <source>Wallet 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>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Ҳамённи кодлаш амалга ошмади</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Ҳамённи кодлаш ташқи хато туфайли амалга ошмади. Ҳамёнингиз кодланмади.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Киритилган пароллар мос келмади.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Ҳамённи қулфдан чиқариш амалга ошмади</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Ҳамённи коддан чиқариш учун киритилган парол нотўғри.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Ҳамённи коддан чиқариш амалга ошмади</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Ҳамён пароли муваффақиятли алмаштирилди.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Диққат: Caps Lock тугмаси ёқилган!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
</context>
@@ -150,14 +290,6 @@
<translation>Паролни ўзгартириш ҳамённи кодлашда фойдаланилади</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Носозликни ҳал қилиш ойнаси</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Носозликни ҳал қилиш ва ташхис терминали</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>Хабарни &amp;тасдиқлаш...</translation>
</message>
@@ -218,10 +350,6 @@
<translation>Фойдаланилган қабул қилинган манзиллар ва ёрлиқлар рўйхатини кўрсатиш</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Bitcoin’ни очиш: URI ёки тўлов сўрови</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>&amp;Буйруқлар сатри мосламалари</translation>
</message>
@@ -285,7 +413,11 @@
<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>
- </context>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>Жиддий хато юз берди. Bitcoin хавфсиз ишлай олмайди, шунинг учун чиқиб кетилади.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -344,7 +476,83 @@
<source>Confirmed</source>
<translation>Тасдиқланди</translation>
</message>
- </context>
+ <message>
+ <source>Copy address</source>
+ <translation>Манзилни нусхалаш</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Ёрликни нусхала</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Кийматни нусхала</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Ўтказам рақамидан нусха олиш</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Сарфланмаганларни қулфлаш</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Сарфланмаганларни қулфдан чиқариш</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Нусха сони</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Нусха солиғи</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Нусха солиқдан сўнг</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Нусха байти</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Нусха чангги</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Нусха қайтими</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 қулфланган)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>ҳа</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>йўқ</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Ҳар бир кирим +/- %1 сатоши(лар) билан ўзгариши мумкин.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(Ёрлиқ мавжуд эмас)</translation>
+ </message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>%1 (%2)дан ўзгартириш</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(ўзгартириш)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
</context>
@@ -373,7 +581,31 @@
<source>&amp;Address</source>
<translation>&amp;Манзил</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Янги жунатилувчи манзил</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Кабул килувчи манзилни тахрирлаш</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Жунатилувчи манзилни тахрирлаш</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>Киритилган "%1" манзили тўғри Bitcoin манзили эмас.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Ҳамён қулфдан чиқмади.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Янги калит яратиш амалга ошмади.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
@@ -404,10 +636,6 @@
<translation>версияси</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>Command-line options</source>
<translation>Буйруқлар сатри мосламалари</translation>
</message>
@@ -453,22 +681,10 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>URI ни очиш</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>URL файлдан тўлов сўровларини очиш</translation>
- </message>
- <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Тўлов сўрови файлини танлаш</translation>
- </message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
</context>
@@ -652,6 +868,18 @@
</context>
<context>
<name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Тўлов сўрови хато</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>URI осилиб қолмоқда</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Нотўғри тўлов манзили %1</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -721,7 +949,19 @@
<source>&amp;Save Image...</source>
<translation>Расмни &amp;сақлаш</translation>
</message>
- </context>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>Расмдан &amp;нусха олиш</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation>QR кодни сақлаш</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>PNG расм (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -737,10 +977,6 @@
<translation>&amp;Маълумот</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Тузатиш ойнаси</translation>
- </message>
- <message>
<source>General</source>
<translation>Асосий</translation>
</message>
@@ -923,7 +1159,19 @@
<source>Remove</source>
<translation>Ўчириш</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>Ёрликни нусхала</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Хабарни нусхала</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Кийматни нусхала</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -939,10 +1187,34 @@
<translation>Расмни &amp;сақлаш</translation>
</message>
<message>
+ <source>Request payment to %1</source>
+ <translation> %1 дан Тўловни сўраш</translation>
+ </message>
+ <message>
+ <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>
@@ -953,6 +1225,22 @@
<source>Date</source>
<translation>Сана</translation>
</message>
+ <message>
+ <source>Label</source>
+ <translation>Ёрлиқ</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Хабар</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(Ёрлиқ мавжуд эмас)</translation>
+ </message>
+ <message>
+ <source>(no message)</source>
+ <translation>(Хабар йўқ)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -1049,10 +1337,70 @@
<translation>Жў&amp;натиш</translation>
</message>
<message>
+ <source>Copy quantity</source>
+ <translation>Нусха сони</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Кийматни нусхала</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Нусха солиғи</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Нусха солиқдан сўнг</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Нусха байти</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Нусха чангги</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Нусха қайтими</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 дан %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Жўнатишни хоҳлашингизга ишончингиз комилми?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ёки</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Ўтказма тўлови</translation>
</message>
- </context>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Тангалар жўнаишни тасдиқлаш</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Тўлов миқдори 0. дан катта бўлиши керак. </translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Диққат: Нотўғр Bitcoin манзили</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Диққат: Номаълум ўзгариш манзили</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(Ёрлиқ мавжуд эмас)</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
<message>
@@ -1072,10 +1420,6 @@
<translation>Олдин фойдаланилган манзилни танла</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Бу нормал тўлов.</translation>
- </message>
- <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -1097,13 +1441,6 @@
</message>
</context>
<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Ҳа</translation>
- </message>
-</context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
@@ -1132,29 +1469,109 @@
<source>Clear &amp;All</source>
<translation>Барчасини &amp; Тозалаш</translation>
</message>
- </context>
+ <message>
+ <source>Message verified.</source>
+ <translation>Хабар тасдиқланди.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
</context>
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>%1 гача очиш</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/тасдиқланмади</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 тасдиқлашлар</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Сана</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>Манба</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Яратилган</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>Дан</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>Номаълум</translation>
</message>
<message>
+ <source>To</source>
+ <translation>Га</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>ўз манзили</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>ёрлиқ</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Кредит (қарз)</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>қабул қилинмади</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Ўтказма тўлови</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>Умумий миқдор</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Хабар</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Шарҳ</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Савдо</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Ўтказма</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Миқдори</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>рост</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>ёлғон</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
@@ -1168,18 +1585,206 @@
<source>Date</source>
<translation>Сана</translation>
</message>
- </context>
+ <message>
+ <source>Type</source>
+ <translation>Тури</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Ёрлиқ</translation>
+ </message>
+ <message>
+ <source>Open until %1</source>
+ <translation>%1 гача очиш</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>Тасдиқланмаган</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Тасдиқланди (%1 та тасдиқ)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Яратилди, аммо қабул қилинмади</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Ёрдамида қабул қилиш</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Дан қабул қилиш</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Жўнатиш</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Ўзингизга тўлов</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Фойда</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(қ/қ)</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(Ёрлиқ мавжуд эмас)</translation>
+ </message>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Ўтказма ҳолати. Ушбу майдон бўйлаб тасдиқлашлар сонини кўрсатиш.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Ўтказма қабул қилинган сана ва вақт.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Пул ўтказмаси тури</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Миқдор ўчирилган ёки балансга қўшилган.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Барча</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Бугун</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Шу ҳафта</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Шу ой</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Ўтган хафта</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Шу йил</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Оралиқ...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Ёрдамида қабул қилиш</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Жўнатиш</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Ўзингизга</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Фойда</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Бошка</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Мин қиймат</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Манзилни нусхалаш</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Ёрликни нусхала</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Кийматни нусхала</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Ўтказам рақамидан нусха олиш</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Ёрликни тахрирлаш</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Ўтказма тафсилотларини кўрсатиш </translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>Ўтказмалар тарихини экспорт қилиш</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Вергул билан ажратилган файл (*.csv)</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation>Тасдиқланди</translation>
</message>
<message>
+ <source>Watch-only</source>
+ <translation>Фақат кўришга</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Сана</translation>
</message>
- </context>
+ <message>
+ <source>Type</source>
+ <translation>Тури</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Ёрлиқ</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Манзил</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Экспорт қилиб бўлмади</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>Ўтказмалар тарихи %1 га муваффаққиятли сақланди.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Оралиқ:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>Кимга</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
@@ -1188,7 +1793,11 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>Хали бирорта хамён юкланмади</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
diff --git a/src/qt/locale/bitcoin_fr_CA.ts b/src/qt/locale/bitcoin_uz@Latn.ts
index 235af7b3ae..fcdde25df6 100644
--- a/src/qt/locale/bitcoin_fr_CA.ts
+++ b/src/qt/locale/bitcoin_uz@Latn.ts
@@ -1,38 +1,46 @@
-<TS language="fr_CA" version="2.1">
+<TS language="uz@Latn" version="2.1">
<context>
<name>AddressBookPage</name>
<message>
<source>Create a new address</source>
- <translation>Créer une nouvelle adresse</translation>
+ <translation>Yangi manzil yaratish</translation>
</message>
<message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Copier l'adresse surligné a votre presse-papier</translation>
+ <source>&amp;New</source>
+ <translation>&amp;Yangi</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;Nusxalash</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>Yo&amp;pish</translation>
</message>
<message>
<source>&amp;Delete</source>
- <translation>&amp;Supprimer</translation>
+ <translation>&amp;O'chirish</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Manzillarni nusxalash</translation>
</message>
</context>
<context>
<name>AddressTableModel</name>
- </context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Enter passphrase</source>
- <translation>Entrer Mot de Passe</translation>
- </message>
<message>
- <source>New passphrase</source>
- <translation>Nouveau Mot de passe</translation>
+ <source>Label</source>
+ <translation>Yorliq</translation>
</message>
<message>
- <source>Repeat new passphrase</source>
- <translation>Répéter Mot de Passe</translation>
+ <source>Address</source>
+ <translation>Manzil</translation>
</message>
</context>
<context>
+ <name>AskPassphraseDialog</name>
+ </context>
+<context>
<name>BanTableModel</name>
</context>
<context>
@@ -40,21 +48,15 @@
</context>
<context>
<name>CoinControlDialog</name>
- <message>
- <source>(un)select all</source>
- <translation>Toute sélectionner </translation>
- </message>
+ </context>
+<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
</context>
<context>
<name>EditAddressDialog</name>
- <message>
- <source>&amp;Label</source>
- <translation>Record</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>Addresse</translation>
- </message>
</context>
<context>
<name>FreespaceChecker</name>
@@ -64,10 +66,6 @@
</context>
<context>
<name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Bienvenue </translation>
- </message>
</context>
<context>
<name>ModalOverlay</name>
@@ -76,6 +74,9 @@
<name>OpenURIDialog</name>
</context>
<context>
+ <name>OpenWalletActivity</name>
+ </context>
+<context>
<name>OptionsDialog</name>
</context>
<context>
@@ -91,9 +92,6 @@
<name>QObject</name>
</context>
<context>
- <name>QObject::QObject</name>
- </context>
-<context>
<name>QRImageWidget</name>
</context>
<context>
@@ -104,9 +102,21 @@
</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>
+ <message>
+ <source>Label</source>
+ <translation>Yorliq</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -115,18 +125,12 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
<name>SignVerifyMessageDialog</name>
</context>
<context>
- <name>SplashScreen</name>
- </context>
-<context>
<name>TrafficGraphWidget</name>
</context>
<context>
@@ -139,36 +143,27 @@
<name>TransactionTableModel</name>
<message>
<source>Label</source>
- <translation>Record</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(pas de record)</translation>
+ <translation>Yorliq</translation>
</message>
</context>
<context>
<name>TransactionView</name>
<message>
- <source>Copy address</source>
- <translation>copier l'adresse </translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Fichier séparé par une virgule (*.csv)</translation>
- </message>
- <message>
<source>Label</source>
- <translation>Record</translation>
+ <translation>Yorliq</translation>
</message>
<message>
<source>Address</source>
- <translation>Addresse</translation>
+ <translation>Manzil</translation>
</message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
<context>
+ <name>WalletController</name>
+ </context>
+<context>
<name>WalletFrame</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_vi.ts b/src/qt/locale/bitcoin_vi.ts
index 3ad7da9133..1d5491137b 100644
--- a/src/qt/locale/bitcoin_vi.ts
+++ b/src/qt/locale/bitcoin_vi.ts
@@ -338,14 +338,6 @@
<translation>Thay đổi cụm mật khẩu cho ví đã mã hóa</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>&amp;Debug window</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Mở trình gỡ lỗi và giao diện điều chỉnh chẩn đoán</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>&amp;Lời nhắn xác nhận...</translation>
</message>
@@ -406,12 +398,8 @@
<translation>Hiển thị danh sách các địa chỉ và nhãn đã dùng để nhận</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Mở một bitcoin: URI hoặc yêu cầu thanh toán</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
- <translation>&amp;Tùy chỉnh Command-line </translation>
+ <translation>&amp;Tùy chỉnh Command-line</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
@@ -491,7 +479,7 @@
</message>
<message>
<source>No wallets available</source>
- <translation>Không có ví nào </translation>
+ <translation>Không có ví nào</translation>
</message>
<message>
<source>&amp;Window</source>
@@ -840,10 +828,6 @@
<translation>phiên bản</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>About %1</translation>
</message>
@@ -969,29 +953,17 @@
<source>Hide</source>
<translation>Ẩn</translation>
</message>
- </context>
-<context>
- <name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>Mở URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Mở payment request từ URI hoặc file</translation>
+ <source>Unknown. Syncing Headers (%1, %2%)...</source>
+ <translation>Không biết. Đang đồng bộ Headers (%1, %2%)...</translation>
</message>
+</context>
+<context>
+ <name>OpenURIDialog</name>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>Chọn payment request file</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Chọn file payment request để mở</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1373,18 +1345,6 @@
<translation>'bitcoin://' không khả dụng URI. Dùng thay vì 'bitcoin:' .</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>Bạn đang dùng một URL BIP70 cái này không hổ trợ trong tương lai.</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Payment request dẫn đến URL thì invalid: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>Không thể tiến hành yêu cầu thanh toán bởi vì sự trợ giúp BIP70 không có biên dịch trong này.</translation>
- </message>
- <message>
<source>Invalid payment address %1</source>
<translation>Invalid payment address %1</translation>
</message>
@@ -1396,66 +1356,6 @@
<source>Payment request file handling</source>
<translation>Payment request file đang xử lý</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Payment request file không thể đọc! Đây có thể gây ra bởi một invalid payment request file.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Payment request bị từ chối</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Payment request network chưa đúng với client network.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Payment request hết hạn.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Payment request đã không được khởi tạo.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Chưa xác nhận payment request đến custom payment scripts không được hỗ trợ.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Invalid payment request.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Yêu cầu payment với lượng của %1 thì quá nhỏ (xem như dust).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Refund từ %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Payment request %1 thì quá lớn (%2 bytes, cho phép %3 bytes).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Error giao thức với %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Payment request không thể giải!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Phản hồi xấu từ server %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Mạng request error</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Payment được thừa nhận</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1633,10 +1533,6 @@
<translation>&amp;Thông tin</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>Debug window</translation>
- </message>
- <message>
<source>General</source>
<translation>Tổng thể</translation>
</message>
@@ -1650,7 +1546,7 @@
</message>
<message>
<source>To specify a non-default location of the data directory use the '%1' option.</source>
- <translation>Để chỉ ra một nơi không mặt định của thư mục dữ liệu hãy dùng tùy chọn '%1' </translation>
+ <translation>Để chỉ ra một nơi không mặt định của thư mục dữ liệu hãy dùng tùy chọn '%1'</translation>
</message>
<message>
<source>Blocksdir</source>
@@ -1658,7 +1554,7 @@
</message>
<message>
<source>To specify a non-default location of the blocks directory use the '%1' option.</source>
- <translation>Để chỉ ra một nơi không mặt định của thư mục các khối hãy dùng tùy chọn '%1' </translation>
+ <translation>Để chỉ ra một nơi không mặt định của thư mục các khối hãy dùng tùy chọn '%1'</translation>
</message>
<message>
<source>Startup time</source>
@@ -1881,6 +1777,14 @@
<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>Nhậ p %1 để biết tổng quan về các lệnh có sẵn.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Để biết thêm thông tin về việc sử dụng bảng điều khiển này, hãy nhập %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>
@@ -2161,10 +2065,6 @@
<translation>Warning: Fee ước tính hiện tại không khả thi.</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>gộp fee-settings</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>
@@ -2314,7 +2214,7 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
</message>
<message>
<source>Total Amount</source>
- <translation>Tổng số </translation>
+ <translation>Tổng số</translation>
</message>
<message>
<source>To review recipient list click "Show Details..."</source>
@@ -2349,10 +2249,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Transaction khởi tạo thất bại!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>The transaction đã bị từ chối với lý do sau: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>Một fee lớn hơn %1 được coi là ngớ ngẩn cao fee.</translation>
</message>
@@ -2404,10 +2300,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Chọn mới thì address</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>Đây là một thông thường payment.</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>The Bitcoin address để gửi the payment đến</translation>
</message>
@@ -2467,17 +2359,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<source>Memo:</source>
<translation>Bản ghi nhớ:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Nhập một label cho address này để thêm vào address book</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Yes</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -3206,10 +3087,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>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</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>
@@ -3366,6 +3243,10 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Initialization sanity check failed. %s is shutting down.</translation>
</message>
<message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Quyền P2P không hợp lệ: '%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>
@@ -3510,10 +3391,26 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Reducing -maxconnections from %d to %d, because of system limitations.</translation>
</message>
<message>
+ <source>Section [%s] is not recognized.</source>
+ <translation>Mục [%s] không được nhìn nhận.</translation>
+ </message>
+ <message>
<source>Signing transaction failed</source>
<translation>Signing transaction failed</translation>
</message>
<message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Thư mục ví được nêu -walletdir "%s" không tồn tại</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Chỉ định -walletdir "%s" là đường dẫn tương đối</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Chỉ định -walletdir "%s" không phải là một thư mục</translation>
+ </message>
+ <message>
<source>The specified config file %s does not exist
</source>
<translation>Tệp cấu hình đã chỉ định %s không tồn tại
@@ -3572,10 +3469,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>This is the transaction fee you may pay when fee estimates are not available.</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</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>
diff --git a/src/qt/locale/bitcoin_vi_VN.ts b/src/qt/locale/bitcoin_vi_VN.ts
deleted file mode 100644
index c9f9ca2add..0000000000
--- a/src/qt/locale/bitcoin_vi_VN.ts
+++ /dev/null
@@ -1,1250 +0,0 @@
-<TS language="vi_VN" version="2.1">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation>Nhấn chuột phải để sửa địa chỉ hoặc nhãn</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation>Tạo một địa chỉ mới</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation>&amp;Tạo mới</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation>Copy địa chỉ được chọn vào clipboard</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation>&amp;Copy</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation>Đó&amp;ng</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation>Xóa địa chỉ hiện tại từ danh sách</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation>Xuất dữ liệu trong mục hiện tại ra file</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Xuất</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation>&amp;Xóa</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation>Chọn địa chỉ để gửi coin đến</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation>Chọn địa chỉ để nhận coin</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation>Chọn</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation>Địa chỉ gửi đến</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation>Địa chỉ nhận</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>Đây là các địa chỉ Bitcoin để gửi bạn gửi tiền. Trước khi gửi bạn nên kiểm tra lại số tiền bạn muốn gửi và địa chỉ bitcoin của người nhận.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Đây là các địa chỉ Bitcoin để bạn nhận tiền. Với mỗi giao dịch, bạn nên dùng một địa chỉ Bitcoin mới để nhận tiền.</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation>&amp;Chép Địa chỉ</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation>Chép &amp;Nhãn</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation>&amp;Sửa</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation>Xuất Danh Sách Địa Chỉ</translation>
- </message>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Các tệp tác nhau bằng đấu phẩy (* .csv)</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Xuất không thành công</translation>
- </message>
- </context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation>Nhãn</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Địa chỉ</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(không nhãn)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation>Hội thoại Passphrase</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation>Điền passphrase</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation>Passphrase mới</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation>Điền lại passphrase</translation>
- </message>
- <message>
- <source>Show password</source>
- <translation>Hiện mật khẩu</translation>
- </message>
- <message>
- <source>Enter the new passphrase to 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>Nhập passphrase mới cho Ví của bạn.&lt;br/&gt;Vui long dùng passphrase gồm&lt;b&gt;ít nhất 10 ký tự bất kỳ &lt;/b&gt;, hoặc &lt;b&gt;ít nhất 8 chữ&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation>Mã hóa ví</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Thao tác này cần cụm từ mật khẩu để mở khóa ví.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation>Mở khóa ví</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Thao tác này cần cụm mật khẩu ví của bạn để giải mã ví.</translation>
- </message>
- <message>
- <source>Decrypt wallet</source>
- <translation>Giải mã ví</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation>Đổi cụm mật khẩu</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Nhập cụm từ mật khẩu cũ và cụm mật khẩu mới vào ví.</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation>Xác nhận mã hóa ví</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Bạn có chắc chắn muốn mã hóa ví của bạn?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation>Ví đã được mã hóa</translation>
- </message>
- <message>
- <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation>QUAN TRỌNG: Bất kỳ bản sao lưu trước nào bạn đã làm từ tệp ví tiền của bạn phải được thay thế bằng tệp ví tiền mới được tạo và mã hóa. Vì lý do bảo mật, các bản sao lưu trước đó của tệp ví tiền không được mã hóa sẽ trở nên vô dụng ngay khi bạn bắt đầu sử dụng ví đã được mã hóa.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation>Mã hóa ví không thành công</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Mã hóa ví không thành công do có lỗi bên trong.
-Ví của bạn chưa được mã hóa.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Cụm mật khẩu được cung cấp không khớp.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation>Mở khóa ví không thành công</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Cụm từ mật mã nhập vào không đúng</translation>
- </message>
- <message>
- <source>Wallet decryption failed</source>
- <translation>Giải mã ví không thành công</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Cụm từ mật khẩu mã hóa của ví đã được thay đổi.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Chú ý: Caps Lock đang được bật!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation>IP/Netmask</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation>Bị cấm đến</translation>
- </message>
-</context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>Sign &amp;message...</source>
- <translation>Chứ ký &amp; Tin nhắn...</translation>
- </message>
- <message>
- <source>Synchronizing with network...</source>
- <translation>Đồng bộ hóa với mạng</translation>
- </message>
- <message>
- <source>&amp;Overview</source>
- <translation>&amp;Tổng quan</translation>
- </message>
- <message>
- <source>Node</source>
- <translation>Node</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation>Hiện thỉ thông tin sơ lược chung về Ví</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation>&amp;Giao dịch</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation>Duyệt tìm lịch sử giao dịch</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation>T&amp;hoát</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation>Thoát chương trình</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation>&amp;Thông tin về %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Hiện thông tin về %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation>Về &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation>Xem thông tin về Qt</translation>
- </message>
- <message>
- <source>&amp;Options...</source>
- <translation>&amp;Tùy chọn...</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation>Chỉnh sửa thiết đặt tùy chọn cho %1</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Mã hóa ví tiền</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Sao lưu ví tiền...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Thay đổi mật khẩu...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Địa chỉ gửi</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Địa chỉ nhận</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Mở &amp;URI...</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Nhấp để vô hiệu hóa kết nối mạng.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Kết nối mạng đã bị ngắt</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Nhấp để kết nối lại mạng.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Đồng bộ hóa các Headers (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Đánh chỉ số (indexing) lại các khối (blocks) trên ổ đĩa ...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Gửi coins đến tài khoản Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Sao lưu ví tiền ở vị trí khác</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Thay đổi cụm mật mã dùng cho mã hoá Ví</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Cửa sổ xử lý lỗi (debug)</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Mở trình gỡ lỗi và bảng lệnh chuẩn đoán</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Tin nhắn xác thực</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Ví</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Gửi</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Nhận</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>Ẩn / H&amp;iện</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Hiện hoặc ẩn cửa sổ chính</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Mã hoá các khoá bí mật trong Ví của bạn.</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Dùng địa chỉ Bitcoin của bạn ký các tin nhắn để xác minh những nội dung tin nhắn đó là của bạn.</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Kiểm tra các tin nhắn để chắc chắn rằng chúng được ký bằng các địa chỉ Bitcoin xác định.</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;File</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Thiết lập</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>Trợ &amp;giúp</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Thanh công cụ (toolbar)</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Yêu cầu thanh toán(tạo mã QR và địa chỉ Bitcoin: URLs)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Hiện thỉ danh sách các địa chỉ và nhãn đã dùng để gửi.</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Hiện thỉ danh sách các địa chỉ và nhãn đã dùng để nhận.</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Mở bitcoin:URL hoặc yêu cầu thanh toán</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>7Tùy chọn dòng lệnh</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n liên kết hoạt động với mạng lưới Bitcoin</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Đang lập chỉ mục các khối trên ổ đĩa</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Đang xử lý các khối trên ổ đĩa...</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>Đã xử lý %n khối của lịch sử giao dịch.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 chậm trễ</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Khối (block) cuối cùng nhận được cách đây %1</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Những giao dịch sau đó sẽ không hiện thị.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Lỗi</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Chú ý</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Thông tin</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Đã cập nhật</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Hiển thị tin nhắn trợ giúp %1 để có được danh sách với các tùy chọn dòng lệnh Bitcoin.</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Kết nối với các máy ngang hàng...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Bắt kịp...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Ngày: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Số lượng: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Loại: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Nhãn hiệu: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Địa chỉ: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Giao dịch đã gửi</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Giao dịch đang tới</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>Ví tiền &lt;b&gt; đã được mã hóa&lt;/b&gt;và hiện &lt;b&gt;đang mở&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>Ví tiền &lt;b&gt; đã được mã hóa&lt;/b&gt;và hiện &lt;b&gt;đang khóa&lt;/b&gt;</translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Quantity:</source>
- <translation>Lượng:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Lượng:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Phí:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Sau thuế, phí:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Thay đổi:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>(bỏ)chọn tất cả</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Chế độ cây</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Chế độ danh sách</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Lượng</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Ngày tháng</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Lần xác nhận</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Đã xác nhận</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(không nhãn)</translation>
- </message>
- </context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Thay đổi địa chỉ</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>Nhãn</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>Địa chỉ</translation>
- </message>
- </context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>name</source>
- <translation>tên</translation>
- </message>
- </context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>version</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-bit)</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>&amp;Tùy chọn dòng lệnh</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>Welcome</source>
- <translation>Chào mừng</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Sử dụng vị trí dữ liệu mặc định</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Lỗi</translation>
- </message>
- </context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Form</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Ẩn</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Mở URI</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- </context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation>Lựa chọn</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Chính</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>MB</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Địa chỉ IP của proxy (ví dụ IPv4: 127.0.0.1 / IPv6: ::1)</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>Ví</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Kết nối đến máy chủ Bitcoin thông qua SOCKS5 proxy.</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>Proxy &amp;IP:</translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>&amp;Cổng:</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Cổng proxy (e.g. 9050) </translation>
- </message>
- <message>
- <source>IPv4</source>
- <translation>IPv4</translation>
- </message>
- <message>
- <source>IPv6</source>
- <translation>IPv6</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>&amp;Hiển thị</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>Giao diện người dùng &amp; ngôn ngữ</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;OK</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Từ chối</translation>
- </message>
- <message>
- <source>default</source>
- <translation>mặc định</translation>
- </message>
- <message>
- <source>none</source>
- <translation>Trống</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Lỗi</translation>
- </message>
- </context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Form</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Khả dụng</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>Đang chờ</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Tổng:</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>User Agent</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Đã gửi</translation>
- </message>
- </context>
-<context>
- <name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Lượng</translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 và %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>
- </context>
-<context>
- <name>QObject::QObject</name>
- </context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>$Lưu hình ảnh...</translation>
- </message>
- </context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>&amp;Information</source>
- <translation>Thông tin</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Nhìn Chung</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Tên</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Block chain</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Đã gửi</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>User Agent</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1&amp;giờ</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1&amp;ngày</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1&amp;tuần</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1&amp;năm</translation>
- </message>
- <message>
- <source>never</source>
- <translation>không bao giờ</translation>
- </message>
- <message>
- <source>Yes</source>
- <translation>Đồng ý</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Không</translation>
- </message>
- </context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation>Lượng:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Nhãn</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Tin nhắn:</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Sử dụng form này để yêu cầu thanh toán. Tất cả các trường &lt;b&gt;không bắt buộc&lt;b&gt;</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Xóa tất cả các trường trong biểu mẫu</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation>Xóa</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation>Lịch sử yêu cầu thanh toán</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Yêu cầu thanh toán</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Hiển thị</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Xóa khỏi danh sách</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Xóa</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Copy tin nhắn</translation>
- </message>
- </context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>QR Code</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Copy &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Copy Địa Chỉ</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>$Lưu hình ảnh...</translation>
- </message>
- <message>
- <source>Request payment to %1</source>
- <translation>Yêu cầu thanh toán cho %1</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation>Thông tin thanh toán</translation>
- </message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Địa chỉ</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>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>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation>Lỗi khi encode từ URI thành QR Code</translation>
- </message>
-</context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Label</source>
- <translation>Nhãn</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Tin nhắn</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(không nhãn)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation>(không tin nhắn)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation>Gửi Coins</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Tính năng Control Coin</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Nhập...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>Tự động chọn</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Không đủ tiền</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Lượng:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Bytes:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Lượng:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Phí:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>Sau thuế, phí:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Thay đổi:</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
- <translation>Phí giao dịch</translation>
- </message>
- <message>
- <source>Choose...</source>
- <translation>Chọn...</translation>
- </message>
- <message>
- <source>collapse fee-settings</source>
- <translation>Thu gọn fee-settings</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>trên KB</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Ẩn</translation>
- </message>
- <message>
- <source>(read the tooltip)</source>
- <translation>(Đọc hướng dẫn)</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Gửi đến nhiều người nhận trong một lần</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>Thêm &amp;Người nhận</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Xóa tất cả các trường trong biểu mẫu</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Xóa &amp;Tất cả</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Tài khoản</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Xác nhận sự gửi</translation>
- </message>
- <message>
- <source>%1 to %2</source>
- <translation>%1 đến %2</translation>
- </message>
- <message>
- <source>or</source>
- <translation>hoặc</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation>Xác nhận gửi coins</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(không nhãn)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>Lượng:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Nhãn</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Đồng ý</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Clear &amp;All</source>
- <translation>Xóa &amp;Tất cả</translation>
- </message>
- </context>
-<context>
- <name>SplashScreen</name>
- </context>
-<context>
- <name>TrafficGraphWidget</name>
- </context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>Message</source>
- <translation>Tin nhắn</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Lượng</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Label</source>
- <translation>Nhãn</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation>(không nhãn)</translation>
- </message>
- </context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>Comma separated file (*.csv)</source>
- <translation>Các tệp tác nhau bằng đấu phẩy (* .csv)</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Nhãn</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Địa chỉ</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation>Xuất không thành công</translation>
- </message>
- </context>
-<context>
- <name>UnitDisplayStatusBarControl</name>
- </context>
-<context>
- <name>WalletFrame</name>
- </context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Gửi Coins</translation>
- </message>
- </context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation>&amp;Xuất</translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Thông tin</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Giao dịch quá lớn</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Chú ý</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation>Không đủ tiền</translation>
- </message>
- <message>
- <source>Loading block index...</source>
- <translation>Đang đọc block index...</translation>
- </message>
- <message>
- <source>Loading wallet...</source>
- <translation>Đang đọc ví...</translation>
- </message>
- <message>
- <source>Cannot downgrade wallet</source>
- <translation>Không downgrade được ví</translation>
- </message>
- <message>
- <source>Rescanning...</source>
- <translation>Đang quét lại...</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation>Đã nạp xong</translation>
- </message>
- <message>
- <source>Error</source>
- <translation>Lỗi</translation>
- </message>
-</context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_yo.ts b/src/qt/locale/bitcoin_yo.ts
index 2e2c1657f7..7094d2b3b4 100644
--- a/src/qt/locale/bitcoin_yo.ts
+++ b/src/qt/locale/bitcoin_yo.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>&amp;New</source>
- <translation>ati tuntun </translation>
+ <translation>&amp;ati tuntun</translation>
</message>
</context>
<context>
@@ -80,7 +80,7 @@
<name>OptionsDialog</name>
<message>
<source>&amp;OK</source>
- <translation>o da</translation>
+ <translation>&amp;o da</translation>
</message>
</context>
<context>
@@ -99,7 +99,7 @@
<name>QRImageWidget</name>
<message>
<source>&amp;Save Image...</source>
- <translation>fi aworan pamo</translation>
+ <translation>fi aworan &amp;pamo</translation>
</message>
</context>
<context>
@@ -110,7 +110,7 @@
</message>
<message>
<source>1 &amp;year</source>
- <translation>okan ati odun</translation>
+ <translation>okan ati &amp;odun</translation>
</message>
</context>
<context>
@@ -120,7 +120,7 @@
<name>ReceiveRequestDialog</name>
<message>
<source>&amp;Save Image...</source>
- <translation>fi aworan pamo</translation>
+ <translation>fi aworan &amp;pamo</translation>
</message>
</context>
<context>
@@ -137,9 +137,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_zh-Hans.ts b/src/qt/locale/bitcoin_zh-Hans.ts
index 20c948c432..5e2595eea3 100644
--- a/src/qt/locale/bitcoin_zh-Hans.ts
+++ b/src/qt/locale/bitcoin_zh-Hans.ts
@@ -213,9 +213,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_zh.ts b/src/qt/locale/bitcoin_zh.ts
new file mode 100644
index 0000000000..409cb3a2bb
--- /dev/null
+++ b/src/qt/locale/bitcoin_zh.ts
@@ -0,0 +1,1373 @@
+<TS language="zh" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>右键单击来编辑地址或者标签</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>创建一个新地址</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;新建</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>复制当前已选地址到系统剪切板</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;复制</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>关&amp;闭</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <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>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;导出</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;删除</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>选择想要发送币的地址</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>选择接收币的地址</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>选&amp;择</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>发送地址</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <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>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>复制 &amp;标记</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;编辑</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>导出地址列表</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>逗号分隔的文件 (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>导出失败</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>试图将地址列表保存为%1时出错。请再试一次。</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>标签</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>地址</translation>
+ </message>
+ <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>
+ <message>
+ <source>New passphrase</source>
+ <translation>新密码</translation>
+ </message>
+ <message>
+ <source>Repeat new 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>
+ <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>
+ <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>注意:如果你加密了钱包,丢失了密码,您将&lt;b&gt;丢失所有的比特币。</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>确定要加密您的钱包吗?</translation>
+ </message>
+ <message>
+ <source>Wallet 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>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>钱包加密失败</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>由于内部错误,钱包加密失败。您的钱包没有加密。</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>提供的密码不匹配。</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>钱包解锁失败</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>输入的钱包密码不正确。</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>钱包解密失败</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>钱包密码更改成功。</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>注意:大写锁定键打开了!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/子网掩码</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>禁止到</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>签名 &amp;消息...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>与网络同步...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;概述</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>显示钱包的一般概述</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;交易</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>浏览交易历史</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>退&amp;出</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>退出应用</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>&amp;关于 %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>显示关于%1的信息</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>关于 &amp;Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>显示关于 Qt 的信息</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>&amp;选项</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;加密钱包...</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>&amp;备份钱包...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>&amp;修改密码...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>打开 &amp;URI...</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>钱包:</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>单击禁用网络活动。</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>禁用网络活动。</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>单击再次启用网络活动。</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>正在同步Headers (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>重新索引磁盘上的区块...</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>启用代理:%1</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>发送比特币到一个比特币地址</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>备份钱包到另一个位置</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>更改钱包密码</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;验证消息...</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;发送</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;接受</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;显示 / 隐藏</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>显示或隐藏主窗口</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>加密您的钱包私钥</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>用您的比特币地址签名信息,以证明拥有它们</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>验证消息,确保它们是用指定的比特币地址签名的</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;文件</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>&amp;设置</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>&amp;帮助</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>标签工具栏</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>请求支付(生成二维码和比特币链接)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>显示使用过的发送地址或标签的列表</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>显示使用接收的地址或标签的列表</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>&amp;命令行选项</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>索引磁盘上的区块...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>处理磁盘上的区块...</translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 落后</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>上次接收到的块是在%1之前生成的。</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>之后的交易还不可见。</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>错误</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>警告</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>消息</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation>最新的</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation>&amp;发送地址</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation>&amp;接受地址</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <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>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>显示%1帮助消息以获得可能包含Bitcoin命令行选项的列表</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>默认钱包</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation>无可用钱包</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;窗口</translation>
+ </message>
+ <message>
+ <source>Minimize</source>
+ <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>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>连接到节点...</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>日期:%1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>总计:%1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>钱包:%1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>类型:%1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>标签:%1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>地址:%1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>发送交易</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>入账交易</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>HD密钥生成 &lt;b&gt;被允许&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>HD密钥生成 &lt;b&gt;被禁止&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <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>
+ <translation>钱包是&lt;b&gt;加密的&lt;/b&gt;,目前&lt;b&gt;已解锁&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation>钱包是&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>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Coin Selection</source>
+ <translation>币种选择</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>数量:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>字节:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>总计:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>手续费:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>粉尘:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>扣除费用后:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>变化:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>(未)选择所有</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>树模式</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>列表模式</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>总计</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>日期</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation>确认数</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>确认</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>复制地址</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>复制标签</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>复制金额</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>复制交易 ID</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>锁定未消费的</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>解锁未消费</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>复制数量</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>复制费用</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>复制扣除费用</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>复制字节</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>复制改变</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 锁住)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>是</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>否</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>如果任何接收方接收到的金额小于当前粉尘交易的阈值,则此标签将变为红色。</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>每个输入可以改变+/- %1 satoshi(s)。</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(没有标签)</translation>
+ </message>
+ </context>
+<context>
+ <name>CreateWalletActivity</name>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation>编辑地址</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;标签</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation>与此地址列表关联的标签</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>与此地址列表项关联的地址。只能修改为发送地址。</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;地址</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>新的发送地址</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>编辑接收地址</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>编辑发送地址</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>输入的地址"%1"不是有效的比特币地址。</translation>
+ </message>
+ <message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>地址“%1”作为标签为“%2”的接收地址已存在,无法新增为发送地址。</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>输入的地址“%1”在标签为“%2”的地址簿中已存在</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>不能解锁钱包</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>新的密钥生成失败</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation>新的数据目录将创建</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation>名称</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>目录已存在。如果你打算在此创建新目录,添加 %1。</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>路径已存在,并非目录。</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>无法在此创建数据目录。</translation>
+ </message>
+</context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation>版本</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation>关于 %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>命令行选项</translation>
+ </message>
+</context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Welcome</source>
+ <translation>欢迎</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation>欢迎到 %1。</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>使用默认的数据目录</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>使用自定数据目录</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>比特币</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>错误</translation>
+ </message>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation>表格</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>未知...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>最后的区块时间</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>计算中...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>估计的同步剩余时间</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>隐藏</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ <message>
+ <source>URI:</source>
+ <translation>URI: </translation>
+ </message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>default wallet</source>
+ <translation>默认钱包</translation>
+ </message>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>正在打开钱包&lt;b&gt;%1&lt;/b&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>Options</source>
+ <translation>选项</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation>&amp;主要</translation>
+ </message>
+ <message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>登录系统后自动开始 %1。</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>&amp;数据库缓存的大小</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation>脚本 &amp;验证线程的数量</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>从系统托盘中隐藏图标</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;隐藏托盘图标</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>打开配置文件</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>重置所有客户端选项为默认</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation>&amp;重置选项</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation>&amp;网络</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation>钱&amp;包</translation>
+ </message>
+ <message>
+ <source>Expert</source>
+ <translation>专家</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>&amp;通过 SOCKS5 代理连接(默认代理)</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation>代理 &amp;IP:</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation>&amp;端口</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;窗口</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>错误</translation>
+ </message>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Form</source>
+ <translation>表格</translation>
+ </message>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>总计</translation>
+ </message>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>Last block time</source>
+ <translation>最后的区块时间</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;小时</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;天</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp;周</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp;年</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;断开连接</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Amount:</source>
+ <translation>&amp;总计:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;标签:</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation>&amp;消息:</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>复制标签</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>复制金额</translation>
+ </message>
+</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>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>日期</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>标签</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(没有标签)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation>余额不足</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>数量:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>字节:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>总计:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>手续费:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>扣除费用后:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>变化:</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>选择...</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>警告:目前无法估算费用。</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>指定交易虚拟大小的每kB(1,000字节)的自定义费用。
+注意:由于费用是按字节计算的,对于大小为500字节(1 kB的一半)的交易,“每kB 100 satoshis”的费用最终只会产生50 satoshis的费用。</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>隐藏</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation>一次发送到多个接收</translation>
+ </message>
+ <message>
+ <source>Dust:</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>
+ <message>
+ <source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
+ <translation>太低的费用可能导致永远无法确认交易(阅读工具提示)</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>目标确认时间:</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>通过 Replace-By-Fee (BIP-125) 您可以在交易发送后增加交易费用。没有这个,可能会建议收取更高的费用,以补偿交易延迟风险的增加。</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>复制数量</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>复制金额</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>复制费用</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>复制扣除费用</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>复制字节</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>复制改变</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>确定发送么?</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>稍后您可以增加费用( 信号 Replace-By-Fee,BIP-125)。</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>请检查您的交易。</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>手续费</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>收款人地址无效,请再次确认。</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>支付的总额必须大于0。</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>总额超过你的余额。</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>当包含%1交易费用时,总额超过你的余额。</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>发现重复地址:每个地址只能使用一次。</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>交易创建失败!</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>高于%1的手续费被认为非常高的手续费。</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>支付请求已过期。</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <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>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(没有标签)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;标签:</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>选择以前使用的地址</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</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>
+ <message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>这是一个未经身份验证的付款请求。</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <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>
+ <translation>附在比特币上的消息:URI将与交易一起存储,供参考。注意:此信息不会通过比特币网络发送。</translation>
+ </message>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>选择以前使用的地址</translation>
+ </message>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Date</source>
+ <translation>日期</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>手续费</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>总计</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>日期</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>标签</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(没有标签)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Copy address</source>
+ <translation>复制地址</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>复制标签</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>复制金额</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>复制交易 ID</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>逗号分隔的文件 (*.csv)</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>确认</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>日期</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>标签</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>地址</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>导出失败</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation>关闭钱包</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <source>default wallet</source>
+ <translation>默认钱包</translation>
+ </message>
+</context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;导出</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>将当前选项卡中的数据导出到文件</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Transaction too large</source>
+ <translation>超额转账</translation>
+ </message>
+ <message>
+ <source>Insufficient funds</source>
+ <translation>余额不足</translation>
+ </message>
+ <message>
+ <source>Loading wallet...</source>
+ <translation>正在载入钱包...</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>再次扫描...</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation>载入完成</translation>
+ </message>
+</context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts
index 910c33a4d4..2c534d9162 100644
--- a/src/qt/locale/bitcoin_zh_CN.ts
+++ b/src/qt/locale/bitcoin_zh_CN.ts
@@ -374,14 +374,6 @@
<translation>修改钱包加密密码</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>调试窗口(&amp;D)</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>打开调试和诊断控制台</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>验证消息(&amp;V)...</translation>
</message>
@@ -442,10 +434,6 @@
<translation>显示用过的收款地址和标签的列表</translation>
</message>
<message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>打开一个 bitcoin: URI 或支付请求</translation>
- </message>
- <message>
<source>&amp;Command-line options</source>
<translation>命令行选项(&amp;C)</translation>
</message>
@@ -467,7 +455,7 @@
</message>
<message>
<source>%1 behind</source>
- <translation>落后 %1 </translation>
+ <translation>落后 %1</translation>
</message>
<message>
<source>Last received block was generated %1 ago.</source>
@@ -494,6 +482,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>付款地址(&amp;S)</translation>
</message>
@@ -502,6 +498,10 @@
<translation>收款地址(&amp;R)</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>打开bitcoin:开头的URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>打开钱包</translation>
</message>
@@ -924,10 +924,6 @@
<translation>版本</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1 位)</translation>
- </message>
- <message>
<source>About %1</source>
<translation>关于 %1</translation>
</message>
@@ -1000,7 +996,7 @@
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>错误:无法创建指定的数据目录 "%1" </translation>
+ <translation>错误:无法创建指定的数据目录 "%1"</translation>
</message>
<message>
<source>Error</source>
@@ -1066,6 +1062,14 @@
<translation>隐藏</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目前正在同步中。它会从其他节点下载区块头和区块数据并进行验证,直到抵达区块链尖端。</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>未知。正在同步区块头 (%1, %2%)...</translation>
</message>
@@ -1073,25 +1077,13 @@
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>打开 URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>从文件或URI打开支付请求</translation>
+ <source>Open bitcoin URI</source>
+ <translation>打开比特币URI</translation>
</message>
<message>
<source>URI:</source>
<translation>URI:</translation>
</message>
- <message>
- <source>Select payment request file</source>
- <translation>选择支付请求文件 </translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>选择要打开的支付请求文件</translation>
- </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1439,7 +1431,7 @@
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>您当前在仅观察观察地址中的余额 </translation>
+ <translation>您当前在仅观察观察地址中的余额</translation>
</message>
<message>
<source>Spendable:</source>
@@ -1459,7 +1451,7 @@
</message>
<message>
<source>Current total balance in watch-only addresses</source>
- <translation>仅观察地址中的当前总余额 </translation>
+ <translation>仅观察地址中的当前总余额</translation>
</message>
</context>
<context>
@@ -1481,20 +1473,12 @@
<translation>‘bitcoin://’不是合法的URI。请改用'bitcoin:'。</translation>
</message>
<message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>你正在使用BIP70 URL,以后将不再支持这个功能。</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>取得付款请求的 URL 无效: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>无法处理支付请求,因为编译时没有启用BIP70支持。</translation>
+ <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>
+ <translation>由于BIP70具有广泛的安全缺陷,无论哪个商家指引要求您更换钱包,我们都建议您不要听信。</translation>
</message>
<message>
<source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
@@ -1512,66 +1496,6 @@
<source>Payment request file handling</source>
<translation>支付请求文件处理</translation>
</message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>无法读取支付请求文件!可能是支付请求文件无效造成的。</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>支付请求已被拒绝</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>支付请求的网络类型跟客户端不符。</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>支付请求已过期。</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>支付请求未初始化。</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>不支持到自定义付款脚本的未验证支付请求。</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>无效的支付请求。</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>请求支付的金额 %1 太小 (被视作粉尘)。</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>来自 %1 的退款</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>支付请求 %1 过大 (%2 字节。只允许 %3 字节)。</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>与 %1 通信出错: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>无法解析支付请求!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>来自服务器 %1 的响应无效</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>网络请求出错</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>付款已确认</translation>
- </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1749,10 +1673,6 @@
<translation>信息(&amp;I)</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>调试窗口</translation>
- </message>
- <message>
<source>General</source>
<translation>常规</translation>
</message>
@@ -1873,6 +1793,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>
@@ -2084,6 +2008,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;C)</translation>
</message>
@@ -2282,7 +2214,7 @@
</message>
<message>
<source>Choose...</source>
- <translation>选择... </translation>
+ <translation>选择...</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>
@@ -2293,10 +2225,6 @@
<translation>警告: 目前无法进行手续费估计。</translation>
</message>
<message>
- <source>collapse fee-settings</source>
- <translation>将费用设置收起</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>
@@ -2341,6 +2269,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>
@@ -2409,6 +2341,14 @@ 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>创建未签名交易(&amp;E)</translation>
+ </message>
+ <message>
+ <source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
+ <translation>创建一个“部分签名比特币交易”(PSBT),以用于像是离线%1钱包,或是兼容PSBT的硬件钱包这种用途。</translation>
+ </message>
+ <message>
<source> from wallet '%1'</source>
<translation>从钱包%1</translation>
</message>
@@ -2421,10 +2361,18 @@ 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>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>
+ </message>
+ <message>
<source>or</source>
<translation>或</translation>
</message>
@@ -2457,6 +2405,26 @@ 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>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>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>接收人地址无效。请重新检查。</translation>
</message>
@@ -2481,10 +2449,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>交易创建失败!</translation>
</message>
<message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>交易因以下原因被拒绝: %1</translation>
- </message>
- <message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation>超过 %1 的手续费被视为高得离谱。</translation>
</message>
@@ -2536,10 +2500,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>选择以前用过的地址</translation>
</message>
<message>
- <source>This is a normal payment.</source>
- <translation>这是笔正常的付款。</translation>
- </message>
- <message>
<source>The Bitcoin address to send the payment to</source>
<translation>付款目的地址</translation>
</message>
@@ -2560,6 +2520,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>
@@ -2599,17 +2563,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Memo:</source>
<translation>附言:</translation>
</message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>为这个地址输入一个标签,以便将它添加到您的地址簿</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>是</translation>
- </message>
</context>
<context>
<name>ShutdownWindow</name>
@@ -2638,7 +2591,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>The Bitcoin address to sign the message with</source>
- <translation>用来对消息签名的地址 </translation>
+ <translation>用来对消息签名的地址</translation>
</message>
<message>
<source>Choose previously used address</source>
@@ -2697,6 +2650,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>验证消息,确保消息是由指定的比特币地址签名过的。</translation>
</message>
@@ -2729,6 +2690,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>
@@ -2903,6 +2868,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>
@@ -3260,6 +3229,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>
@@ -3276,6 +3249,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>
@@ -3342,10 +3323,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>修剪:上次同步钱包的位置已经超出(落后于)现有修剪后数据的范围。你需要进行-reindex(对于已经启用修剪节点,就需要重新下载整个区块链)</translation>
</message>
<message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>无法在开启修剪的状态下进行重扫描,请使用 -reindex重新下载完整的区块链。</translation>
- </message>
- <message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>错误:发生了致命的内部错误,详情见 debug.log 文件</translation>
</message>
@@ -3446,6 +3423,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<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>
<translation>你想现在就重建区块数据库吗?</translation>
</message>
@@ -3603,7 +3588,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>错误:监听外部连接失败 (listen函数返回了错误 %s) </translation>
+ <translation>错误:监听外部连接失败 (listen函数返回了错误 %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>
@@ -3736,10 +3721,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>不能估计手续费时,你会付出这个手续费金额。</translation>
</message>
<message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>此产品包含了由OpenSSL Project所开发的OpenSSL Toolkit %s,由Eric Young撰写的密码学软件,以及由Thomas Bernard所撰写的UPnP软件。</translation>
- </message>
- <message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation>网络版本字符串的总长度 (%i) 超过最大长度 (%i) 了。请减少 uacomment 参数的数目或长度。</translation>
</message>
@@ -3793,7 +3774,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>
+ <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>
diff --git a/src/qt/locale/bitcoin_zh_HK.ts b/src/qt/locale/bitcoin_zh_HK.ts
index 5b714a0ed2..619cd0b768 100644
--- a/src/qt/locale/bitcoin_zh_HK.ts
+++ b/src/qt/locale/bitcoin_zh_HK.ts
@@ -306,14 +306,6 @@
<translation>改變錢包加密用的密碼</translation>
</message>
<message>
- <source>&amp;Debug window</source>
- <translation>除錯視窗 &amp;D</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>開啓除錯和診斷主控台</translation>
- </message>
- <message>
<source>&amp;Verify message...</source>
<translation>驗證訊息... &amp;V</translation>
</message>
@@ -523,10 +515,6 @@
<translation>資訊 &amp;I</translation>
</message>
<message>
- <source>Debug window</source>
- <translation>除錯視窗</translation>
- </message>
- <message>
<source>General</source>
<translation>一般</translation>
</message>
@@ -583,9 +571,6 @@
<name>SendCoinsEntry</name>
</context>
<context>
- <name>SendConfirmationDialog</name>
- </context>
-<context>
<name>ShutdownWindow</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts
index 0a6e5d6050..27c2b0c71f 100644
--- a/src/qt/locale/bitcoin_zh_TW.ts
+++ b/src/qt/locale/bitcoin_zh_TW.ts
@@ -3,71 +3,71 @@
<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;N)</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;C)</translation>
</message>
<message>
<source>C&amp;lose</source>
- <translation>关闭(&amp;l)</translation>
+ <translation>關閉(&amp;L)</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>
- <translation>将当前标签页数据导出到文件</translation>
+ <translation>把目前分頁的資料匯出存成檔案</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation>导出(&amp;E)</translation>
+ <translation>匯出(&amp;E)</translation>
</message>
<message>
<source>&amp;Delete</source>
- <translation>删除(&amp;D)</translation>
+ <translation>刪掉(&amp;D)</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;C)</translation>
+ <translation>選取(&amp;H)</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>您可以给这些比特币地址付款。在付款之前,务必要检查金额和收款地址是否正确。</translation>
+ <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>
@@ -75,105 +75,105 @@
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>复制地址(&amp;C)</translation>
+ <translation>複製位址(&amp;C)</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>复制标签(&amp;L)</translation>
+ <translation>複製標記(&amp;L)</translation>
</message>
<message>
<source>&amp;Edit</source>
- <translation>编辑(&amp;E)</translation>
+ <translation>編輯(&amp;E)</translation>
</message>
<message>
<source>Export Address List</source>
- <translation>导出地址列表</translation>
+ <translation>匯出位址清單</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>逗号分隔文件 (*.csv)</translation>
+ <translation>逗點分隔資料檔(*.csv)</translation>
</message>
<message>
<source>Exporting Failed</source>
- <translation>导出失败</translation>
+ <translation>匯出失敗</translation>
</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>
<name>AddressTableModel</name>
<message>
<source>Label</source>
- <translation>标签</translation>
+ <translation>標記</translation>
</message>
<message>
<source>Address</source>
- <translation>地址</translation>
+ <translation>位址</translation>
</message>
<message>
<source>(no label)</source>
- <translation>(无标签)</translation>
+ <translation>(無標記)</translation>
</message>
</context>
<context>
<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>
- <translation>新密码</translation>
+ <translation>新密碼</translation>
</message>
<message>
<source>Repeat new 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>
- <translation>这个操作需要你的钱包密码来解锁钱包。</translation>
+ <translation>這個動作需要你的錢包密碼來解鎖錢包。</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation>解锁钱包</translation>
+ <translation>解鎖錢包</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>这个操作需要你的钱包密码来把钱包解密。</translation>
+ <translation>這個動作需要你的錢包密碼來把錢包解密。</translation>
</message>
<message>
<source>Decrypt wallet</source>
- <translation>解密钱包</translation>
+ <translation>解密錢包</translation>
</message>
<message>
<source>Change passphrase</source>
- <translation>修改密码</translation>
+ <translation>改變密碼</translation>
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation>确认钱包加密</translation>
+ <translation>確認錢包加密</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>警告: 如果把钱包加密后又忘记密码,你就会从此&lt;b&gt;失去其中所有的比特币了&lt;/b&gt;!</translation>
+ <translation>警告: 如果把錢包加密後又忘記密碼,你就會從此&lt;b&gt;失去其中所有的 Bitcoin 了&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation>你确定要把钱包加密吗?</translation>
+ <translation>你確定要把錢包加密嗎?</translation>
</message>
<message>
<source>Wallet encrypted</source>
- <translation>钱包已加密</translation>
+ <translation>錢包已加密</translation>
</message>
<message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
@@ -181,273 +181,261 @@
</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>
+ <translation>重要須知: 請改用新造出來、有加密的錢包檔,來取代舊錢包檔的備份。為了安全起見,當你開始使用新的有加密的錢包後,舊錢包檔的備份就沒有用了。</translation>
</message>
<message>
<source>Wallet encryption failed</source>
- <translation>钱包加密失败</translation>
+ <translation>錢包加密失敗</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>因为内部错误导致钱包加密失败。你的钱包还是没加密。</translation>
+ <translation>因為內部錯誤導致錢包加密失敗。你的錢包還是沒加密。</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
- <translation>提供的密码不一致。</translation>
+ <translation>提供的密碼不一樣。</translation>
</message>
<message>
<source>Wallet unlock failed</source>
- <translation>钱包解锁失败</translation>
+ <translation>錢包解鎖失敗</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>输入用来解密钱包的密码不正确。</translation>
+ <translation>輸入要用來解密錢包的密碼不對。</translation>
</message>
<message>
<source>Wallet decryption failed</source>
- <translation>钱包解密失败</translation>
+ <translation>錢包解密失敗</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
- <translation>钱包密码修改成功。</translation>
+ <translation>錢包密碼改成功了。</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
- <translation>警告: 大写字母锁定已开启!</translation>
+ <translation>警告: 大寫字母鎖定作用中!</translation>
</message>
</context>
<context>
<name>BanTableModel</name>
<message>
<source>IP/Netmask</source>
- <translation>IP/网络掩码</translation>
+ <translation>網路位址/遮罩</translation>
</message>
<message>
<source>Banned Until</source>
- <translation>在此之前禁止:</translation>
+ <translation>禁止期限</translation>
</message>
</context>
<context>
<name>BitcoinGUI</name>
<message>
<source>Sign &amp;message...</source>
- <translation>消息签名(&amp;M)...</translation>
+ <translation>簽署訊息(&amp;M)...</translation>
</message>
<message>
<source>Synchronizing with network...</source>
- <translation>正在与网络同步...</translation>
+ <translation>正在跟網路進行同步...</translation>
</message>
<message>
<source>&amp;Overview</source>
- <translation>概况(&amp;O)</translation>
+ <translation>總覽(&amp;O)</translation>
</message>
<message>
<source>Show general overview of wallet</source>
- <translation>显示钱包概况</translation>
+ <translation>顯示錢包一般總覽</translation>
</message>
<message>
<source>&amp;Transactions</source>
- <translation>交易记录(&amp;T)</translation>
+ <translation>交易(&amp;T)</translation>
</message>
<message>
<source>Browse transaction history</source>
- <translation>查看交易历史</translation>
+ <translation>瀏覽交易紀錄</translation>
</message>
<message>
<source>E&amp;xit</source>
- <translation>退出(&amp;X)</translation>
+ <translation>結束(&amp;X)</translation>
</message>
<message>
<source>Quit application</source>
- <translation>退出程序</translation>
+ <translation>結束應用程式</translation>
</message>
<message>
<source>&amp;About %1</source>
- <translation>关于 %1</translation>
+ <translation>關於%1(&amp;A)</translation>
</message>
<message>
<source>Show information about %1</source>
- <translation>显示 %1 相关信息</translation>
+ <translation>顯示 %1 的相關資訊</translation>
</message>
<message>
<source>About &amp;Qt</source>
- <translation>关于Qt(&amp;Q)</translation>
+ <translation>關於 &amp;Qt</translation>
</message>
<message>
<source>Show information about Qt</source>
- <translation>显示 Qt 相关信息</translation>
+ <translation>顯示 Qt 相關資訊</translation>
</message>
<message>
<source>&amp;Options...</source>
- <translation>选项(&amp;O)...</translation>
+ <translation>選項(&amp;O)...</translation>
</message>
<message>
<source>Modify configuration options for %1</source>
- <translation>修改%1配置选项</translation>
+ <translation>修改 %1 的設定選項</translation>
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
- <translation>加密钱包(&amp;E)...</translation>
+ <translation>加密錢包(&amp;E)...</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>备份钱包(&amp;B)...</translation>
+ <translation>備份錢包(&amp;B)...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
- <translation>更改密码(&amp;C)...</translation>
+ <translation>改變密碼(&amp;C)...</translation>
</message>
<message>
<source>Open &amp;URI...</source>
- <translation>打开 &amp;URI...</translation>
+ <translation>開啓 &amp;URI...</translation>
</message>
<message>
<source>Wallet:</source>
- <translation>钱包:</translation>
+ <translation>錢包:</translation>
</message>
<message>
<source>Click to disable network activity.</source>
- <translation>点击禁用网络活动。</translation>
+ <translation>按一下就會不使用網路。</translation>
</message>
<message>
<source>Network activity disabled.</source>
- <translation>网络活动已禁用。</translation>
+ <translation>網路活動關閉了。</translation>
</message>
<message>
<source>Click to enable network activity again.</source>
- <translation>点击重新开启网络活动。</translation>
+ <translation>按一下就又會使用網路。</translation>
</message>
<message>
<source>Syncing Headers (%1%)...</source>
- <translation>同步区块头 (%1%)...</translation>
+ <translation>正在同步前導資料(%1%)中...</translation>
</message>
<message>
<source>Reindexing blocks on disk...</source>
- <translation>正在为区块数据重建索引...</translation>
+ <translation>正在為磁碟裡的區塊重建索引...</translation>
</message>
<message>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation>代理已被&lt;b&gt;启用&lt;/b&gt;:%1</translation>
+ <translation>代理伺服器&lt;b&gt;已經啟用&lt;/b&gt;: %1</translation>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation>向一个比特币地址发送比特币</translation>
+ <translation>付錢給一個 Bitcoin 位址</translation>
</message>
<message>
<source>Backup wallet to another location</source>
- <translation>备份钱包到其他文件夹</translation>
+ <translation>把錢包備份到其它地方</translation>
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
- <translation>更改钱包加密口令</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>调试窗口(&amp;D)</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>打开调试和诊断控制台</translation>
+ <translation>改變錢包加密用的密碼</translation>
</message>
<message>
<source>&amp;Verify message...</source>
- <translation>验证消息(&amp;V)...</translation>
+ <translation>驗證訊息(&amp;V)...</translation>
</message>
<message>
<source>&amp;Send</source>
- <translation>发送(&amp;S)</translation>
+ <translation>付款(&amp;S)</translation>
</message>
<message>
<source>&amp;Receive</source>
- <translation>接收(&amp;R)</translation>
+ <translation>收款(&amp;R)</translation>
</message>
<message>
<source>&amp;Show / Hide</source>
- <translation>显示 / 隐藏(&amp;S)</translation>
+ <translation>顯示或隱藏(&amp;S)</translation>
</message>
<message>
<source>Show or hide the main Window</source>
- <translation>显示或隐藏主窗口</translation>
+ <translation>顯示或隱藏主視窗</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
- <translation>对钱包中的私钥加密</translation>
+ <translation>把錢包中的密鑰加密</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>用比特币地址关联的私钥为消息签名,以证明您拥有这个比特币地址</translation>
+ <translation>用 Bitcoin 位址簽署訊息來證明位址是你的</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>校验消息,确保该消息是由指定的比特币地址所有者签名的</translation>
+ <translation>驗證訊息是用來確定訊息是用指定的 Bitcoin 位址簽署的</translation>
</message>
<message>
<source>&amp;File</source>
- <translation>文件(&amp;F)</translation>
+ <translation>檔案(&amp;F)</translation>
</message>
<message>
<source>&amp;Settings</source>
- <translation>设置(&amp;S)</translation>
+ <translation>設定(&amp;S)</translation>
</message>
<message>
<source>&amp;Help</source>
- <translation>帮助(&amp;H)</translation>
+ <translation>說明(&amp;H)</translation>
</message>
<message>
<source>Tabs toolbar</source>
- <translation>分页工具栏</translation>
+ <translation>分頁工具列</translation>
</message>
<message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>请求支付 (生成二维码和 bitcoin: URI)</translation>
+ <translation>要求付款(產生 QR Code 和 bitcoin 付款協議的資源識別碼: URI)</translation>
</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>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>打开一个 bitcoin: URI 或支付请求</translation>
+ <translation>顯示已使用過的收款位址和標記的清單</translation>
</message>
<message>
<source>&amp;Command-line options</source>
- <translation>命令行选项(&amp;C)</translation>
+ <translation>命令列選項(&amp;C)</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n 条到比特币网络的活动连接</numerusform></translation>
+ <translation><numerusform>%n 個運作中的 Bitcoin 網路連線</numerusform></translation>
</message>
<message>
<source>Indexing blocks on disk...</source>
- <translation>正在为区块数据建立索引...</translation>
+ <translation>正在為磁碟裡的區塊建立索引...</translation>
</message>
<message>
<source>Processing blocks on disk...</source>
- <translation>正在处理区块数据...</translation>
+ <translation>正在處理磁碟裡的區塊資料...</translation>
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>已处理 %n 个区块的交易历史</numerusform></translation>
+ <translation><numerusform>已經處理了 %n 個區塊的交易紀錄。</numerusform></translation>
</message>
<message>
<source>%1 behind</source>
- <translation>落后 %1 </translation>
+ <translation>落後 %1</translation>
</message>
<message>
<source>Last received block was generated %1 ago.</source>
- <translation>最新收到的区块产生于 %1。</translation>
+ <translation>最近收到的區塊是在 %1 以前生出來的。</translation>
</message>
<message>
<source>Transactions after this will not yet be visible.</source>
- <translation>在此之后的交易尚未可见</translation>
+ <translation>暫時會看不到在這之後的交易。</translation>
</message>
<message>
<source>Error</source>
- <translation>错误</translation>
+ <translation>錯誤</translation>
</message>
<message>
<source>Warning</source>
@@ -455,43 +443,43 @@
</message>
<message>
<source>Information</source>
- <translation>信息</translation>
+ <translation>資訊</translation>
</message>
<message>
<source>Up to date</source>
- <translation>已是最新</translation>
+ <translation>最新狀態</translation>
</message>
<message>
<source>&amp;Sending addresses</source>
- <translation>付款地址(&amp;S)</translation>
+ <translation>付款位址(&amp;S)</translation>
</message>
<message>
<source>&amp;Receiving addresses</source>
- <translation>收款地址(&amp;R)</translation>
+ <translation>收款位址(&amp;R)</translation>
</message>
<message>
<source>Open Wallet</source>
- <translation>打开钱包</translation>
+ <translation>打開錢包</translation>
</message>
<message>
<source>Open a wallet</source>
- <translation>打开一个钱包</translation>
+ <translation>打開一個錢包檔</translation>
</message>
<message>
<source>Close Wallet...</source>
- <translation>关闭钱包...</translation>
+ <translation>關上錢包...</translation>
</message>
<message>
<source>Close wallet</source>
- <translation>关闭钱包</translation>
+ <translation>關上錢包</translation>
</message>
<message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>显示 %1 帮助信息,获取可用命令行选项列表</translation>
+ <translation>顯示 %1 的說明訊息,來取得可用命令列選項的列表</translation>
</message>
<message>
<source>default wallet</source>
- <translation>默认钱包</translation>
+ <translation>預設錢包</translation>
</message>
<message>
<source>No wallets available</source>
@@ -499,11 +487,11 @@
</message>
<message>
<source>&amp;Window</source>
- <translation>窗口(&amp;W)</translation>
+ <translation>視窗(&amp;W)</translation>
</message>
<message>
<source>Minimize</source>
- <translation>最小化</translation>
+ <translation>縮小</translation>
</message>
<message>
<source>Zoom</source>
@@ -515,15 +503,15 @@
</message>
<message>
<source>%1 client</source>
- <translation>%1 客户端</translation>
+ <translation>%1 客戶端軟體</translation>
</message>
<message>
<source>Connecting to peers...</source>
- <translation>正在连接到节点……</translation>
+ <translation>正在跟其他節點連線中...</translation>
</message>
<message>
<source>Catching up...</source>
- <translation>更新中...</translation>
+ <translation>正在趕進度...</translation>
</message>
<message>
<source>Error: %1</source>
@@ -542,47 +530,48 @@
<message>
<source>Amount: %1
</source>
- <translation>金额: %1
+ <translation>金額: %1
</translation>
</message>
<message>
<source>Wallet: %1
</source>
- <translation>钱包:%1</translation>
+ <translation>錢包: %1
+</translation>
</message>
<message>
<source>Type: %1
</source>
- <translation>类型: %1
+ <translation>種類: %1
</translation>
</message>
<message>
<source>Label: %1
</source>
- <translation>标签: %1
+ <translation>標記: %1
</translation>
</message>
<message>
<source>Address: %1
</source>
- <translation>地址: %1
+ <translation>位址: %1
</translation>
</message>
<message>
<source>Sent transaction</source>
- <translation>发送交易</translation>
+ <translation>付款交易</translation>
</message>
<message>
<source>Incoming transaction</source>
- <translation>流入交易</translation>
+ <translation>收款交易</translation>
</message>
<message>
<source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>HD密钥生成&lt;b&gt;启用&lt;/b&gt;</translation>
+ <translation>產生 HD 金鑰&lt;b&gt;已經啟用&lt;/b&gt;</translation>
</message>
<message>
<source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>HD密钥生成&lt;b&gt;禁用&lt;/b&gt;</translation>
+ <translation>產生 HD 金鑰&lt;b&gt;已經停用&lt;/b&gt;</translation>
</message>
<message>
<source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
@@ -590,58 +579,58 @@
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>钱包已被&lt;b&gt;加密&lt;/b&gt;,当前为&lt;b&gt;解锁&lt;/b&gt;状态</translation>
+ <translation>錢包&lt;b&gt;已加密&lt;/b&gt;並且&lt;b&gt;解鎖中&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation>钱包已被&lt;b&gt;加密&lt;/b&gt;,当前为&lt;b&gt;锁定&lt;/b&gt;状态</translation>
+ <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>
+ <translation>發生了致命的錯誤。Bitcoin 軟體沒辦法再繼續安全執行,只好結束。</translation>
</message>
</context>
<context>
<name>CoinControlDialog</name>
<message>
<source>Coin Selection</source>
- <translation>币源选择(Coin Selection)</translation>
+ <translation>選擇錢幣</translation>
</message>
<message>
<source>Quantity:</source>
- <translation>总量:</translation>
+ <translation>數目:</translation>
</message>
<message>
<source>Bytes:</source>
- <translation>字节:</translation>
+ <translation>位元組數:</translation>
</message>
<message>
<source>Amount:</source>
- <translation>金额:</translation>
+ <translation>金額:</translation>
</message>
<message>
<source>Fee:</source>
- <translation>费用:</translation>
+ <translation>手續費:</translation>
</message>
<message>
<source>Dust:</source>
- <translation>粉尘:</translation>
+ <translation>零散錢:</translation>
</message>
<message>
<source>After Fee:</source>
- <translation>加上交易费用后:</translation>
+ <translation>計費後金額:</translation>
</message>
<message>
<source>Change:</source>
- <translation>找零 : </translation>
+ <translation>找零金額:</translation>
</message>
<message>
<source>(un)select all</source>
- <translation>全(不)选</translation>
+ <translation>全選或全不選</translation>
</message>
<message>
<source>Tree mode</source>
- <translation>树状模式</translation>
+ <translation>樹狀模式</translation>
</message>
<message>
<source>List mode</source>
@@ -649,15 +638,15 @@
</message>
<message>
<source>Amount</source>
- <translation>金额</translation>
+ <translation>金額</translation>
</message>
<message>
<source>Received with label</source>
- <translation>收款标签</translation>
+ <translation>收款標記</translation>
</message>
<message>
<source>Received with address</source>
- <translation>收款地址</translation>
+ <translation>收款位址</translation>
</message>
<message>
<source>Date</source>
@@ -665,63 +654,63 @@
</message>
<message>
<source>Confirmations</source>
- <translation>确认</translation>
+ <translation>確認次數</translation>
</message>
<message>
<source>Confirmed</source>
- <translation>已确认</translation>
+ <translation>已確認</translation>
</message>
<message>
<source>Copy address</source>
- <translation>复制地址</translation>
+ <translation>複製位址</translation>
</message>
<message>
<source>Copy label</source>
- <translation>复制标签</translation>
+ <translation>複製標記</translation>
</message>
<message>
<source>Copy amount</source>
- <translation>复制金额</translation>
+ <translation>複製金額</translation>
</message>
<message>
<source>Copy transaction ID</source>
- <translation>复制交易ID</translation>
+ <translation>複製交易識別碼</translation>
</message>
<message>
<source>Lock unspent</source>
- <translation>锁定未花费</translation>
+ <translation>鎖定不用</translation>
</message>
<message>
<source>Unlock unspent</source>
- <translation>解锁未花费</translation>
+ <translation>解鎖可用</translation>
</message>
<message>
<source>Copy quantity</source>
- <translation>复制数目</translation>
+ <translation>複製數目</translation>
</message>
<message>
<source>Copy fee</source>
- <translation>复制手续费</translation>
+ <translation>複製手續費</translation>
</message>
<message>
<source>Copy after fee</source>
- <translation>复制计费后金额</translation>
+ <translation>複製計費後金額</translation>
</message>
<message>
<source>Copy bytes</source>
- <translation>复制字节数</translation>
+ <translation>複製位元組數</translation>
</message>
<message>
<source>Copy dust</source>
- <translation>复制粉尘金额</translation>
+ <translation>複製零散金額</translation>
</message>
<message>
<source>Copy change</source>
- <translation>复制找零金额</translation>
+ <translation>複製找零金額</translation>
</message>
<message>
<source>(%1 locked)</source>
- <translation>(锁定 %1 枚)</translation>
+ <translation>(鎖定 %1 枚)</translation>
</message>
<message>
<source>yes</source>
@@ -733,15 +722,15 @@
</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>
- <translation>每组输入可能有 +/- %1 个 satoshi 的误差。</translation>
+ <translation>每組輸入可能有 +/- %1 個 satoshi 的誤差。</translation>
</message>
<message>
<source>(no label)</source>
- <translation>(无标签)</translation>
+ <translation>(無標記)</translation>
</message>
<message>
<source>change from %1 (%2)</source>
@@ -762,78 +751,78 @@
<name>EditAddressDialog</name>
<message>
<source>Edit Address</source>
- <translation>编辑地址</translation>
+ <translation>編輯位址</translation>
</message>
<message>
<source>&amp;Label</source>
- <translation>标签(&amp;L)</translation>
+ <translation>標記(&amp;L)</translation>
</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;A)</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 并不是有效的比特币地址。</translation>
+ <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 已經是標記為 %2 的收款位址了,不可以又是付款位址。</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>
- <translation>无法将钱包解锁。</translation>
+ <translation>沒辦法把錢包解鎖。</translation>
</message>
<message>
<source>New key generation failed.</source>
- <translation>生成新密钥失败。</translation>
+ <translation>產生新的密鑰失敗了。</translation>
</message>
</context>
<context>
<name>FreespaceChecker</name>
<message>
<source>A new data directory will be created.</source>
- <translation>一个新的数据目录将被创建。</translation>
+ <translation>就要產生新的資料目錄。</translation>
</message>
<message>
<source>name</source>
- <translation>名称</translation>
+ <translation>名稱</translation>
</message>
<message>
<source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>目录已存在。如果您打算在这里创建一个新目录,添加 %1。</translation>
+ <translation>已經有這個目錄了。如果你要在裡面造出新的目錄的話,請加上 %1.</translation>
</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>
- <translation>无法在此创建数据目录。</translation>
+ <translation>沒辦法在這裡造出資料目錄。</translation>
</message>
</context>
<context>
@@ -843,161 +832,141 @@
<translation>版本</translation>
</message>
<message>
- <source>(%1-bit)</source>
- <translation>(%1 位)</translation>
- </message>
- <message>
<source>About %1</source>
- <translation>关于 %1</translation>
+ <translation>關於 %1</translation>
</message>
<message>
<source>Command-line options</source>
- <translation>命令行选项</translation>
+ <translation>命令列選項</translation>
</message>
</context>
<context>
<name>Intro</name>
<message>
<source>Welcome</source>
- <translation>欢迎</translation>
+ <translation>歡迎</translation>
</message>
<message>
<source>Welcome to %1.</source>
- <translation>欢迎使用 %1</translation>
+ <translation>歡迎使用 %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>由于这是第一次启动此程序,您可以选择%1的数据所存储的位置</translation>
+ <translation>因為這是程式第一次啓動,你可以選擇 %1 儲存資料的地方。</translation>
</message>
<message>
<source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation>当你点击确认后,%1 将会在 %4 启动时从 %3 中最早的交易开始,下载并处理完整的 %4 区块链 (%2GB)。</translation>
+ <translation>在你按下「好」之後,%1 就會開始下載並處理整個 %4 區塊鏈(大小是 %2GB),也就是從 %3 年 %4 剛剛起步時的最初交易開始。</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>
+ <translation>一開始的同步作業非常的耗費資源,並且可能會暴露出之前沒被發現的電腦硬體問題。每次執行 %1 的時候都會繼續先前未完成的下載。</translation>
</message>
<message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation>如果你选择限制区块链存储大小(区块链裁剪模式),程序依然会下载并处理全部历史数据,此后才会删除不必须的部分,占用最少的存储空间。</translation>
+ <translation>如果你選擇要限制區塊鏈儲存空間的大小(修剪模式),還是需要下載和處理過去的歷史資料被,但是之後就會把它刪掉來節省磁碟使用量。</translation>
</message>
<message>
<source>Use the default data directory</source>
- <translation>使用默认的数据目录</translation>
+ <translation>使用預設的資料目錄</translation>
</message>
<message>
<source>Use a custom data directory:</source>
- <translation>使用自定义的数据目录:</translation>
+ <translation>使用自訂的資料目錄:</translation>
</message>
<message>
<source>Bitcoin</source>
- <translation>比特币</translation>
+ <translation>Bitcoin</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 GB 的数据,并且尺寸还会随着时间增长。</translation>
+ <translation>在這個目錄中至少會存放 %1 GB 的資料,並且還會隨時間增加。</translation>
</message>
<message>
<source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>会在此目录中存储约 %1 GB 的数据。</translation>
+ <translation>在這個目錄中大約會存放 %1 GB 的資料。</translation>
</message>
<message>
<source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 将会下载并存储比特币区块链。</translation>
+ <translation>%1 會下載 Bitcoin 區塊鏈並且儲存一份副本。</translation>
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
- <translation>钱包也会被保存在这个目录中。</translation>
+ <translation>錢包檔也會存放在這個目錄中。</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>错误:无法创建 指定的数据目录 "%1" </translation>
+ <translation>錯誤: 無法新增指定的資料目錄: %1</translation>
</message>
<message>
<source>Error</source>
- <translation>错误</translation>
+ <translation>錯誤</translation>
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
- <translation><numerusform>有 %n GB 空闲空间可用</numerusform></translation>
+ <translation><numerusform>可用空間尚存 %n GB</numerusform></translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
- <translation><numerusform>(需要 %n GB的空间)</numerusform></translation>
+ <translation><numerusform>(需要 %n GB)</numerusform></translation>
</message>
</context>
<context>
<name>ModalOverlay</name>
<message>
<source>Form</source>
- <translation>表单</translation>
+ <translation>表單</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>近期交易可能尚未显示,因此当前余额可能不准确。以上信息将在与比特币网络完全同步后更正。详情如下</translation>
+ <translation>最近的交易可能還看不到,因此錢包餘額可能不正確。在錢包軟體完成跟 bitcoin 網路的同步後,這裡的資訊就會正確。詳情請見下面。</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation>尝试使用受未可见交易影响的余额将不被网络接受。</translation>
+ <translation>使用還沒顯示出來的交易所影響到的 bitcoin 可能會不被網路所接受。</translation>
</message>
<message>
<source>Number of blocks left</source>
- <translation>剩余区块数量</translation>
+ <translation>剩餘區塊數</translation>
</message>
<message>
<source>Unknown...</source>
- <translation>未知</translation>
+ <translation>不明...</translation>
</message>
<message>
<source>Last block time</source>
- <translation>上一区块时间</translation>
+ <translation>最近區塊時間</translation>
</message>
<message>
<source>Progress</source>
- <translation>进度</translation>
+ <translation>進度</translation>
</message>
<message>
<source>Progress increase per hour</source>
- <translation>每小时进度增加</translation>
+ <translation>每小時進度</translation>
</message>
<message>
<source>calculating...</source>
- <translation>正在计算</translation>
+ <translation>正在計算中...</translation>
</message>
<message>
<source>Estimated time left until synced</source>
- <translation>预计剩余同步时间</translation>
+ <translation>預估完成同步所需時間</translation>
</message>
<message>
<source>Hide</source>
- <translation>隐藏</translation>
+ <translation>隱藏</translation>
</message>
<message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
- <translation>未知。正在同步区块头 (%1, %2%)...</translation>
+ <translation>不明。正在同步前導資料中(%1, %2%)...</translation>
</message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open URI</source>
- <translation>打开 URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>打开来自URI或文件的付款请求 </translation>
- </message>
- <message>
<source>URI:</source>
- <translation>URI: </translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>选择付款请求文件 </translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>选择要打开的付款请求文件</translation>
+ <translation>URI:</translation>
</message>
</context>
<context>
@@ -1015,7 +984,7 @@
<name>OptionsDialog</name>
<message>
<source>Options</source>
- <translation>选项</translation>
+ <translation>選項</translation>
</message>
<message>
<source>&amp;Main</source>
@@ -1023,83 +992,83 @@
</message>
<message>
<source>Automatically start %1 after logging in to the system.</source>
- <translation>在登入系统后自动启动 %1</translation>
+ <translation>在登入系統後自動啓動 %1。</translation>
</message>
<message>
<source>&amp;Start %1 on system login</source>
- <translation>系统登入时启动 %1</translation>
+ <translation>系統登入時啟動 %1 (&amp;S)</translation>
</message>
<message>
<source>Size of &amp;database cache</source>
- <translation>数据库缓存大小(&amp;D)</translation>
+ <translation>資料庫快取大小(&amp;D)</translation>
</message>
<message>
<source>Number of script &amp;verification threads</source>
- <translation>脚本验证线程数(&amp;V)</translation>
+ <translation>指令碼驗證執行緒數目(&amp;V)</translation>
</message>
<message>
<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>
+ <translation>代理伺服器的網際網路位址(像是 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>
+ <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>
+ <translation>透過另外的 SOCKS&amp;5 代理伺服器來連線到 Bitcoin 網路中的 Tor 隱藏服務:</translation>
</message>
<message>
<source>Hide the icon from the system tray.</source>
- <translation>隐藏系统通知区图标</translation>
+ <translation>隱藏系統通知區圖示</translation>
</message>
<message>
<source>&amp;Hide tray icon</source>
- <translation>隐藏通知区图标(&amp;H)</translation>
+ <translation>隱藏通知區圖示(&amp;H)</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>窗口被关闭时最小化程序而不是退出。当此选项启用时,只有在菜单中选择“退出”时才会让程序退出。</translation>
+ <translation>當視窗關閉時,把應用程式縮到最小,而不是結束。當勾選這個選項時,只能夠用選單中的結束來關掉應用程式。</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>这个第三方网址(比如区块浏览器)会出现在交易选项卡的右键菜单中。 网址中的%s代表交易哈希。多个网址需要用竖线 | 相互分隔。</translation>
+ <translation>在交易頁籤的情境選單出現的第三方網址連結(URL),比如說區塊探索網站。網址中的 %s 會被取代為交易的雜湊值。可以用直線符號 | 來分隔多個連結。</translation>
</message>
<message>
<source>Open the %1 configuration file from the working directory.</source>
- <translation>从工作目录下打开配置文件 %1。</translation>
+ <translation>從工作目錄開啟設定檔 %1。</translation>
</message>
<message>
<source>Open Configuration File</source>
- <translation>打开配置文件</translation>
+ <translation>開啟設定檔</translation>
</message>
<message>
<source>Reset all client options to default.</source>
- <translation>恢复客户端的缺省设置</translation>
+ <translation>重設所有客戶端軟體選項成預設值。</translation>
</message>
<message>
<source>&amp;Reset Options</source>
- <translation>恢复缺省设置(&amp;R)</translation>
+ <translation>重設選項(&amp;R)</translation>
</message>
<message>
<source>&amp;Network</source>
- <translation>网络(&amp;N)</translation>
+ <translation>網路(&amp;N)</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>
+ <translation>啟用時有些進階功能會不能使用,不過區塊資料還是會被完全驗證。如果把這個設定改回來,會需要重新下載整個區塊鏈。區塊資料實際使用的磁碟空間會比設定值稍微大一點。</translation>
</message>
<message>
<source>Prune &amp;block storage to</source>
- <translation>将区块存储修剪至(&amp;B)</translation>
+ <translation>修剪區塊資料大小到</translation>
</message>
<message>
<source>GB</source>
- <translation>GB</translation>
+ <translation>GB (十億位元組)</translation>
</message>
<message>
<source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation>警告:还原此设置需要重新下载整个区块链。</translation>
+ <translation>把這個設定改回來會需要重新下載整個區塊鏈。</translation>
</message>
<message>
<source>MiB</source>
@@ -1107,67 +1076,67 @@
</message>
<message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = 自动, &lt;0 = 保持指定数量的CPU核心空闲)</translation>
+ <translation>(0 表示程式自動決定,小於 0 表示保留處理器核心不用的數目)</translation>
</message>
<message>
<source>W&amp;allet</source>
- <translation>钱包(&amp;A)</translation>
+ <translation>錢包(&amp;A)</translation>
</message>
<message>
<source>Expert</source>
- <translation>专家</translation>
+ <translation>專家</translation>
</message>
<message>
<source>Enable coin &amp;control features</source>
- <translation>启动货币控制功能(&amp;C)</translation>
+ <translation>開啟錢幣控制功能(&amp;C)</translation>
</message>
<message>
<source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
- <translation>如果您禁止动用尚未确认的找零资金,则一笔交易的找零资金至少需要有1个确认后才能动用。这同时也会影响账户余额的计算。</translation>
+ <translation>如果你關掉「可以花還沒確認的零錢」,那麼交易中找零的零錢就必須要等交易至少有一次確認後,才能夠使用。這也會影響餘額的計算方式。</translation>
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
- <translation>动用尚未确认的找零资金(&amp;S)</translation>
+ <translation>可以花還沒確認的零錢(&amp;S)</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>
+ <translation>自動在路由器上開放 Bitcoin 的客戶端通訊埠。只有在你的路由器支援且開啓「通用即插即用」協定(UPnP)時才有作用。</translation>
</message>
<message>
<source>Map port using &amp;UPnP</source>
- <translation>使用 &amp;UPnP 映射端口</translation>
+ <translation>用 &amp;UPnP 設定通訊埠對應</translation>
</message>
<message>
<source>Accept connections from outside.</source>
- <translation>接收外部连接。</translation>
+ <translation>接受外來連線</translation>
</message>
<message>
<source>Allow incomin&amp;g connections</source>
- <translation>允许流入连接(&amp;G)</translation>
+ <translation>接受外來連線(&amp;G)</translation>
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>通过 SOCKS5 代理连接比特币网络。</translation>
+ <translation>透過 SOCKS5 代理伺服器來連線到 Bitcoin 網路。</translation>
</message>
<message>
<source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>通过 SO&amp;CKS5 代理连接(默认代理):</translation>
+ <translation>透過 SOCKS5 代理伺服器連線(預設代理伺服器 &amp;C):</translation>
</message>
<message>
<source>Proxy &amp;IP:</source>
- <translation>代理服务器 &amp;IP:</translation>
+ <translation>代理位址(&amp;I):</translation>
</message>
<message>
<source>&amp;Port:</source>
- <translation>端口(&amp;P):</translation>
+ <translation>埠號(&amp;P):</translation>
</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>
- <translation>连接到同伴的方式:</translation>
+ <translation>用來跟其他節點聯絡的中介:</translation>
</message>
<message>
<source>IPv4</source>
@@ -1183,51 +1152,51 @@
</message>
<message>
<source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>访问 Tor 隐藏服务上的比特币网络时使用另一个 SOCKS5 代理。</translation>
+ <translation>透過另外的 SOCKS5 代理伺服器來連線到 Bitcoin 網路中的 Tor 隱藏服務。</translation>
</message>
<message>
<source>&amp;Window</source>
- <translation>窗口(&amp;W)</translation>
+ <translation>視窗(&amp;W)</translation>
</message>
<message>
<source>Show only a tray icon after minimizing the window.</source>
- <translation>最小化窗口后仅显示托盘图标</translation>
+ <translation>視窗縮到最小後只在通知區顯示圖示。</translation>
</message>
<message>
<source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>最小化到托盘(&amp;M)</translation>
+ <translation>縮到最小到通知區而不是工作列(&amp;M)</translation>
</message>
<message>
<source>M&amp;inimize on close</source>
- <translation>单击关闭按钮时最小化(&amp;I)</translation>
+ <translation>關閉時縮到最小(&amp;I)</translation>
</message>
<message>
<source>&amp;Display</source>
- <translation>显示(&amp;D)</translation>
+ <translation>顯示(&amp;D)</translation>
</message>
<message>
<source>User Interface &amp;language:</source>
- <translation>用户界面语言(&amp;L):</translation>
+ <translation>使用界面語言(&amp;L):</translation>
</message>
<message>
<source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation>可以在这里设定用户界面的语言。这个设定在重启 %1 后才会生效。</translation>
+ <translation>可以在這裡設定使用者介面的語言。這個設定在重啓 %1 後才會生效。</translation>
</message>
<message>
<source>&amp;Unit to show amounts in:</source>
- <translation>比特币金额单位(&amp;U):</translation>
+ <translation>金額顯示單位(&amp;U):</translation>
</message>
<message>
<source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>选择比特币单位。</translation>
+ <translation>選擇操作界面和付款時,預設顯示金額的細分單位。</translation>
</message>
<message>
<source>Whether to show coin control features or not.</source>
- <translation>是否需要交易源地址控制功能。</translation>
+ <translation>是否要顯示錢幣控制功能。</translation>
</message>
<message>
<source>&amp;Third party transaction URLs</source>
- <translation>第三方交易网址(&amp;T)</translation>
+ <translation>第三方交易網址連結(&amp;T)</translation>
</message>
<message>
<source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
@@ -1235,7 +1204,7 @@
</message>
<message>
<source>&amp;OK</source>
- <translation>确定(&amp;O)</translation>
+ <translation>好(&amp;O)</translation>
</message>
<message>
<source>&amp;Cancel</source>
@@ -1243,249 +1212,176 @@
</message>
<message>
<source>default</source>
- <translation>默认</translation>
+ <translation>預設值</translation>
</message>
<message>
<source>none</source>
- <translation>无</translation>
+ <translation>無</translation>
</message>
<message>
<source>Confirm options reset</source>
- <translation>确认恢复缺省设置</translation>
+ <translation>確認重設選項</translation>
</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>
- <translation>客户端即将关闭,您想继续吗?</translation>
+ <translation>客戶端軟體就要關掉了。繼續做下去嗎?</translation>
</message>
<message>
<source>Configuration options</source>
- <translation>配置选项</translation>
+ <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>
+ <translation>設定檔可以用來指定進階的使用選項,並且會覆蓋掉圖形介面的設定。不過,命令列的選項也會覆蓋掉設定檔中的選項。</translation>
</message>
<message>
<source>Error</source>
- <translation>错误</translation>
+ <translation>錯誤</translation>
</message>
<message>
<source>The configuration file could not be opened.</source>
- <translation>配置文件无法打开。</translation>
+ <translation>沒辦法開啟設定檔。</translation>
</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>
<name>OverviewPage</name>
<message>
<source>Form</source>
- <translation>表单</translation>
+ <translation>表單</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>现在显示的消息可能是过期的。在连接上比特币网络节点后,您的钱包将自动与网络同步,但是这个过程还没有完成。</translation>
+ <translation>顯示的資訊可能是過期的。跟 Bitcoin 網路的連線建立後,你的錢包會自動和網路同步,但是這個步驟還沒完成。</translation>
</message>
<message>
<source>Watch-only:</source>
- <translation>仅观察:</translation>
+ <translation>只能看:</translation>
</message>
<message>
<source>Available:</source>
- <translation>可使用的余额:</translation>
+ <translation>可用金額:</translation>
</message>
<message>
<source>Your current spendable balance</source>
- <translation>您当前可使用的余额</translation>
+ <translation>目前可用餘額</translation>
</message>
<message>
<source>Pending:</source>
- <translation>等待中的余额:</translation>
+ <translation>未定金額:</translation>
</message>
<message>
<source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>尚未确认的交易总额,未计入当前余额</translation>
+ <translation>還沒被確認的交易的總金額,可用餘額不包含這些金額</translation>
</message>
<message>
<source>Immature:</source>
- <translation>未成熟的:</translation>
+ <translation>未成熟金額:</translation>
</message>
<message>
<source>Mined balance that has not yet matured</source>
- <translation>尚未成熟的挖矿收入余额</translation>
+ <translation>還沒成熟的開採金額</translation>
</message>
<message>
<source>Balances</source>
- <translation>余额</translation>
+ <translation>餘額</translation>
</message>
<message>
<source>Total:</source>
- <translation>总额:</translation>
+ <translation>總金額:</translation>
</message>
<message>
<source>Your current total balance</source>
- <translation>您当前的总余额</translation>
+ <translation>目前全部餘額</translation>
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>您当前 观察地址(watch-only address)的余额 </translation>
+ <translation>所有只能看位址的目前餘額</translation>
</message>
<message>
<source>Spendable:</source>
- <translation>可使用:</translation>
+ <translation>可支配:</translation>
</message>
<message>
<source>Recent transactions</source>
- <translation>最近交易记录</translation>
+ <translation>最近的交易</translation>
</message>
<message>
<source>Unconfirmed transactions to watch-only addresses</source>
- <translation>观察地址(watch-only address)的未确认交易记录 </translation>
+ <translation>所有只能看位址還沒確認的交易</translation>
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>观察地址(watch-only address)中尚未成熟(matured)的挖矿收入余额:</translation>
+ <translation>所有只能看位址還沒成熟的開採金額</translation>
</message>
<message>
<source>Current total balance in watch-only addresses</source>
- <translation>观察地址(watch-only address)中的当前总余额 </translation>
+ <translation>所有只能看位址的目前全部餘額</translation>
</message>
</context>
<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
- <translation>要求付款时发生错误</translation>
+ <translation>要求付款時發生錯誤</translation>
</message>
<message>
<source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>无法启动 bitcoin 协议的“
-一键支付”处理器</translation>
+ <translation>沒辦法啟動 bitcoin 協議的「按就付」處理器</translation>
</message>
<message>
<source>URI handling</source>
- <translation>URI 处理</translation>
+ <translation>URI 處理</translation>
</message>
<message>
<source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
- <translation>‘bitcoin://’不是合法的URI。请使用'bitcoin:'作为替代。</translation>
- </message>
- <message>
- <source>You are using a BIP70 URL which will be unsupported in the future.</source>
- <translation>你正在使用BIP70 URL,它在未来会被终止支持。</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>取得付款请求的 URL 无效: %1</translation>
- </message>
- <message>
- <source>Cannot process payment request because BIP70 support was not compiled in.</source>
- <translation>无法处理支付请求,因为编译时没有启用BIP70支持。</translation>
+ <translation>字首為 bitcoin:// 不是有效的 URI,請改用 bitcoin: 開頭。</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 地址!可能是因为比特币地址无效,或是 URI 参数格式错误。</translation>
+ <translation>沒辦法解析 URI 位址!可能是因為 Bitcoin 位址無效,或是 URI 參數格式錯誤。</translation>
</message>
<message>
<source>Payment request file handling</source>
- <translation>处理付款请求文件</translation>
- </message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>无法读取付款请求文件!可能是文件无效造成的。</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>付款请求已被拒绝</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>付款请求的网络类型跟客户端不符。</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>付款请求已过期。</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>付款请求未初始化。</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>不支持到自定义付款脚本的未验证付款请求。</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>无效的支付请求。</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>请求支付的金额 %1 太小 (可被忽略)。</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>来自 %1 的退款</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>支付请求 %1 太大 (%2 字节。只允许 %3 字节)。</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>与 %1 通信出错: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>无法解析付款请求!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>来自服务器 %1 的响应无效</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>网络请求出错</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>付款已确认</translation>
+ <translation>處理付款要求檔案</translation>
</message>
</context>
<context>
<name>PeerTableModel</name>
<message>
<source>User Agent</source>
- <translation>用户代理</translation>
+ <translation>使用者代理</translation>
</message>
<message>
<source>Node/Service</source>
- <translation>节点/服务</translation>
+ <translation>節點/服務</translation>
</message>
<message>
<source>NodeId</source>
- <translation>节点ID</translation>
+ <translation>節點識別碼</translation>
</message>
<message>
<source>Ping</source>
- <translation>Ping</translation>
+ <translation>Ping 時間</translation>
</message>
<message>
<source>Sent</source>
- <translation>发送</translation>
+ <translation>送出</translation>
</message>
<message>
<source>Received</source>
@@ -1496,11 +1392,11 @@
<name>QObject</name>
<message>
<source>Amount</source>
- <translation>金额</translation>
+ <translation>金額</translation>
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>请输入一个比特币地址 (例如 %1)</translation>
+ <translation>輸入 Bitcoin 位址 (比如說 %1)</translation>
</message>
<message>
<source>%1 d</source>
@@ -1508,11 +1404,11 @@
</message>
<message>
<source>%1 h</source>
- <translation>%1 小时</translation>
+ <translation>%1 小時</translation>
</message>
<message>
<source>%1 m</source>
- <translation>%1 分钟</translation>
+ <translation>%1 分鐘</translation>
</message>
<message>
<source>%1 s</source>
@@ -1520,11 +1416,11 @@
</message>
<message>
<source>None</source>
- <translation>无</translation>
+ <translation>無</translation>
</message>
<message>
<source>N/A</source>
- <translation>不可用</translation>
+ <translation>未知</translation>
</message>
<message>
<source>%1 ms</source>
@@ -1532,15 +1428,15 @@
</message>
<message numerus="yes">
<source>%n second(s)</source>
- <translation><numerusform>%n 秒</numerusform></translation>
+ <translation><numerusform>%n 秒鐘</numerusform></translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
- <translation><numerusform>%n 分钟</numerusform></translation>
+ <translation><numerusform>%n 分鐘</numerusform></translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
- <translation><numerusform>%n 小时</numerusform></translation>
+ <translation><numerusform>%n 小時</numerusform></translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
@@ -1548,11 +1444,11 @@
</message>
<message numerus="yes">
<source>%n week(s)</source>
- <translation><numerusform>%n 周</numerusform></translation>
+ <translation><numerusform>%n 星期</numerusform></translation>
</message>
<message>
<source>%1 and %2</source>
- <translation>%1 和 %2</translation>
+ <translation>%1又 %2</translation>
</message>
<message numerus="yes">
<source>%n year(s)</source>
@@ -1560,19 +1456,19 @@
</message>
<message>
<source>%1 B</source>
- <translation>%1 字节</translation>
+ <translation>%1 B (位元組)</translation>
</message>
<message>
<source>%1 KB</source>
- <translation>%1 KB</translation>
+ <translation>%1 KB (千位元組)</translation>
</message>
<message>
<source>%1 MB</source>
- <translation>%1 MB</translation>
+ <translation>%1 MB (百萬位元組)</translation>
</message>
<message>
<source>%1 GB</source>
- <translation>%1 GB</translation>
+ <translation>%1 GB (十億位元組)</translation>
</message>
<message>
<source>Error: Specified data directory "%1" does not exist.</source>
@@ -1588,7 +1484,7 @@
</message>
<message>
<source>%1 didn't yet exit safely...</source>
- <translation>%1 尚未安全退出</translation>
+ <translation>%1 還沒有安全地結束...</translation>
</message>
<message>
<source>unknown</source>
@@ -1599,11 +1495,11 @@
<name>QRImageWidget</name>
<message>
<source>&amp;Save Image...</source>
- <translation>保存图片(&amp;S)...</translation>
+ <translation>儲存圖片(&amp;S)...</translation>
</message>
<message>
<source>&amp;Copy Image</source>
- <translation>复制图片</translation>
+ <translation>複製圖片(&amp;C)</translation>
</message>
<message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
@@ -1619,42 +1515,38 @@
</message>
<message>
<source>Save QR Code</source>
- <translation>保存二维码</translation>
+ <translation>儲存 QR Code</translation>
</message>
<message>
<source>PNG Image (*.png)</source>
- <translation>PNG 图像(*.png)</translation>
+ <translation>PNG 圖檔(*.png)</translation>
</message>
</context>
<context>
<name>RPCConsole</name>
<message>
<source>N/A</source>
- <translation>不可用</translation>
+ <translation>未知</translation>
</message>
<message>
<source>Client version</source>
- <translation>客户端版本</translation>
+ <translation>客戶端軟體版本</translation>
</message>
<message>
<source>&amp;Information</source>
- <translation>信息</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>调试窗口</translation>
+ <translation>資訊(&amp;I)</translation>
</message>
<message>
<source>General</source>
- <translation>常规</translation>
+ <translation>普通</translation>
</message>
<message>
<source>Using BerkeleyDB version</source>
- <translation>使用的 BerkeleyDB 版本</translation>
+ <translation>使用 BerkeleyDB 版本</translation>
</message>
<message>
<source>Datadir</source>
- <translation>数据目录</translation>
+ <translation>資料目錄</translation>
</message>
<message>
<source>To specify a non-default location of the data directory use the '%1' option.</source>
@@ -1670,51 +1562,51 @@
</message>
<message>
<source>Startup time</source>
- <translation>启动时间</translation>
+ <translation>啓動時間</translation>
</message>
<message>
<source>Network</source>
- <translation>网络</translation>
+ <translation>網路</translation>
</message>
<message>
<source>Name</source>
- <translation>姓名</translation>
+ <translation>名稱</translation>
</message>
<message>
<source>Number of connections</source>
- <translation>连接数</translation>
+ <translation>連線數</translation>
</message>
<message>
<source>Block chain</source>
- <translation>区块链</translation>
+ <translation>區塊鏈</translation>
</message>
<message>
<source>Current number of blocks</source>
- <translation>当前区块数量</translation>
+ <translation>目前區塊數</translation>
</message>
<message>
<source>Memory Pool</source>
- <translation>内存池</translation>
+ <translation>記憶體暫存池</translation>
</message>
<message>
<source>Current number of transactions</source>
- <translation>当前交易数量</translation>
+ <translation>目前交易數目</translation>
</message>
<message>
<source>Memory usage</source>
- <translation>内存使用</translation>
+ <translation>記憶體使用量</translation>
</message>
<message>
<source>Wallet: </source>
- <translation>钱包:</translation>
+ <translation>錢包:</translation>
</message>
<message>
<source>(none)</source>
- <translation>(无)</translation>
+ <translation>(無)</translation>
</message>
<message>
<source>&amp;Reset</source>
- <translation>&amp;重置</translation>
+ <translation>重置(&amp;R)</translation>
</message>
<message>
<source>Received</source>
@@ -1722,23 +1614,23 @@
</message>
<message>
<source>Sent</source>
- <translation>发送</translation>
+ <translation>送出</translation>
</message>
<message>
<source>&amp;Peers</source>
- <translation>同伴(&amp;P)</translation>
+ <translation>節點(&amp;P)</translation>
</message>
<message>
<source>Banned peers</source>
- <translation>节点黑名单</translation>
+ <translation>被禁節點</translation>
</message>
<message>
<source>Select a peer to view detailed information.</source>
- <translation>选择节点查看详细信息。</translation>
+ <translation>選一個節點來看詳細資訊</translation>
</message>
<message>
<source>Whitelisted</source>
- <translation>白名单</translation>
+ <translation>列在白名單</translation>
</message>
<message>
<source>Direction</source>
@@ -1750,27 +1642,27 @@
</message>
<message>
<source>Starting Block</source>
- <translation>起步区块</translation>
+ <translation>起始區塊</translation>
</message>
<message>
<source>Synced Headers</source>
- <translation>已同步区块头</translation>
+ <translation>已同步前導資料</translation>
</message>
<message>
<source>Synced Blocks</source>
- <translation>已同步区块</translation>
+ <translation>已同步區塊</translation>
</message>
<message>
<source>User Agent</source>
- <translation>用户代理</translation>
+ <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>
- <translation>缩小文字</translation>
+ <translation>縮小文字</translation>
</message>
<message>
<source>Increase font size</source>
@@ -1778,83 +1670,83 @@
</message>
<message>
<source>Services</source>
- <translation>服务</translation>
+ <translation>服務</translation>
</message>
<message>
<source>Ban Score</source>
- <translation>封禁记分</translation>
+ <translation>惡劣分數</translation>
</message>
<message>
<source>Connection Time</source>
- <translation>连接时间</translation>
+ <translation>連線時間</translation>
</message>
<message>
<source>Last Send</source>
- <translation>最后发送</translation>
+ <translation>最近送出</translation>
</message>
<message>
<source>Last Receive</source>
- <translation>最后接收</translation>
+ <translation>最近收到</translation>
</message>
<message>
<source>Ping Time</source>
- <translation>Ping 时间</translation>
+ <translation>Ping 時間</translation>
</message>
<message>
<source>The duration of a currently outstanding ping.</source>
- <translation>目前这一次 ping 已经过去的时间。</translation>
+ <translation>目前這一次 ping 已經過去的時間。</translation>
</message>
<message>
<source>Ping Wait</source>
- <translation>Ping等待</translation>
+ <translation>Ping 等待時間</translation>
</message>
<message>
<source>Min Ping</source>
- <translation>最小Ping值</translation>
+ <translation>Ping 最短時間</translation>
</message>
<message>
<source>Time Offset</source>
- <translation>时间偏移</translation>
+ <translation>時間差</translation>
</message>
<message>
<source>Last block time</source>
- <translation>上一区块时间</translation>
+ <translation>最近區塊時間</translation>
</message>
<message>
<source>&amp;Open</source>
- <translation>打开(&amp;O)</translation>
+ <translation>開啓(&amp;O)</translation>
</message>
<message>
<source>&amp;Console</source>
- <translation>控制台(&amp;C)</translation>
+ <translation>主控台(&amp;C)</translation>
</message>
<message>
<source>&amp;Network Traffic</source>
- <translation>网络流量(&amp;N)</translation>
+ <translation>網路流量(&amp;N)</translation>
</message>
<message>
<source>Totals</source>
- <translation>总数</translation>
+ <translation>總計</translation>
</message>
<message>
<source>In:</source>
- <translation>输入:</translation>
+ <translation>來:</translation>
</message>
<message>
<source>Out:</source>
- <translation>输出:</translation>
+ <translation>去:</translation>
</message>
<message>
<source>Debug log file</source>
- <translation>调试日志文件</translation>
+ <translation>除錯紀錄檔</translation>
</message>
<message>
<source>Clear console</source>
- <translation>清空控制台</translation>
+ <translation>清主控台</translation>
</message>
<message>
<source>1 &amp;hour</source>
- <translation>1 小时(&amp;H)</translation>
+ <translation>1 小時(&amp;H)</translation>
</message>
<message>
<source>1 &amp;day</source>
@@ -1862,7 +1754,7 @@
</message>
<message>
<source>1 &amp;week</source>
- <translation>1 周(&amp;W)</translation>
+ <translation>1 星期(&amp;W)</translation>
</message>
<message>
<source>1 &amp;year</source>
@@ -1870,67 +1762,67 @@
</message>
<message>
<source>&amp;Disconnect</source>
- <translation>(&amp;D)断开</translation>
+ <translation>斷線(&amp;D)</translation>
</message>
<message>
<source>Ban for</source>
- <translation>封禁时长</translation>
+ <translation>禁止連線</translation>
</message>
<message>
<source>&amp;Unban</source>
- <translation>重新允许</translation>
+ <translation>連線解禁(&amp;U)</translation>
</message>
<message>
<source>Welcome to the %1 RPC console.</source>
- <translation>欢迎使用 %1 的 RPC 控制台。</translation>
+ <translation>歡迎使用 %1 的 RPC 主控台。</translation>
</message>
<message>
<source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
- <translation>使用上下方向键浏览历史, 以及 %1 清除屏幕。</translation>
+ <translation>請用游標上下鍵來瀏覽先前指令的紀錄,並用 %1 來清畫面。</translation>
</message>
<message>
<source>Type %1 for an overview of available commands.</source>
- <translation>输入%1命令显示可用命令信息。</translation>
+ <translation>請打 %1 來看所有可用指令的簡介。</translation>
</message>
<message>
<source>For more information on using this console type %1.</source>
- <translation>输入%1来取得使用这个控制台的更多信息。</translation>
+ <translation>請打 %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>警告: 已有骗子通过要求用户在此输入指令以盗取钱包。不要在没有完全理解命令规范时使用控制台。</translation>
+ <translation>警告: 已知有詐騙集團會叫人在這個畫面輸入指令,以偷取他們錢包的內容物。如果你沒有充分理解指令可能造成的後果,請不要使用主控台。</translation>
</message>
<message>
<source>Network activity disabled</source>
- <translation>网络活动已禁用</translation>
+ <translation>網路活動已關閉</translation>
</message>
<message>
<source>Executing command without any wallet</source>
- <translation>不使用任何钱包执行命令</translation>
+ <translation>不使用任何錢包來執行指令</translation>
</message>
<message>
<source>Executing command using "%1" wallet</source>
- <translation>使用“%1”钱包执行命令</translation>
+ <translation>使用 %1 錢包來執行指令</translation>
</message>
<message>
<source>(node id: %1)</source>
- <translation>(节点ID: %1)</translation>
+ <translation>(節點識別碼: %1)</translation>
</message>
<message>
<source>via %1</source>
- <translation>通过 %1</translation>
+ <translation>經由 %1</translation>
</message>
<message>
<source>never</source>
- <translation>从未</translation>
+ <translation>沒有過</translation>
</message>
<message>
<source>Inbound</source>
- <translation>传入</translation>
+ <translation>進來</translation>
</message>
<message>
<source>Outbound</source>
- <translation>传出</translation>
+ <translation>出去</translation>
</message>
<message>
<source>Yes</source>
@@ -1942,38 +1834,38 @@
</message>
<message>
<source>Unknown</source>
- <translation>未知</translation>
+ <translation>不明</translation>
</message>
</context>
<context>
<name>ReceiveCoinsDialog</name>
<message>
<source>&amp;Amount:</source>
- <translation>总额(&amp;A):</translation>
+ <translation>金額(&amp;A):</translation>
</message>
<message>
<source>&amp;Label:</source>
- <translation>标签(&amp;L):</translation>
+ <translation>標記(&amp;L):</translation>
</message>
<message>
<source>&amp;Message:</source>
- <translation>消息(&amp;M):</translation>
+ <translation>訊息(&amp;M):</translation>
</message>
<message>
<source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
- <translation>可在付款请求上备注一条信息,在打开付款请求时可以看到。注意:该消息不是通过比特币网络传送。</translation>
+ <translation>附加在付款要求中的訊息,可以不填,打開要求內容時會顯示。注意: 這個訊息不會隨著付款送到 Bitcoin 網路上。</translation>
</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>
- <translation>使用此表单要求付款。所有字段都是&lt;b&gt;可选&lt;/b&gt;。</translation>
+ <translation>請用這份表單來要求付款。所有欄位都&lt;b&gt;可以不填&lt;/b&gt;。</translation>
</message>
<message>
<source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation>可选的请求金额。留空或填零为不要求具体金额。</translation>
+ <translation>要求付款的金額,可以不填。不確定金額時可以留白或是填零。</translation>
</message>
<message>
<source>&amp;Create new receiving address</source>
@@ -1981,82 +1873,82 @@
</message>
<message>
<source>Clear all fields of the form.</source>
- <translation>清除此表单的所有字段。</translation>
+ <translation>把表單中的所有欄位清空。</translation>
</message>
<message>
<source>Clear</source>
- <translation>清除</translation>
+ <translation>清空</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>原生隔离见证地址(又称为Bech32或者BIP-173)可减少您日后的交易费用,并且可以更好的防范打字错误,但旧版本的钱包不能识别这种地址。如果取消勾选,则会生成一个与旧版本钱包兼容的地址。</translation>
+ <translation>使用 segwit 原生位址(也叫做 Bech32 或 BIP-173)可以減少日後的交易手續費,也比較不容易打錯字,不過會跟舊版的錢包軟體不相容。如果沒有勾選的話,會改產生與舊版錢包軟體相容的位址。</translation>
</message>
<message>
<source>Generate native segwit (Bech32) address</source>
- <translation>生成原生隔离见证 (Bech32)地址</translation>
+ <translation>產生 segwit 原生位址(Bech32)</translation>
</message>
<message>
<source>Requested payments history</source>
- <translation>请求付款的历史</translation>
+ <translation>先前要求付款的記錄</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>显示选中的请求 (双击也可以显示)</translation>
+ <translation>顯示選擇的要求內容(效果跟按它兩下一樣)</translation>
</message>
<message>
<source>Show</source>
- <translation>显示</translation>
+ <translation>顯示</translation>
</message>
<message>
<source>Remove the selected entries from the list</source>
- <translation>从列表中移除选中的条目</translation>
+ <translation>從列表中刪掉選擇的項目</translation>
</message>
<message>
<source>Remove</source>
- <translation>移除</translation>
+ <translation>刪掉</translation>
</message>
<message>
<source>Copy URI</source>
- <translation>复制URI</translation>
+ <translation>複製 URI</translation>
</message>
<message>
<source>Copy label</source>
- <translation>复制标签</translation>
+ <translation>複製標記</translation>
</message>
<message>
<source>Copy message</source>
- <translation>复制消息</translation>
+ <translation>複製訊息</translation>
</message>
<message>
<source>Copy amount</source>
- <translation>复制金额</translation>
+ <translation>複製金額</translation>
</message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
<source>QR Code</source>
- <translation>二维码</translation>
+ <translation>QR Code</translation>
</message>
<message>
<source>Copy &amp;URI</source>
- <translation>复制 URI(&amp;U)</translation>
+ <translation>複製 &amp;URI</translation>
</message>
<message>
<source>Copy &amp;Address</source>
- <translation>复制地址(&amp;A)</translation>
+ <translation>複製位址(&amp;A)</translation>
</message>
<message>
<source>&amp;Save Image...</source>
- <translation>保存图片(&amp;S)...</translation>
+ <translation>儲存圖片(&amp;S)...</translation>
</message>
<message>
<source>Request payment to %1</source>
- <translation>请求付款到 %1</translation>
+ <translation>付款給 %1 的要求</translation>
</message>
<message>
<source>Payment information</source>
- <translation>付款信息</translation>
+ <translation>付款資訊</translation>
</message>
<message>
<source>URI</source>
@@ -2064,23 +1956,23 @@
</message>
<message>
<source>Address</source>
- <translation>地址</translation>
+ <translation>位址</translation>
</message>
<message>
<source>Amount</source>
- <translation>金额</translation>
+ <translation>金額</translation>
</message>
<message>
<source>Label</source>
- <translation>标签</translation>
+ <translation>標記:</translation>
</message>
<message>
<source>Message</source>
- <translation>消息</translation>
+ <translation>訊息</translation>
</message>
<message>
<source>Wallet</source>
- <translation>钱包</translation>
+ <translation>錢包</translation>
</message>
</context>
<context>
@@ -2091,146 +1983,142 @@
</message>
<message>
<source>Label</source>
- <translation>标签</translation>
+ <translation>標記:</translation>
</message>
<message>
<source>Message</source>
- <translation>消息</translation>
+ <translation>訊息</translation>
</message>
<message>
<source>(no label)</source>
- <translation>(无标签)</translation>
+ <translation>(無標記)</translation>
</message>
<message>
<source>(no message)</source>
- <translation>(无消息)</translation>
+ <translation>(無訊息)</translation>
</message>
<message>
<source>(no amount requested)</source>
- <translation>(无请求金额)</translation>
+ <translation>(無要求金額)</translation>
</message>
<message>
<source>Requested</source>
- <translation>总额</translation>
+ <translation>要求金額</translation>
</message>
</context>
<context>
<name>SendCoinsDialog</name>
<message>
<source>Send Coins</source>
- <translation>发送</translation>
+ <translation>付款</translation>
</message>
<message>
<source>Coin Control Features</source>
- <translation>交易源地址控制功能</translation>
+ <translation>錢幣控制功能</translation>
</message>
<message>
<source>Inputs...</source>
- <translation>输入...</translation>
+ <translation>輸入...</translation>
</message>
<message>
<source>automatically selected</source>
- <translation>自动选择</translation>
+ <translation>自動選擇</translation>
</message>
<message>
<source>Insufficient funds!</source>
- <translation>存款不足!</translation>
+ <translation>累計金額不足!</translation>
</message>
<message>
<source>Quantity:</source>
- <translation>总量:</translation>
+ <translation>數目:</translation>
</message>
<message>
<source>Bytes:</source>
- <translation>字节:</translation>
+ <translation>位元組數:</translation>
</message>
<message>
<source>Amount:</source>
- <translation>金额:</translation>
+ <translation>金額:</translation>
</message>
<message>
<source>Fee:</source>
- <translation>费用:</translation>
+ <translation>手續費:</translation>
</message>
<message>
<source>After Fee:</source>
- <translation>加上交易费用后:</translation>
+ <translation>計費後金額:</translation>
</message>
<message>
<source>Change:</source>
- <translation>找零 : </translation>
+ <translation>找零金額:</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>如果该选项已被激活,但是找零地址却被用光了,或者是非法的,找零资金将会被转入新生成的地址。</translation>
+ <translation>如果這項有打開,但是找零位址是空的或無效,那麼找零的錢會送到一個新造出來的位址去。</translation>
</message>
<message>
<source>Custom change address</source>
- <translation>自定义找零地址</translation>
+ <translation>自訂找零位址</translation>
</message>
<message>
<source>Transaction Fee:</source>
- <translation>交易费用:</translation>
+ <translation>交易手續費:</translation>
</message>
<message>
<source>Choose...</source>
- <translation>选择... </translation>
+ <translation>選項...</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>如果使用备用交易费设置,有可能会导致交易经过几个小时、几天(甚至永远)无法被确认。请考虑手动选择交易费,或等待整个链完成验证。</translation>
+ <translation>以備用手續費金額(fallbackfee)來付手續費可能會造成交易確認時間長達數小時、數天、或是永遠不會確認。請考慮自行指定金額,或是等到完全驗證區塊鏈後,再進行交易。</translation>
</message>
<message>
<source>Warning: Fee estimation is currently not possible.</source>
- <translation>警告: 目前无法进行交易费估计。</translation>
- </message>
- <message>
- <source>collapse fee-settings</source>
- <translation>收起 费用设置 </translation>
+ <translation>警告:目前無法計算預估手續費。</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>按照交易的虚拟大小自定义每kB ( 1,000 字节 )要交多少手续费。
+ <translation>指定每一千位元祖(kB)擬真大小的交易所要付出的手續費。
-注意:手续费是按照字节数计算的,对于一笔大小为500字节(1kB的一半)的交易来说,"每kB付100聪手续费"就意味着手续费一共只付了50聪。</translation>
+注意: 交易手續費是以位元組為單位來計算。因此當指定手續費為每千位元組 100 個 satoshi 時,對於一筆大小為 500 位元組(一千位元組的一半)的交易,其手續費會只有 50 個 satoshi。</translation>
</message>
<message>
<source>per kilobyte</source>
- <translation>每kb</translation>
+ <translation>每千位元組</translation>
</message>
<message>
<source>Hide</source>
- <translation>隐藏</translation>
+ <translation>隱藏</translation>
</message>
<message>
<source>Recommended:</source>
- <translation>推荐:</translation>
+ <translation>建議值:</translation>
</message>
<message>
<source>Custom:</source>
- <translation>自定义:</translation>
+ <translation>自訂:</translation>
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(智能交易费用 尚未初始化。 需要再下载一些区块数据...)</translation>
+ <translation>(手續費智慧演算法還沒準備好。通常都要等幾個區塊才行...)</translation>
</message>
<message>
<source>Send to multiple recipients at once</source>
- <translation>一次发送给多个接收者</translation>
+ <translation>一次付給多個收款人</translation>
</message>
<message>
<source>Add &amp;Recipient</source>
- <translation>添加收款人(&amp;R)</translation>
+ <translation>增加收款人(&amp;R)</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
- <translation>清除此表单的所有字段。</translation>
+ <translation>把表單中的所有欄位清空。</translation>
</message>
<message>
<source>Dust:</source>
- <translation>粉尘:</translation>
+ <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>
@@ -2238,67 +2126,67 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
- <translation>过低的手续费率可能导致交易永远无法确认(请阅读工具提示)</translation>
+ <translation>手續費太低的話可能會造成永遠無法確認的交易(請參考提示)</translation>
</message>
<message>
<source>Confirmation time target:</source>
- <translation>确认时间目标:</translation>
+ <translation>目標確認時間:</translation>
</message>
<message>
<source>Enable Replace-By-Fee</source>
- <translation>启用手续费追加</translation>
+ <translation>啟用手續費追加</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>手续费追加(Replace-By-Fee,BIP-125)可以让你在送出交易后才来提高手续费。不用这个功能的话,建议付比较高的手续费来降低交易延迟的风险。</translation>
+ <translation>手續費追加(Replace-By-Fee, BIP-125)可以讓你在送出交易後才來提高手續費。不用這個功能的話,建議付比較高的手續費來降低交易延遲的風險。</translation>
</message>
<message>
<source>Clear &amp;All</source>
- <translation>清除所有(&amp;A)</translation>
+ <translation>全部清掉(&amp;A)</translation>
</message>
<message>
<source>Balance:</source>
- <translation>余额:</translation>
+ <translation>餘額:</translation>
</message>
<message>
<source>Confirm the send action</source>
- <translation>确认发送货币</translation>
+ <translation>確認付款動作</translation>
</message>
<message>
<source>S&amp;end</source>
- <translation>发送(&amp;E)</translation>
+ <translation>付款(&amp;E)</translation>
</message>
<message>
<source>Copy quantity</source>
- <translation>复制数目</translation>
+ <translation>複製數目</translation>
</message>
<message>
<source>Copy amount</source>
- <translation>复制金额</translation>
+ <translation>複製金額</translation>
</message>
<message>
<source>Copy fee</source>
- <translation>复制手续费</translation>
+ <translation>複製手續費</translation>
</message>
<message>
<source>Copy after fee</source>
- <translation>复制计费后金额</translation>
+ <translation>複製計費後金額</translation>
</message>
<message>
<source>Copy bytes</source>
- <translation>复制字节数</translation>
+ <translation>複製位元組數</translation>
</message>
<message>
<source>Copy dust</source>
- <translation>复制粉尘金额</translation>
+ <translation>複製零散金額</translation>
</message>
<message>
<source>Copy change</source>
- <translation>复制找零金额</translation>
+ <translation>複製找零金額</translation>
</message>
<message>
<source>%1 (%2 blocks)</source>
- <translation>%1 (%2个块)</translation>
+ <translation>%1 (%2 個區塊)</translation>
</message>
<message>
<source> from wallet '%1'</source>
@@ -2310,11 +2198,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>%1 to %2</source>
- <translation>%1 到 %2</translation>
+ <translation>%1 給 %2</translation>
</message>
<message>
<source>Are you sure you want to send?</source>
- <translation>您确定要发出吗?</translation>
+ <translation>你確定要付錢出去嗎?</translation>
</message>
<message>
<source>or</source>
@@ -2322,23 +2210,23 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
- <translation>你可以之后再提高手续费(有BIP-125手续费追加的标记)</translation>
+ <translation>你可以之後再提高手續費(有 BIP-125 手續費追加的標記)</translation>
</message>
<message>
<source>Please, review your transaction.</source>
- <translation>请检查您的交易。</translation>
+ <translation>請再次確認交易內容。</translation>
</message>
<message>
<source>Transaction fee</source>
- <translation>交易费用</translation>
+ <translation>交易手續費</translation>
</message>
<message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
- <translation>没有BIP-125手续费追加的标记。</translation>
+ <translation>沒有 BIP-125 手續費追加的標記。</translation>
</message>
<message>
<source>Total Amount</source>
- <translation>总额</translation>
+ <translation>總金額</translation>
</message>
<message>
<source>To review recipient list click "Show Details..."</source>
@@ -2346,43 +2234,39 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Confirm send coins</source>
- <translation>确认发送</translation>
+ <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>
- <translation>支付金额必须大于0。</translation>
+ <translation>付款金額必須大於零。</translation>
</message>
<message>
<source>The amount exceeds your balance.</source>
- <translation>金额超出您的余额。</translation>
+ <translation>金額超過餘額了。</translation>
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>计入 %1 交易费后的金额超出您的余额。</translation>
+ <translation>包含 %1 的交易手續費後,總金額超過你的餘額了。</translation>
</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>
- <translation>交易创建失败!</translation>
- </message>
- <message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>交易因以下原因拒绝:%1</translation>
+ <translation>製造交易失敗了!</translation>
</message>
<message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation>交易费一般不应超过 %1。</translation>
+ <translation>高於 %1 的手續費會被認為是不合理。</translation>
</message>
<message>
<source>Payment request expired.</source>
- <translation>付款请求已过期。</translation>
+ <translation>付款的要求過期了。</translation>
</message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
@@ -2390,50 +2274,46 @@ 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>警告: 比特币地址无效</translation>
+ <translation>警告: Bitcoin 位址無效</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>
- <translation>(无标签)</translation>
+ <translation>(無標記)</translation>
</message>
</context>
<context>
<name>SendCoinsEntry</name>
<message>
<source>A&amp;mount:</source>
- <translation>金额(&amp;M)</translation>
+ <translation>金額(&amp;M):</translation>
</message>
<message>
<source>Pay &amp;To:</source>
- <translation>付给(&amp;T):</translation>
+ <translation>付給(&amp;T):</translation>
</message>
<message>
<source>&amp;Label:</source>
- <translation>标签(&amp;L):</translation>
+ <translation>標記(&amp;L):</translation>
</message>
<message>
<source>Choose previously used address</source>
- <translation>选择以前用过的地址</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>这是笔正常的支付。</translation>
+ <translation>選擇先前使用過的位址</translation>
</message>
<message>
<source>The Bitcoin address to send the payment to</source>
- <translation>付款目的地址</translation>
+ <translation>接收付款的 Bitcoin 位址</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2441,7 +2321,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>
@@ -2449,92 +2329,81 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Remove this entry</source>
- <translation>移除此项</translation>
+ <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>
+ <translation>手續費會從要付款出去的金額中扣掉。因此收款人會收到比輸入的金額還要少的 bitcoin。如果有多個收款人的話,手續費會平均分配來扣除。</translation>
</message>
<message>
<source>S&amp;ubtract fee from amount</source>
- <translation>从金额中减去交易费(&amp;U)</translation>
+ <translation>從付款金額減去手續費(&amp;U)</translation>
</message>
<message>
<source>Use available balance</source>
- <translation>使用全部可用余额</translation>
+ <translation>使用全部可用餘額</translation>
</message>
<message>
<source>Message:</source>
- <translation>消息:</translation>
+ <translation>訊息:</translation>
</message>
<message>
<source>This is an unauthenticated payment request.</source>
- <translation>这是一个未经验证的支付请求。</translation>
+ <translation>這是個沒有驗證過身份的付款要求。</translation>
</message>
<message>
<source>This is an authenticated payment request.</source>
- <translation>这是一个已经验证的支付请求。</translation>
+ <translation>這是個已經驗證過身份的付款要求。</translation>
</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>
- <translation>bitcoin:URI 附带的备注信息,将会和交易一起存储,备查。 注意:该消息不会通过比特币网络传输。</translation>
+ <translation>附加在 Bitcoin 付款協議的資源識別碼(URI)中的訊息,會和交易內容一起存起來,給你自己做參考。注意: 這個訊息不會送到 Bitcoin 網路上。</translation>
</message>
<message>
<source>Pay To:</source>
- <translation>支付给:</translation>
+ <translation>付給:</translation>
</message>
<message>
<source>Memo:</source>
- <translation>便条:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>为这个地址输入一个标签,以便将它添加到您的地址簿</translation>
- </message>
-</context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>是</translation>
+ <translation>備註:</translation>
</message>
</context>
<context>
<name>ShutdownWindow</name>
<message>
<source>%1 is shutting down...</source>
- <translation>正在关闭 %1 ...</translation>
+ <translation>正在關閉 %1 中...</translation>
</message>
<message>
<source>Do not shut down the computer until this window disappears.</source>
- <translation>在此窗口消失前不要关闭计算机。</translation>
+ <translation>在這個視窗不見以前,請不要關掉電腦。</translation>
</message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
<source>Signatures - Sign / Verify a Message</source>
- <translation>签名 - 为消息签名/验证签名消息</translation>
+ <translation>簽章 - 簽署或驗證訊息</translation>
</message>
<message>
<source>&amp;Sign Message</source>
- <translation>签名消息(&amp;S)</translation>
+ <translation>簽署訊息(&amp;S)</translation>
</message>
<message>
<source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
- <translation>您可以用你的地址对消息/协议进行签名,以证明您可以接收发送到该地址的比特币。注意不要对任何模棱两可或者随机的消息进行签名,以免遭受钓鱼式攻击。请确保消息内容准确的表达了您的真实意愿。</translation>
+ <translation>你可以用自己的位址簽署訊息或合約,來證明你可以從該位址收款。但是請小心,不要簽署語意含糊不清,或隨機產生的內容,因為釣魚式詐騙可能會用騙你簽署的手法來冒充是你。只有在語句中的細節你都同意時才簽署。</translation>
</message>
<message>
<source>The Bitcoin address to sign the message with</source>
- <translation>用来对消息签名的地址 </translation>
+ <translation>用來簽署訊息的 Bitcoin 位址</translation>
</message>
<message>
<source>Choose previously used address</source>
- <translation>选择以前用过的地址</translation>
+ <translation>選擇先前使用過的位址</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2542,7 +2411,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>
@@ -2550,107 +2419,107 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Enter the message you want to sign here</source>
- <translation>请输入您要发送的签名消息</translation>
+ <translation>請在這裡輸入你想簽署的訊息</translation>
</message>
<message>
<source>Signature</source>
- <translation>签名</translation>
+ <translation>簽章</translation>
</message>
<message>
<source>Copy the current signature to the system clipboard</source>
- <translation>复制当前签名至剪切板</translation>
+ <translation>複製目前的簽章到系統剪貼簿</translation>
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation>签名消息,证明这个地址属于您。</translation>
+ <translation>簽署這個訊息來證明這個 Bitcoin 位址是你的</translation>
</message>
<message>
<source>Sign &amp;Message</source>
- <translation>消息签名(&amp;M)</translation>
+ <translation>簽署訊息(&amp;M)</translation>
</message>
<message>
<source>Reset all sign message fields</source>
- <translation>清空所有签名消息栏</translation>
+ <translation>重設所有訊息簽署欄位</translation>
</message>
<message>
<source>Clear &amp;All</source>
- <translation>清除所有(&amp;A)</translation>
+ <translation>全部清掉(&amp;A)</translation>
</message>
<message>
<source>&amp;Verify Message</source>
- <translation>验证消息(&amp;V)</translation>
+ <translation>驗證訊息(&amp;V)</translation>
</message>
<message>
<source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
- <translation>请在下面输入接收者地址、消息(确保换行符、空格符、制表符等完全相同)和签名以验证消息。请仔细核对签名信息,以提防中间人攻击。请注意,这只是证明接收方签名的地址,它不能证明任何交易!</translation>
+ <translation>請在下面輸入收款人的位址,訊息(請確定完整複製了所包含的換行,空格,跳位符號等等),以及簽章,來驗證這個訊息。請小心,除了訊息內容以外,不要對簽章本身過度解讀,以避免被用「中間人攻擊法」詐騙。請注意,通過驗證的簽章只能證明簽章人確實可以從該位址收款,不能證明任何交易中的付款人身份!</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
- <translation>消息使用的签名地址</translation>
+ <translation>簽署這個訊息的 Bitcoin 位址</translation>
</message>
<message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>验证消息,确保消息是由指定的比特币地址签名过的。</translation>
+ <translation>驗證這個訊息來確定是用指定的 Bitcoin 位址簽署的</translation>
</message>
<message>
<source>Verify &amp;Message</source>
- <translation>验证消息签名(&amp;M)</translation>
+ <translation>驗證訊息(&amp;M)</translation>
</message>
<message>
<source>Reset all verify message fields</source>
- <translation>清空所有验证消息栏</translation>
+ <translation>重設所有訊息驗證欄位</translation>
</message>
<message>
<source>Click "Sign Message" to generate signature</source>
- <translation>单击“签名消息“产生签名。</translation>
+ <translation>請按一下「簽署訊息」來產生簽章</translation>
</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>
- <translation>钱包解锁动作取消。</translation>
+ <translation>錢包解鎖已取消。</translation>
</message>
<message>
<source>Private key for the entered address is not available.</source>
- <translation>找不到输入地址关联的私钥。</translation>
+ <translation>沒有對應輸入位址的密鑰。</translation>
</message>
<message>
<source>Message signing failed.</source>
- <translation>消息签名失败。</translation>
+ <translation>訊息簽署失敗。</translation>
</message>
<message>
<source>Message signed.</source>
- <translation>消息已签名。</translation>
+ <translation>訊息簽署好了。</translation>
</message>
<message>
<source>The signature could not be decoded.</source>
- <translation>签名无法解码。</translation>
+ <translation>沒辦法把這個簽章解碼。</translation>
</message>
<message>
<source>Please check the signature and try again.</source>
- <translation>请检查签名后重试。</translation>
+ <translation>請檢查簽章是否正確後再試一次。</translation>
</message>
<message>
<source>The signature did not match the message digest.</source>
- <translation>签名与消息摘要不匹配。</translation>
+ <translation>這個簽章跟訊息的數位摘要不符。</translation>
</message>
<message>
<source>Message verification failed.</source>
- <translation>消息验证失败。</translation>
+ <translation>訊息驗證失敗。</translation>
</message>
<message>
<source>Message verified.</source>
- <translation>消息验证成功。</translation>
+ <translation>訊息驗證沒錯。</translation>
</message>
</context>
<context>
@@ -2664,43 +2533,43 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<name>TransactionDesc</name>
<message numerus="yes">
<source>Open for %n more block(s)</source>
- <translation><numerusform>在进一步同步完%n个区块前状态待定</numerusform></translation>
+ <translation><numerusform>到下 %n 個區塊生出來前可修改</numerusform></translation>
</message>
<message>
<source>Open until %1</source>
- <translation>至 %1 个数据块时开启</translation>
+ <translation>到 %1 前可修改</translation>
</message>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
- <translation>与一个有 %1 个确认的交易冲突</translation>
+ <translation>跟一個目前確認 %1 次的交易互相衝突</translation>
</message>
<message>
<source>0/unconfirmed, %1</source>
- <translation>0/未确认,%1</translation>
+ <translation>0 次/未確認,%1</translation>
</message>
<message>
<source>in memory pool</source>
- <translation>在内存池中</translation>
+ <translation>在記憶池中</translation>
</message>
<message>
<source>not in memory pool</source>
- <translation>不在内存池中</translation>
+ <translation>不在記憶池中</translation>
</message>
<message>
<source>abandoned</source>
- <translation>已抛弃</translation>
+ <translation>已中止</translation>
</message>
<message>
<source>%1/unconfirmed</source>
- <translation>%1/未确认</translation>
+ <translation>%1 次/未確認</translation>
</message>
<message>
<source>%1 confirmations</source>
- <translation>%1 个确认</translation>
+ <translation>確認 %1 次</translation>
</message>
<message>
<source>Status</source>
- <translation>状态</translation>
+ <translation>狀態</translation>
</message>
<message>
<source>Date</source>
@@ -2708,15 +2577,15 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Source</source>
- <translation>源</translation>
+ <translation>來源</translation>
</message>
<message>
<source>Generated</source>
- <translation>生成</translation>
+ <translation>生產出來</translation>
</message>
<message>
<source>From</source>
- <translation>来自</translation>
+ <translation>來源</translation>
</message>
<message>
<source>unknown</source>
@@ -2724,75 +2593,75 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>To</source>
- <translation>到</translation>
+ <translation>目的</translation>
</message>
<message>
<source>own address</source>
- <translation>自己的地址</translation>
+ <translation>自己的位址</translation>
</message>
<message>
<source>watch-only</source>
- <translation>观察地址(watch-only) </translation>
+ <translation>只能看</translation>
</message>
<message>
<source>label</source>
- <translation>标签</translation>
+ <translation>標記</translation>
</message>
<message>
<source>Credit</source>
- <translation>收入</translation>
+ <translation>入帳</translation>
</message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
- <translation><numerusform>还差 %n 个区块成熟</numerusform></translation>
+ <translation><numerusform>再等 %n 個區塊生出來後成熟</numerusform></translation>
</message>
<message>
<source>not accepted</source>
- <translation>未被接受</translation>
+ <translation>不被接受</translation>
</message>
<message>
<source>Debit</source>
- <translation>支出</translation>
+ <translation>出帳</translation>
</message>
<message>
<source>Total debit</source>
- <translation>总收入</translation>
+ <translation>出帳總額</translation>
</message>
<message>
<source>Total credit</source>
- <translation>总支出</translation>
+ <translation>入帳總額</translation>
</message>
<message>
<source>Transaction fee</source>
- <translation>交易费用</translation>
+ <translation>交易手續費</translation>
</message>
<message>
<source>Net amount</source>
- <translation>净额</translation>
+ <translation>淨額</translation>
</message>
<message>
<source>Message</source>
- <translation>消息</translation>
+ <translation>訊息</translation>
</message>
<message>
<source>Comment</source>
- <translation>备注</translation>
+ <translation>附註</translation>
</message>
<message>
<source>Transaction ID</source>
- <translation>交易 ID</translation>
+ <translation>交易識別碼</translation>
</message>
<message>
<source>Transaction total size</source>
- <translation>交易总大小</translation>
+ <translation>交易總大小</translation>
</message>
<message>
<source>Transaction virtual size</source>
- <translation>交易虚拟大小</translation>
+ <translation>交易擬真大小</translation>
</message>
<message>
<source>Output index</source>
- <translation>输出索引</translation>
+ <translation>輸出索引</translation>
</message>
<message>
<source>Merchant</source>
@@ -2800,11 +2669,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>新挖出的比特币在可以使用前必须经过 %1 个区块确认的成熟过程。当您挖出此区块后,它将被广播到网络中以加入区块链。如果它未成功进入区块链,其状态将变更为“不接受”并且不可使用。这可能偶尔会发生,在另一个节点比你早几秒钟成功挖出一个区块时就会这样。</translation>
+ <translation>生產出來的錢要再等 %1 個區塊生出來後才成熟可以用。當區塊生產出來時會公布到網路上,來被加進區塊鏈。如果加失敗了,狀態就會變成「不被接受」,而且不能夠花。如果在你生產出區塊的幾秒鐘內,也有其他節點生產出來的話,就有可能會發生這種情形。</translation>
</message>
<message>
<source>Debug information</source>
- <translation>调试信息</translation>
+ <translation>除錯資訊</translation>
</message>
<message>
<source>Transaction</source>
@@ -2812,11 +2681,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Inputs</source>
- <translation>输入</translation>
+ <translation>輸入</translation>
</message>
<message>
<source>Amount</source>
- <translation>金额</translation>
+ <translation>金額</translation>
</message>
<message>
<source>true</source>
@@ -2831,11 +2700,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<name>TransactionDescDialog</name>
<message>
<source>This pane shows a detailed description of the transaction</source>
- <translation>当前面板显示了交易的详细信息</translation>
+ <translation>這個版面顯示這次交易的詳細說明</translation>
</message>
<message>
<source>Details for %1</source>
- <translation>%1 详情</translation>
+ <translation>交易 %1 的明細</translation>
</message>
</context>
<context>
@@ -2846,47 +2715,47 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Type</source>
- <translation>种类</translation>
+ <translation>種類</translation>
</message>
<message>
<source>Label</source>
- <translation>标签</translation>
+ <translation>標記:</translation>
</message>
<message numerus="yes">
<source>Open for %n more block(s)</source>
- <translation><numerusform>在进一步同步完%n个区块前状态待定</numerusform></translation>
+ <translation><numerusform>到下 %n 個區塊生出來前可修改</numerusform></translation>
</message>
<message>
<source>Open until %1</source>
- <translation>至 %1 个数据块时开启</translation>
+ <translation>到 %1 前可修改</translation>
</message>
<message>
<source>Unconfirmed</source>
- <translation>未确认</translation>
+ <translation>未確認</translation>
</message>
<message>
<source>Abandoned</source>
- <translation>已丢弃</translation>
+ <translation>已中止</translation>
</message>
<message>
<source>Confirming (%1 of %2 recommended confirmations)</source>
- <translation>确认中 (推荐 %2个确认,已经有 %1个确认)</translation>
+ <translation>確認中(已經 %1 次,建議至少 %2 次)</translation>
</message>
<message>
<source>Confirmed (%1 confirmations)</source>
- <translation>已确认 (%1 条确认信息)</translation>
+ <translation>已確認(%1 次)</translation>
</message>
<message>
<source>Conflicted</source>
- <translation>冲突的</translation>
+ <translation>有衝突</translation>
</message>
<message>
<source>Immature (%1 confirmations, will be available after %2)</source>
- <translation>未成熟 (%1 个确认,将在 %2 个后可用)</translation>
+ <translation>未成熟(確認 %1 次,會在 %2 次後可用)</translation>
</message>
<message>
<source>Generated but not accepted</source>
- <translation>已生成但未被接受</translation>
+ <translation>生產出來但是不被接受</translation>
</message>
<message>
<source>Received with</source>
@@ -2894,7 +2763,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Received from</source>
- <translation>收款来自</translation>
+ <translation>收款自</translation>
</message>
<message>
<source>Sent to</source>
@@ -2902,47 +2771,47 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Payment to yourself</source>
- <translation>付款给自己</translation>
+ <translation>付給自己</translation>
</message>
<message>
<source>Mined</source>
- <translation>挖矿所得</translation>
+ <translation>開採所得</translation>
</message>
<message>
<source>watch-only</source>
- <translation>观察地址(watch-only) </translation>
+ <translation>只能看</translation>
</message>
<message>
<source>(n/a)</source>
- <translation>(不可用)</translation>
+ <translation>(不適用)</translation>
</message>
<message>
<source>(no label)</source>
- <translation>(无标签)</translation>
+ <translation>(無標記)</translation>
</message>
<message>
<source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>交易状态。 鼠标移到此区域可显示确认项数量。</translation>
+ <translation>交易狀態。把游標停在欄位上會顯示確認次數。</translation>
</message>
<message>
<source>Date and time that the transaction was received.</source>
- <translation>交易被接收的时间和日期。</translation>
+ <translation>收到交易的日期和時間。</translation>
</message>
<message>
<source>Type of transaction.</source>
- <translation>交易类型。</translation>
+ <translation>交易的種類。</translation>
</message>
<message>
<source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation>该交易中是否涉及 观察地址(watch-only address)。</translation>
+ <translation>不論如何有一個只能觀看的地只有參與這次的交易</translation>
</message>
<message>
<source>User-defined intent/purpose of the transaction.</source>
- <translation>用户定义的该交易的意图/目的。</translation>
+ <translation>使用者定義的交易動機或理由。</translation>
</message>
<message>
<source>Amount removed from or added to balance.</source>
- <translation>从余额添加或移除的金额。</translation>
+ <translation>要減掉或加進餘額的金額。</translation>
</message>
</context>
<context>
@@ -2957,15 +2826,15 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>This week</source>
- <translation>这星期</translation>
+ <translation>這星期</translation>
</message>
<message>
<source>This month</source>
- <translation>这个月</translation>
+ <translation>這個月</translation>
</message>
<message>
<source>Last month</source>
- <translation>上个月</translation>
+ <translation>上個月</translation>
</message>
<message>
<source>This year</source>
@@ -2973,7 +2842,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Range...</source>
- <translation>指定范围...</translation>
+ <translation>指定範圍...</translation>
</message>
<message>
<source>Received with</source>
@@ -2985,11 +2854,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>To yourself</source>
- <translation>给自己</translation>
+ <translation>給自己</translation>
</message>
<message>
<source>Mined</source>
- <translation>挖矿所得</translation>
+ <translation>開採所得</translation>
</message>
<message>
<source>Other</source>
@@ -2997,67 +2866,67 @@ 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>输入地址、交易ID或标签进行搜索</translation>
+ <translation>請輸入要搜尋的位址、交易識別碼、或是標記</translation>
</message>
<message>
<source>Min amount</source>
- <translation>最小金额</translation>
+ <translation>最小金額</translation>
</message>
<message>
<source>Abandon transaction</source>
- <translation>放弃交易</translation>
+ <translation>中止交易</translation>
</message>
<message>
<source>Increase transaction fee</source>
- <translation>增加交易费</translation>
+ <translation>提高手續費</translation>
</message>
<message>
<source>Copy address</source>
- <translation>复制地址</translation>
+ <translation>複製位址</translation>
</message>
<message>
<source>Copy label</source>
- <translation>复制标签</translation>
+ <translation>複製標記</translation>
</message>
<message>
<source>Copy amount</source>
- <translation>复制金额</translation>
+ <translation>複製金額</translation>
</message>
<message>
<source>Copy transaction ID</source>
- <translation>复制交易ID</translation>
+ <translation>複製交易識別碼</translation>
</message>
<message>
<source>Copy raw transaction</source>
- <translation>拷贝原始交易</translation>
+ <translation>複製交易原始資料</translation>
</message>
<message>
<source>Copy full transaction details</source>
- <translation>复制所有交易详情</translation>
+ <translation>複製完整交易明細</translation>
</message>
<message>
<source>Edit label</source>
- <translation>编辑标签</translation>
+ <translation>編輯標記</translation>
</message>
<message>
<source>Show transaction details</source>
- <translation>显示交易详情</translation>
+ <translation>顯示交易明細</translation>
</message>
<message>
<source>Export Transaction History</source>
- <translation>导出交易历史</translation>
+ <translation>匯出交易記錄</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>逗号分隔文件 (*.csv)</translation>
+ <translation>逗點分隔資料檔(*.csv)</translation>
</message>
<message>
<source>Confirmed</source>
- <translation>已确认</translation>
+ <translation>已確認</translation>
</message>
<message>
<source>Watch-only</source>
- <translation>观察地址(Watch-only) </translation>
+ <translation>只能觀看的</translation>
</message>
<message>
<source>Date</source>
@@ -3065,39 +2934,39 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Type</source>
- <translation>种类</translation>
+ <translation>種類</translation>
</message>
<message>
<source>Label</source>
- <translation>标签</translation>
+ <translation>標記:</translation>
</message>
<message>
<source>Address</source>
- <translation>地址</translation>
+ <translation>位址</translation>
</message>
<message>
<source>ID</source>
- <translation>ID</translation>
+ <translation>識別碼</translation>
</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>
- <translation>导出成功</translation>
+ <translation>匯出成功</translation>
</message>
<message>
<source>The transaction history was successfully saved to %1.</source>
- <translation>交易历史已成功保存到 %1。</translation>
+ <translation>交易記錄已經成功儲存到 %1 了。</translation>
</message>
<message>
<source>Range:</source>
- <translation>范围:</translation>
+ <translation>範圍:</translation>
</message>
<message>
<source>to</source>
@@ -3108,107 +2977,107 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<name>UnitDisplayStatusBarControl</name>
<message>
<source>Unit to show amounts in. Click to select another unit.</source>
- <translation>金额单位。单击选择别的单位。</translation>
+ <translation>金額顯示單位。可以點選其他單位。</translation>
</message>
</context>
<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
- <translation>关闭钱包</translation>
+ <translation>關閉錢包</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>
+ <translation>關上錢包太久的話且修剪模式又有開啟的話,可能會造成日後需要重新同步整個區塊鏈。</translation>
</message>
</context>
<context>
<name>WalletFrame</name>
<message>
<source>No wallet has been loaded.</source>
- <translation>没有载入钱包。</translation>
+ <translation>沒有載入錢包。</translation>
</message>
</context>
<context>
<name>WalletModel</name>
<message>
<source>Send Coins</source>
- <translation>发送</translation>
+ <translation>付款</translation>
</message>
<message>
<source>Fee bump error</source>
- <translation>手续费提升失败</translation>
+ <translation>手續費提升失敗</translation>
</message>
<message>
<source>Increasing transaction fee failed</source>
- <translation>增加交易费失败</translation>
+ <translation>手續費提高失敗了</translation>
</message>
<message>
<source>Do you want to increase the fee?</source>
- <translation>你是否愿意增加交易费?</translation>
+ <translation>想要提高手續費嗎?</translation>
</message>
<message>
<source>Current fee:</source>
- <translation>当前交易费:</translation>
+ <translation>目前費用:</translation>
</message>
<message>
<source>Increase:</source>
- <translation>增加量:</translation>
+ <translation>增加:</translation>
</message>
<message>
<source>New fee:</source>
- <translation>新交易费:</translation>
+ <translation>新的費用:</translation>
</message>
<message>
<source>Confirm fee bump</source>
- <translation>确认手续费提升</translation>
+ <translation>確認手續費提升</translation>
</message>
<message>
<source>Can't sign transaction.</source>
- <translation>无法签署交易。</translation>
+ <translation>沒辦法簽署交易。</translation>
</message>
<message>
<source>Could not commit transaction</source>
- <translation>无法提交交易</translation>
+ <translation>沒辦法提交交易</translation>
</message>
<message>
<source>default wallet</source>
- <translation>默认钱包</translation>
+ <translation>預設錢包</translation>
</message>
</context>
<context>
<name>WalletView</name>
<message>
<source>&amp;Export</source>
- <translation>导出(&amp;E)</translation>
+ <translation>匯出(&amp;E)</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>将当前标签页数据导出到文件</translation>
+ <translation>將目前分頁的資料匯出存成檔案</translation>
</message>
<message>
<source>Backup Wallet</source>
- <translation>备份钱包</translation>
+ <translation>備份錢包</translation>
</message>
<message>
<source>Wallet Data (*.dat)</source>
- <translation>钱包文件(*.dat)</translation>
+ <translation>錢包資料檔(*.dat)</translation>
</message>
<message>
<source>Backup Failed</source>
- <translation>备份失败</translation>
+ <translation>備份失敗</translation>
</message>
<message>
<source>There was an error trying to save the wallet data to %1.</source>
- <translation>尝试保存钱包数据至 %1 时发生了错误。</translation>
+ <translation>儲存錢包資料到 %1 時發生錯誤。</translation>
</message>
<message>
<source>Backup Successful</source>
- <translation>备份成功</translation>
+ <translation>備份成功</translation>
</message>
<message>
<source>The wallet data was successfully saved to %1.</source>
- <translation>钱包数据成功保存至 %1。</translation>
+ <translation>錢包的資料已經成功儲存到 %1 了。</translation>
</message>
<message>
<source>Cancel</source>
@@ -3219,35 +3088,31 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<name>bitcoin-core</name>
<message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
- <translation>在MIT协议下分发,参见附带的 %s 文件或 %s</translation>
+ <translation>依據 MIT 軟體授權條款散布,詳情請見附帶的 %s 檔案或是 %s</translation>
</message>
<message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation>修剪值被设置为低于最小值%d MiB,请使用更大的数值。</translation>
+ <translation>設定的修剪值小於最小需求的 %d 百萬位元組(MiB)。請指定大一點的數字。</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>修剪:最后的钱包同步超过了修剪的数据。你需要通过 -reindex (重新下载整个区块链以防修剪节点)</translation>
- </message>
- <message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>无法在开启修剪的状态下进行重扫描,请使用 -reindex重新下载完整的区块链。</translation>
+ <translation>修剪模式:錢包的最後同步狀態是在被修剪掉的區塊資料中。你需要用 -reindex 參數執行(會重新下載整個區塊鏈)</translation>
</message>
<message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>错误:发生了致命的内部错误,详情见 debug.log 文件</translation>
+ <translation>錯誤: 發生了致命的內部錯誤,詳情請看 debug.log</translation>
</message>
<message>
<source>Pruning blockstore...</source>
- <translation>正在修剪区块存储...</translation>
+ <translation>正在修剪區塊資料庫中...</translation>
</message>
<message>
<source>Unable to start HTTP server. See debug log for details.</source>
- <translation>无法启动HTTP服务,查看日志获取更多信息</translation>
+ <translation>無法啟動 HTTP 伺服器。詳情請看除錯紀錄。</translation>
</message>
<message>
<source>The %s developers</source>
- <translation>%s 开发人员</translation>
+ <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>
@@ -3255,71 +3120,71 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
- <translation>无法锁定数据目录 %s。%s 可能已经在运行。</translation>
+ <translation>沒辦法鎖定資料目錄 %s。%s 可能已經在執行了。</translation>
</message>
<message>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
- <translation>无法同时指定特定连接地址以及自动寻找连接。</translation>
+ <translation>無法同時指定特定連線位址以及自動尋找連線。</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>读取 %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>
- <translation>请检查电脑的日期时间设置是否正确!时间错误可能会导致 %s 运行异常。</translation>
+ <translation>請檢查電腦日期和時間是否正確!%s 沒辦法在時鐘不準的情況下正常運作。</translation>
</message>
<message>
<source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <translation>如果你认为%s对你比较有用的话,请对我们进行一些捐赠支持。请访问%s网站来获取有关这个软件的更多信息。</translation>
+ <translation>如果你覺得 %s 有用,可以幫助我們。關於這個軟體的更多資訊請見 %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>区块数据库包含未来的交易,这可能是由本机错误的日期时间引起。若确认本机日期时间正确,请重新建立区块数据库。</translation>
+ <translation>區塊資料庫中有來自未來的區塊。可能是你電腦的日期時間不對。如果確定電腦日期時間沒錯的話,就重建區塊資料庫看看。</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>这是测试用的预发布版本 - 请谨慎使用 - 不要用来挖矿,或者在正式商用环境下使用</translation>
+ <translation>這是個還沒發表的測試版本 - 使用請自負風險 - 請不要用來開採或做商業應用</translation>
</message>
<message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>如果找零金额低于粉尘水平,你或许可以把它作为手续费忽略掉。</translation>
+ <translation>在該交易手續費率下,找零的零錢會因為少於零散錢的金額,而自動棄掉變成手續費</translation>
</message>
<message>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <translation>没办法重算区块。你需要先用-reindex-chainstate参数来重建数据库。</translation>
+ <translation>沒辦法重算區塊。你需要先用 -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>没办法将数据库倒转回分叉前的状态。必须要重新下载区块链。</translation>
+ <translation>沒辦法將資料庫倒轉回分岔前的狀態。必須要重新下載區塊鍊。</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>警告:网络似乎并不完全同意!有些矿工似乎遇到了问题。</translation>
+ <translation>警告: 位元幣網路對於區塊鏈結的決定目前有分歧!有些礦工看來會有問題。</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>警告:我们和其他节点似乎不完全意见一致!您可能需要升级,或者是其他节点可能需要升级。</translation>
+ <translation>警告: 我們和某些連線的節點對於區塊鏈結的決定不同!你可能需要升級,或是需要等其它的節點升級。</translation>
</message>
<message>
<source>%d of last 100 blocks have unexpected version</source>
- <translation>最后100个区块中的%d个包含未知的版本号</translation>
+ <translation>最近的 100 個區塊中有 %d 個意料之外的區塊版本</translation>
</message>
<message>
<source>%s corrupt, salvage failed</source>
- <translation>%s 已损坏,抢救备份失败</translation>
+ <translation>錢包檔 %s 壞掉了,搶救失敗</translation>
</message>
<message>
<source>-maxmempool must be at least %d MB</source>
- <translation>-maxmempool 最小为%d MB</translation>
+ <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>
- <translation>找零超过索引范围</translation>
+ <translation>找零的索引值超出範圍</translation>
</message>
<message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
@@ -3327,67 +3192,67 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Copyright (C) %i-%i</source>
- <translation>版权所有 (C) %i-%i</translation>
+ <translation>版權所有 (C) %i-%i</translation>
</message>
<message>
<source>Corrupted block database detected</source>
- <translation>检测到区块数据库损坏</translation>
+ <translation>發現區塊資料庫壞掉了</translation>
</message>
<message>
<source>Do you want to rebuild the block database now?</source>
- <translation>你想现在就重建区块数据库吗?</translation>
+ <translation>你想要現在重建區塊資料庫嗎?</translation>
</message>
<message>
<source>Error initializing block database</source>
- <translation>初始化区块数据库出错</translation>
+ <translation>初始化區塊資料庫時發生錯誤</translation>
</message>
<message>
<source>Error initializing wallet database environment %s!</source>
- <translation>初始化钱包数据库环境错误 %s!</translation>
+ <translation>初始化錢包資料庫環境 %s 時發生錯誤!</translation>
</message>
<message>
<source>Error loading %s</source>
- <translation>载入 %s 时发生错误</translation>
+ <translation>載入檔案 %s 時發生錯誤</translation>
</message>
<message>
<source>Error loading %s: Private keys can only be disabled during creation</source>
- <translation>加载 %s 时出错:只能在创建钱包时禁用私钥。</translation>
+ <translation>載入 %s 時發生錯誤: 只有在造新錢包時能夠指定不允許私鑰</translation>
</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>
- <translation>%s 加载错误:请升级到最新版 %s</translation>
+ <translation>載入檔案 %s 時發生錯誤: 這個錢包需要新版的 %s</translation>
</message>
<message>
<source>Error loading block database</source>
- <translation>导入区块数据库出错</translation>
+ <translation>載入區塊資料庫時發生錯誤</translation>
</message>
<message>
<source>Error opening block database</source>
- <translation>导入区块数据库出错</translation>
+ <translation>打開區塊資料庫時發生錯誤</translation>
</message>
<message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>监听端口失败。请使用 -listen=0 参数。</translation>
+ <translation>在任意的通訊埠聽候失敗。如果你希望這樣的話,可以設定 -listen=0.</translation>
</message>
<message>
<source>Failed to rescan the wallet during initialization</source>
- <translation>初始化时重新扫描钱包失败了</translation>
+ <translation>初始化時重新掃描錢包失敗了</translation>
</message>
<message>
<source>Importing...</source>
- <translation>导入中...</translation>
+ <translation>正在匯入中...</translation>
</message>
<message>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>不正确或没有找到起源区块。网络错误?</translation>
+ <translation>創世區塊不正確或找不到。資料目錄錯了嗎?</translation>
</message>
<message>
<source>Initialization sanity check failed. %s is shutting down.</source>
- <translation>初始化完整性检查失败。%s 即将关闭。</translation>
+ <translation>初始化時的基本檢查失敗了。%s 就要關閉了。</translation>
</message>
<message>
<source>Invalid P2P permission: '%s'</source>
@@ -3395,19 +3260,19 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>无效的金额 -%s=&lt;amount&gt;: '%s'</translation>
+ <translation>參數 -%s=&lt;金額&gt; 指定的金額無效: '%s'</translation>
</message>
<message>
<source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
- <translation>无效的金额 -discardfee=&lt;amount&gt;: '%s'</translation>
+ <translation>設定 -discardfee=&lt;金額&gt; 的金額無效: '%s'</translation>
</message>
<message>
<source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>-fallbackfee 的无效数额=&lt;amount&gt;: '%s'</translation>
+ <translation>設定 -fallbackfee=&lt;金額&gt; 的金額無效: '%s'</translation>
</message>
<message>
<source>Specified blocks directory "%s" does not exist.</source>
- <translation>指定的区块目录"%s"不存在。</translation>
+ <translation>指定的區塊目錄 "%s" 不存在。</translation>
</message>
<message>
<source>Unknown address type '%s'</source>
@@ -3419,11 +3284,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Upgrading txindex database</source>
- <translation>正在升级交易索引数据库</translation>
+ <translation>正在升級 txindex 資料庫</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
- <translation>正在加载P2P地址...</translation>
+ <translation>正在載入 P2P 位址資料...</translation>
</message>
<message>
<source>Error: Disk space is too low!</source>
@@ -3431,87 +3296,87 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Loading banlist...</source>
- <translation>正在加载黑名单...</translation>
+ <translation>正在載入禁止連線名單中...</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
- <translation>没有足够的文件描述符可用。</translation>
+ <translation>檔案描述元不足。</translation>
</message>
<message>
<source>Prune cannot be configured with a negative value.</source>
- <translation>修剪不能配置一个负数。</translation>
+ <translation>修剪值不能設定為負的。</translation>
</message>
<message>
<source>Prune mode is incompatible with -txindex.</source>
- <translation>修剪模式与 -txindex 不兼容。</translation>
+ <translation>修剪模式和 -txindex 參數不相容。</translation>
</message>
<message>
<source>Replaying blocks...</source>
- <translation>正在对区块进行重算…</translation>
+ <translation>正在對區塊進行重算...</translation>
</message>
<message>
<source>Rewinding blocks...</source>
- <translation>回退区块...</translation>
+ <translation>正在倒轉回區塊鏈之前的狀態...</translation>
</message>
<message>
<source>The source code is available from %s.</source>
- <translation>源代码可以在 %s 获得。</translation>
+ <translation>原始碼可以在 %s 取得。</translation>
</message>
<message>
<source>Transaction fee and change calculation failed</source>
- <translation>计算交易手续费和找零失败</translation>
+ <translation>計算交易手續費和找零失敗了</translation>
</message>
<message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
- <translation>无法在本机绑定 %s 端口。%s 可能已经在运行。</translation>
+ <translation>沒辦法繫結在這台電腦上的 %s 。%s 可能已經在執行了。</translation>
</message>
<message>
<source>Unable to generate keys</source>
- <translation>无法生成密钥</translation>
+ <translation>沒辦法產生密鑰</translation>
</message>
<message>
<source>Unsupported logging category %s=%s.</source>
- <translation>不支持的日志分类 %s=%s.</translation>
+ <translation>不支援的紀錄類別 %s=%s。</translation>
</message>
<message>
<source>Upgrading UTXO database</source>
- <translation>升级UTXO数据库</translation>
+ <translation>正在升級 UTXO 資料庫</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
- <translation>用户代理评论(%s)包含不安全的字符。</translation>
+ <translation>使用者代理註解(%s)中含有不安全的字元。</translation>
</message>
<message>
<source>Verifying blocks...</source>
- <translation>正在验证区块...</translation>
+ <translation>正在驗證區塊資料...</translation>
</message>
<message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
- <translation>钱包需要被重写:请重新启动%s来完成</translation>
+ <translation>錢包需要重寫: 請重新啓動 %s 來完成</translation>
</message>
<message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>错误:监听外部连接失败 (监听返回错误 %s) </translation>
+ <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' 的金额无效(交易费至少为 %s,以免交易滞留过久)</translation>
+ <translation>-maxtxfee=&lt;amount&gt;: '%s' 的金額無效 (必須大於最低轉發手續費 %s 以避免交易無法確認)</translation>
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>在交易费被扣除后发送的交易金额太小</translation>
+ <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>
+ <translation>回到非修剪的模式需要用 -reindex 參數來重建資料庫。這會導致重新下載整個區塊鏈。</translation>
</message>
<message>
<source>Error reading from database, shutting down.</source>
- <translation>读取数据库出错,关闭中。</translation>
+ <translation>讀取資料庫時發生錯誤,要關閉了。</translation>
</message>
<message>
<source>Error upgrading chainstate database</source>
- <translation>升级链状态数据库出错</translation>
+ <translation>升級區塊鏈狀態資料庫時發生錯誤</translation>
</message>
<message>
<source>Error: Disk space is low for %s</source>
@@ -3519,23 +3384,23 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>
- <translation>无效的金额 -paytxfee=&lt;amount&gt;: '%s' (必须至少为 %s)</translation>
+ <translation>設定 -paytxfee=&lt;金額&gt; 的金額無效: '%s' (至少要有 %s)</translation>
</message>
<message>
<source>Invalid netmask specified in -whitelist: '%s'</source>
- <translation>-whitelist: '%s' 指定的网络掩码无效</translation>
+ <translation>指定在 -whitelist 的網段無效: '%s'</translation>
</message>
<message>
<source>Need to specify a port with -whitebind: '%s'</source>
- <translation>-whitebind: '%s' 需要指定一个端口</translation>
+ <translation>指定 -whitebind 時必須包含通訊埠: '%s'</translation>
</message>
<message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
@@ -3543,7 +3408,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <translation>因为系统的限制,将 -maxconnections 参数从 %d 降到了 %d</translation>
+ <translation>因為系統的限制,將 -maxconnections 參數從 %d 降到了 %d</translation>
</message>
<message>
<source>Section [%s] is not recognized.</source>
@@ -3551,19 +3416,19 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Signing transaction failed</source>
- <translation>签署交易失败</translation>
+ <translation>簽署交易失敗</translation>
</message>
<message>
<source>Specified -walletdir "%s" does not exist</source>
- <translation>以-walletdir指定的路径“%s”不存在</translation>
+ <translation>以 -walletdir 指定的路徑 "%s" 不存在</translation>
</message>
<message>
<source>Specified -walletdir "%s" is a relative path</source>
- <translation>以-walletdir指定的路径“%s”是相对路径</translation>
+ <translation>以 -walletdir 指定的路徑 "%s" 是相對路徑</translation>
</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
@@ -3573,23 +3438,23 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
- <translation>交易金额太小,不足以支付交易费</translation>
+ <translation>交易金額太少而付不起手續費</translation>
</message>
<message>
<source>This is experimental software.</source>
- <translation>这是实验性的软件。</translation>
+ <translation>這套軟體屬於實驗性質。</translation>
</message>
<message>
<source>Transaction amount too small</source>
- <translation>交易量太小</translation>
+ <translation>交易金額太小</translation>
</message>
<message>
<source>Transaction too large</source>
- <translation>交易太大</translation>
+ <translation>交易位元量太大</translation>
</message>
<message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation>无法在此计算机上绑定 %s (绑定返回错误 %s)</translation>
+ <translation>無法和這台電腦上的 %s 繫結(回傳錯誤 %s)</translation>
</message>
<message>
<source>Unable to create the PID file '%s': %s</source>
@@ -3597,7 +3462,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Unable to generate initial keys</source>
- <translation>无法产生初始的密钥</translation>
+ <translation>無法產生初始的密鑰</translation>
</message>
<message>
<source>Unknown -blockfilterindex value %s.</source>
@@ -3605,115 +3470,111 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>
+ <translation>警告: 不明的交易規則被啟用了(versionbit %i)</translation>
</message>
<message>
<source>Zapping all transactions from wallet...</source>
- <translation>正在消除錢包中的所有交易...</translation>
+ <translation>正在砍掉錢包中的所有交易...</translation>
</message>
<message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <translation>参数 -maxtxfee 设定了很高的金额!这是你一次交易就有可能付出的最高手续费。</translation>
+ <translation>參數 -maxtxfee 設定了很高的金額!這可是你一次交易就有可能付出的最高手續費。</translation>
</message>
<message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation>这是在费用估计不可用时你可能会支付的交易费。</translation>
- </message>
- <message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>此产品包含了由OpenSSL Project所开发的OpenSSL Toolkit软件%s,由Eric Young撰写的加解密软件,以及由Thomas Bernard所撰写的UPnP软件。</translation>
+ <translation>這是當預估手續費還沒計算出來時,付款交易預設會付的手續費。</translation>
</message>
<message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <translation>网络版本字符串的总长度 (%i) 超过最大长度 (%i) 了。请减少 uacomment 参数的数目或长度。</translation>
+ <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>
+ <translation>警告: 錢包檔壞掉,但資料被救回來了!原來的檔案 %s 改儲存為 %s,在目錄 %s 下。 如果餘額或交易資料有誤的話,你應該要從備份資料復原回來。</translation>
</message>
<message>
<source>%s is set very high!</source>
- <translation>%s非常高!</translation>
+ <translation>%s 的設定值異常大!</translation>
</message>
<message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
- <translation>加载钱包 %s 出错。 重复的 -wallet 文件名。</translation>
+ <translation>載入錢包檔 %s 失敗。-wallet 參數指定了重複的檔名。</translation>
</message>
<message>
<source>Starting network threads...</source>
- <translation>正在启动网络线程...</translation>
+ <translation>正在啟動網路執行緒...</translation>
</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>
- <translation>这是你每次交易付款时最少要付的手续费。</translation>
+ <translation>這是你每次交易付款時最少要付的手續費。</translation>
</message>
<message>
<source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>如果发送交易,这将是你要支付的交易费。</translation>
+ <translation>這是你交易付款時所要付的手續費。</translation>
</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>
- <translation>此交易在内存池中串接了太多其他交易</translation>
+ <translation>交易造成記憶池中的交易鏈太長</translation>
</message>
<message>
<source>Transaction must have at least one recipient</source>
- <translation>交易必须包含至少一个接收人</translation>
+ <translation>交易必須至少要有一個收款人</translation>
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
- <translation>-onlynet 指定的是未知网络:%s</translation>
+ <translation>在 -onlynet 指定了不明的網路別: '%s'</translation>
</message>
<message>
<source>Insufficient funds</source>
- <translation>金额不足</translation>
+ <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>
+ <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>
+ <translation>計算預估手續費失敗了,也沒有備用手續費(fallbackfee)可用。請再多等待幾個區塊,或是啟用 -fallbackfee 參數。</translation>
</message>
<message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <translation>警告:在已经禁用私钥的钱包 {%s} 中仍然检测到私钥</translation>
+ <translation>警告: 在不允許私鑰的錢包 {%s} 中發現有私鑰</translation>
</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>
- <translation>正在加载区块索引...</translation>
+ <translation>正在載入區塊索引...</translation>
</message>
<message>
<source>Loading wallet...</source>
- <translation>正在加载钱包...</translation>
+ <translation>正在載入錢包資料...</translation>
</message>
<message>
<source>Cannot downgrade wallet</source>
- <translation>无法降级钱包</translation>
+ <translation>沒辦法把錢包格式降級</translation>
</message>
<message>
<source>Rescanning...</source>
- <translation>正在重新扫描...</translation>
+ <translation>正在重新掃描...</translation>
</message>
<message>
<source>Done loading</source>
- <translation>加载完成</translation>
+ <translation>載入完成</translation>
</message>
</context>
</TS> \ No newline at end of file
diff --git a/src/qt/macnotificationhandler.mm b/src/qt/macnotificationhandler.mm
index b16042e946..2d26a8383d 100644
--- a/src/qt/macnotificationhandler.mm
+++ b/src/qt/macnotificationhandler.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/main.cpp b/src/qt/main.cpp
index 3dfd9e850e..6e772d58c5 100644
--- a/src/qt/main.cpp
+++ b/src/qt/main.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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 <qt/bitcoin.h>
#include <util/translation.h>
+#include <util/url.h>
#include <QCoreApplication>
@@ -15,5 +16,6 @@
extern const std::function<std::string(const char*)> G_TRANSLATION_FUN = [](const char* psz) {
return QCoreApplication::translate("bitcoin-core", psz).toStdString();
};
+UrlDecodeFn* const URL_DECODE = urlDecode;
int main(int argc, char* argv[]) { return GuiMain(argc, argv); }
diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp
index 6243a71c7d..49a1992803 100644
--- a/src/qt/modaloverlay.cpp
+++ b/src/qt/modaloverlay.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 977076c4c2..58a7591c95 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -17,6 +17,7 @@
#include <net.h>
#include <netbase.h>
#include <txdb.h> // for -dbcache defaults
+#include <util/string.h>
#include <QDebug>
#include <QSettings>
@@ -241,7 +242,7 @@ void OptionsModel::SetPruneEnabled(bool prune, bool force)
QSettings settings;
settings.setValue("bPrune", prune);
const int64_t prune_target_mib = PruneGBtoMiB(settings.value("nPruneSize").toInt());
- std::string prune_val = prune ? std::to_string(prune_target_mib) : "0";
+ std::string prune_val = prune ? ToString(prune_target_mib) : "0";
if (force) {
m_node.forceSetArg("-prune", prune_val);
return;
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index 342c7cce31..e0ae1f9e92 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -161,20 +161,27 @@ void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
{
int unit = walletModel->getOptionsModel()->getDisplayUnit();
m_balances = balances;
- if (walletModel->privateKeysDisabled()) {
- ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
- ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
- ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
- ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ if (walletModel->wallet().isLegacy()) {
+ if (walletModel->wallet().privateKeysDisabled()) {
+ ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ } else {
+ ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.balance, false, BitcoinUnits::separatorAlways));
+ ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ }
} else {
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.balance, false, BitcoinUnits::separatorAlways));
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_balance, false, BitcoinUnits::separatorAlways));
ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_balance, false, BitcoinUnits::separatorAlways));
ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, false, BitcoinUnits::separatorAlways));
- ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
- ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
- ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
- ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
}
// only show immature (newly mined) balance if it's non-zero, so as not to complicate things
// for the non-mining users
@@ -184,7 +191,7 @@ void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
// for symmetry reasons also show immature label when the watch-only one is shown
ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
- ui->labelWatchImmature->setVisible(!walletModel->privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
+ ui->labelWatchImmature->setVisible(!walletModel->wallet().privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
}
// show/hide watch-only labels
@@ -236,9 +243,9 @@ void OverviewPage::setWalletModel(WalletModel *model)
connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit);
- updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->privateKeysDisabled());
+ updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->wallet().privateKeysDisabled());
connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
- updateWatchOnlyLabels(showWatchOnly && !walletModel->privateKeysDisabled());
+ updateWatchOnlyLabels(showWatchOnly && !walletModel->wallet().privateKeysDisabled());
});
}
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index a497f58b16..5220f8e138 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -32,7 +32,7 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine
case PeerTableModel::Subversion:
return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
case PeerTableModel::Ping:
- return pLeft->dMinPing < pRight->dMinPing;
+ return pLeft->m_min_ping_usec < pRight->m_min_ping_usec;
case PeerTableModel::Sent:
return pLeft->nSendBytes < pRight->nSendBytes;
case PeerTableModel::Received:
@@ -161,7 +161,7 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const
case Subversion:
return QString::fromStdString(rec->nodeStats.cleanSubVer);
case Ping:
- return GUIUtil::formatPingTime(rec->nodeStats.dMinPing);
+ return GUIUtil::formatPingTime(rec->nodeStats.m_min_ping_usec);
case Sent:
return GUIUtil::formatBytes(rec->nodeStats.nSendBytes);
case Received:
diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h
index cf45c5a08f..0e20b1d9dc 100644
--- a/src/qt/peertablemodel.h
+++ b/src/qt/peertablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h
index 5cca515079..bde9c0d1a6 100644
--- a/src/qt/qvaluecombobox.h
+++ b/src/qt/qvaluecombobox.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index 16597e4758..5debded4ea 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -99,11 +99,11 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
}
// Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
- ui->receiveButton->setEnabled(model->canGetAddresses());
+ ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
// Enable/disable the receive button if the wallet is now able/unable to give out new addresses.
connect(model, &WalletModel::canGetAddressesChanged, [this] {
- ui->receiveButton->setEnabled(model->canGetAddresses());
+ ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
});
}
}
@@ -157,17 +157,40 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()
}
}
address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type);
- SendCoinsRecipient info(address, label,
- ui->reqAmount->value(), ui->reqMessage->text());
- ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
- dialog->setAttribute(Qt::WA_DeleteOnClose);
- dialog->setModel(model);
- dialog->setInfo(info);
- dialog->show();
- clear();
- /* Store request for later reference */
- model->getRecentRequestsTableModel()->addNewRequest(info);
+ switch(model->getAddressTableModel()->getEditStatus())
+ {
+ case AddressTableModel::EditStatus::OK: {
+ // Success
+ SendCoinsRecipient info(address, label,
+ ui->reqAmount->value(), ui->reqMessage->text());
+ ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->setModel(model);
+ dialog->setInfo(info);
+ dialog->show();
+
+ /* Store request for later reference */
+ model->getRecentRequestsTableModel()->addNewRequest(info);
+ break;
+ }
+ case AddressTableModel::EditStatus::WALLET_UNLOCK_FAILURE:
+ QMessageBox::critical(this, windowTitle(),
+ tr("Could not unlock wallet."),
+ QMessageBox::Ok, QMessageBox::Ok);
+ break;
+ case AddressTableModel::EditStatus::KEY_GENERATION_FAILURE:
+ QMessageBox::critical(this, windowTitle(),
+ tr("Could not generate new %1 address").arg(QString::fromStdString(FormatOutputType(address_type))),
+ QMessageBox::Ok, QMessageBox::Ok);
+ break;
+ // These aren't valid return values for our action
+ case AddressTableModel::EditStatus::INVALID_ADDRESS:
+ case AddressTableModel::EditStatus::DUPLICATE_ADDRESS:
+ case AddressTableModel::EditStatus::NO_CHANGES:
+ assert(false);
+ }
+ clear();
}
void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex &index)
diff --git a/src/qt/res/icons/bitcoin.ico b/src/qt/res/icons/bitcoin.ico
index 8f5045015d..8f5045015d 100755..100644
--- a/src/qt/res/icons/bitcoin.ico
+++ b/src/qt/res/icons/bitcoin.ico
Binary files differ
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index be6de140e8..bfe316bdcd 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -1111,15 +1111,16 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats)
ui->peerBytesSent->setText(GUIUtil::formatBytes(stats->nodeStats.nSendBytes));
ui->peerBytesRecv->setText(GUIUtil::formatBytes(stats->nodeStats.nRecvBytes));
ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nTimeConnected));
- ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingTime));
- ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingWait));
- ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.dMinPing));
+ ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.m_ping_usec));
+ ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStats.m_ping_wait_usec));
+ ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.m_min_ping_usec));
ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset));
- ui->peerVersion->setText(QString("%1").arg(QString::number(stats->nodeStats.nVersion)));
+ ui->peerVersion->setText(QString::number(stats->nodeStats.nVersion));
ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound") : tr("Outbound"));
- ui->peerHeight->setText(QString("%1").arg(QString::number(stats->nodeStats.nStartingHeight)));
+ ui->peerHeight->setText(QString::number(stats->nodeStats.nStartingHeight));
ui->peerWhitelisted->setText(stats->nodeStats.m_legacyWhitelisted ? tr("Yes") : tr("No"));
+ ui->peerMappedAS->setText(stats->nodeStats.m_mapped_as != 0 ? QString::number(stats->nodeStats.m_mapped_as) : tr("N/A"));
// This check fails for example if the lock was busy and
// nodeStateStats couldn't be fetched.
@@ -1193,7 +1194,7 @@ void RPCConsole::disconnectSelectedNode()
// Get currently selected peer address
NodeId id = nodes.at(i).data().toLongLong();
// Find the node, disconnect it and clear the selected node
- if(m_node.disconnect(id))
+ if(m_node.disconnectById(id))
clearSelectedNode();
}
}
@@ -1218,7 +1219,7 @@ void RPCConsole::banSelectedNode(int bantime)
const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
if (stats) {
m_node.ban(stats->nodeStats.addr, BanReasonManuallyAdded, bantime);
- m_node.disconnect(stats->nodeStats.addr);
+ m_node.disconnectByAddress(stats->nodeStats.addr);
}
}
clearSelectedNode();
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index cc01aafb23..7b389a48d6 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -26,7 +26,6 @@
#include <ui_interface.h>
#include <wallet/coincontrol.h>
#include <wallet/fees.h>
-#include <wallet/psbtwallet.h>
#include <wallet/wallet.h>
#include <QFontMetrics>
@@ -188,7 +187,7 @@ void SendCoinsDialog::setModel(WalletModel *_model)
// set default rbf checkbox state
ui->optInRBF->setCheckState(Qt::Checked);
- if (model->privateKeysDisabled()) {
+ if (model->wallet().privateKeysDisabled()) {
ui->sendButton->setText(tr("Cr&eate Unsigned"));
ui->sendButton->setToolTip(tr("Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.").arg(PACKAGE_NAME));
}
@@ -220,11 +219,8 @@ SendCoinsDialog::~SendCoinsDialog()
delete ui;
}
-void SendCoinsDialog::on_sendButton_clicked()
+bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informative_text, QString& detailed_text)
{
- if(!model || !model->getOptionsModel())
- return;
-
QList<SendCoinsRecipient> recipients;
bool valid = true;
@@ -247,7 +243,7 @@ void SendCoinsDialog::on_sendButton_clicked()
if(!valid || recipients.isEmpty())
{
- return;
+ return false;
}
fNewRecipientAllowed = false;
@@ -256,11 +252,11 @@ void SendCoinsDialog::on_sendButton_clicked()
{
// Unlock wallet was cancelled
fNewRecipientAllowed = true;
- return;
+ return false;
}
// prepare transaction for getting txFee earlier
- WalletModelTransaction currentTransaction(recipients);
+ m_current_transaction = MakeUnique<WalletModelTransaction>(recipients);
WalletModel::SendCoinsReturn prepareStatus;
// Always use a CCoinControl instance, use the CoinControlDialog instance if CoinControl has been enabled
@@ -270,22 +266,20 @@ void SendCoinsDialog::on_sendButton_clicked()
updateCoinControlState(ctrl);
- prepareStatus = model->prepareTransaction(currentTransaction, ctrl);
+ prepareStatus = model->prepareTransaction(*m_current_transaction, ctrl);
// process prepareStatus and on error generate message shown to user
processSendCoinsReturn(prepareStatus,
- BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), currentTransaction.getTransactionFee()));
+ BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), m_current_transaction->getTransactionFee()));
if(prepareStatus.status != WalletModel::OK) {
fNewRecipientAllowed = true;
- return;
+ return false;
}
- CAmount txFee = currentTransaction.getTransactionFee();
-
- // Format confirmation message
+ CAmount txFee = m_current_transaction->getTransactionFee();
QStringList formatted;
- for (const SendCoinsRecipient &rcp : currentTransaction.getRecipients())
+ for (const SendCoinsRecipient &rcp : m_current_transaction->getRecipients())
{
// generate amount string with wallet name in case of multiwallet
QString amount = BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
@@ -312,72 +306,82 @@ void SendCoinsDialog::on_sendButton_clicked()
formatted.append(recipientElement);
}
- QString questionString;
- if (model->privateKeysDisabled()) {
- questionString.append(tr("Do you want to draft this transaction?"));
+ if (model->wallet().privateKeysDisabled()) {
+ question_string.append(tr("Do you want to draft this transaction?"));
} else {
- questionString.append(tr("Are you sure you want to send?"));
+ question_string.append(tr("Are you sure you want to send?"));
}
- questionString.append("<br /><span style='font-size:10pt;'>");
- if (model->privateKeysDisabled()) {
- questionString.append(tr("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.").arg(PACKAGE_NAME));
+ question_string.append("<br /><span style='font-size:10pt;'>");
+ if (model->wallet().privateKeysDisabled()) {
+ question_string.append(tr("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.").arg(PACKAGE_NAME));
} else {
- questionString.append(tr("Please, review your transaction."));
+ question_string.append(tr("Please, review your transaction."));
}
- questionString.append("</span>%1");
+ question_string.append("</span>%1");
if(txFee > 0)
{
// append fee string if a fee is required
- questionString.append("<hr /><b>");
- questionString.append(tr("Transaction fee"));
- questionString.append("</b>");
+ question_string.append("<hr /><b>");
+ question_string.append(tr("Transaction fee"));
+ question_string.append("</b>");
// append transaction size
- questionString.append(" (" + QString::number((double)currentTransaction.getTransactionSize() / 1000) + " kB): ");
+ question_string.append(" (" + QString::number((double)m_current_transaction->getTransactionSize() / 1000) + " kB): ");
// append transaction fee value
- questionString.append("<span style='color:#aa0000; font-weight:bold;'>");
- questionString.append(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), txFee));
- questionString.append("</span><br />");
+ question_string.append("<span style='color:#aa0000; font-weight:bold;'>");
+ question_string.append(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), txFee));
+ question_string.append("</span><br />");
// append RBF message according to transaction's signalling
- questionString.append("<span style='font-size:10pt; font-weight:normal;'>");
+ question_string.append("<span style='font-size:10pt; font-weight:normal;'>");
if (ui->optInRBF->isChecked()) {
- questionString.append(tr("You can increase the fee later (signals Replace-By-Fee, BIP-125)."));
+ question_string.append(tr("You can increase the fee later (signals Replace-By-Fee, BIP-125)."));
} else {
- questionString.append(tr("Not signalling Replace-By-Fee, BIP-125."));
+ question_string.append(tr("Not signalling Replace-By-Fee, BIP-125."));
}
- questionString.append("</span>");
+ question_string.append("</span>");
}
// add total amount in all subdivision units
- questionString.append("<hr />");
- CAmount totalAmount = currentTransaction.getTotalTransactionAmount() + txFee;
+ question_string.append("<hr />");
+ CAmount totalAmount = m_current_transaction->getTotalTransactionAmount() + txFee;
QStringList alternativeUnits;
for (const BitcoinUnits::Unit u : BitcoinUnits::availableUnits())
{
if(u != model->getOptionsModel()->getDisplayUnit())
alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount));
}
- questionString.append(QString("<b>%1</b>: <b>%2</b>").arg(tr("Total Amount"))
+ question_string.append(QString("<b>%1</b>: <b>%2</b>").arg(tr("Total Amount"))
.arg(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), totalAmount)));
- questionString.append(QString("<br /><span style='font-size:10pt; font-weight:normal;'>(=%1)</span>")
+ question_string.append(QString("<br /><span style='font-size:10pt; font-weight:normal;'>(=%1)</span>")
.arg(alternativeUnits.join(" " + tr("or") + " ")));
- QString informative_text;
- QString detailed_text;
if (formatted.size() > 1) {
- questionString = questionString.arg("");
+ question_string = question_string.arg("");
informative_text = tr("To review recipient list click \"Show Details...\"");
detailed_text = formatted.join("\n\n");
} else {
- questionString = questionString.arg("<br /><br />" + formatted.at(0));
+ question_string = question_string.arg("<br /><br />" + formatted.at(0));
}
- const QString confirmation = model->privateKeysDisabled() ? tr("Confirm transaction proposal") : tr("Confirm send coins");
- const QString confirmButtonText = model->privateKeysDisabled() ? tr("Copy PSBT to clipboard") : tr("Send");
- SendConfirmationDialog confirmationDialog(confirmation, questionString, informative_text, detailed_text, SEND_CONFIRM_DELAY, confirmButtonText, this);
+
+ return true;
+}
+
+void SendCoinsDialog::on_sendButton_clicked()
+{
+ if(!model || !model->getOptionsModel())
+ return;
+
+ QString question_string, informative_text, detailed_text;
+ if (!PrepareSendText(question_string, informative_text, detailed_text)) return;
+ assert(m_current_transaction);
+
+ const QString confirmation = model->wallet().privateKeysDisabled() ? tr("Confirm transaction proposal") : tr("Confirm send coins");
+ const QString confirmButtonText = model->wallet().privateKeysDisabled() ? tr("Create Unsigned") : tr("Send");
+ SendConfirmationDialog confirmationDialog(confirmation, question_string, informative_text, detailed_text, SEND_CONFIRM_DELAY, confirmButtonText, this);
confirmationDialog.exec();
QMessageBox::StandardButton retval = static_cast<QMessageBox::StandardButton>(confirmationDialog.result());
@@ -388,26 +392,62 @@ void SendCoinsDialog::on_sendButton_clicked()
}
bool send_failure = false;
- if (model->privateKeysDisabled()) {
- CMutableTransaction mtx = CMutableTransaction{*(currentTransaction.getWtx())};
+ if (model->wallet().privateKeysDisabled()) {
+ CMutableTransaction mtx = CMutableTransaction{*(m_current_transaction->getWtx())};
PartiallySignedTransaction psbtx(mtx);
bool complete = false;
- const TransactionError err = model->wallet().fillPSBT(psbtx, complete, SIGHASH_ALL, false /* sign */, true /* bip32derivs */);
+ const TransactionError err = model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, psbtx, complete);
assert(!complete);
assert(err == TransactionError::OK);
// Serialize the PSBT
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str());
- Q_EMIT message(tr("PSBT copied"), "Copied to clipboard", CClientUIInterface::MSG_INFORMATION);
+ QMessageBox msgBox;
+ msgBox.setText("Unsigned Transaction");
+ msgBox.setInformativeText("The PSBT has been copied to the clipboard. You can also save it.");
+ msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard);
+ msgBox.setDefaultButton(QMessageBox::Discard);
+ switch (msgBox.exec()) {
+ case QMessageBox::Save: {
+ QString selectedFilter;
+ QString fileNameSuggestion = "";
+ bool first = true;
+ for (const SendCoinsRecipient &rcp : m_current_transaction->getRecipients()) {
+ if (!first) {
+ fileNameSuggestion.append(" - ");
+ }
+ QString labelOrAddress = rcp.label.isEmpty() ? rcp.address : rcp.label;
+ QString amount = BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
+ fileNameSuggestion.append(labelOrAddress + "-" + amount);
+ first = false;
+ }
+ fileNameSuggestion.append(".psbt");
+ QString filename = GUIUtil::getSaveFileName(this,
+ tr("Save Transaction Data"), fileNameSuggestion,
+ tr("Partially Signed Transaction (Binary) (*.psbt)"), &selectedFilter);
+ if (filename.isEmpty()) {
+ return;
+ }
+ std::ofstream out(filename.toLocal8Bit().data());
+ out << ssTx.str();
+ out.close();
+ Q_EMIT message(tr("PSBT saved"), "PSBT saved to disk", CClientUIInterface::MSG_INFORMATION);
+ break;
+ }
+ case QMessageBox::Discard:
+ break;
+ default:
+ assert(false);
+ }
} else {
// now send the prepared transaction
- WalletModel::SendCoinsReturn sendStatus = model->sendCoins(currentTransaction);
+ WalletModel::SendCoinsReturn sendStatus = model->sendCoins(*m_current_transaction);
// process sendStatus and on error generate message shown to user
processSendCoinsReturn(sendStatus);
if (sendStatus.status == WalletModel::OK) {
- Q_EMIT coinsSent(currentTransaction.getWtx()->GetHash());
+ Q_EMIT coinsSent(m_current_transaction->getWtx()->GetHash());
} else {
send_failure = true;
}
@@ -418,10 +458,13 @@ void SendCoinsDialog::on_sendButton_clicked()
coinControlUpdateLabels();
}
fNewRecipientAllowed = true;
+ m_current_transaction.reset();
}
void SendCoinsDialog::clear()
{
+ m_current_transaction.reset();
+
// Clear coin control settings
CoinControlDialog::coinControl()->UnSelectAll();
ui->checkBoxCoinControlChange->setChecked(false);
@@ -563,7 +606,7 @@ void SendCoinsDialog::setBalance(const interfaces::WalletBalances& balances)
if(model && model->getOptionsModel())
{
CAmount balance = balances.balance;
- if (model->privateKeysDisabled()) {
+ if (model->wallet().privateKeysDisabled()) {
balance = balances.watch_only_balance;
ui->labelBalanceName->setText(tr("Watch-only balance:"));
}
@@ -653,7 +696,7 @@ void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry)
}
// Include watch-only for wallets without private key
- coin_control.fAllowWatchOnly = model->privateKeysDisabled();
+ coin_control.fAllowWatchOnly = model->wallet().privateKeysDisabled();
// Calculate available amount to send.
CAmount amount = model->wallet().getAvailableBalance(coin_control);
@@ -708,7 +751,7 @@ void SendCoinsDialog::updateCoinControlState(CCoinControl& ctrl)
ctrl.m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex());
ctrl.m_signal_bip125_rbf = ui->optInRBF->isChecked();
// Include watch-only for wallets without private key
- ctrl.fAllowWatchOnly = model->privateKeysDisabled();
+ ctrl.fAllowWatchOnly = model->wallet().privateKeysDisabled();
}
void SendCoinsDialog::updateSmartFeeLabel()
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index 86422c4030..36bc2a846b 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -60,6 +60,7 @@ private:
Ui::SendCoinsDialog *ui;
ClientModel *clientModel;
WalletModel *model;
+ std::unique_ptr<WalletModelTransaction> m_current_transaction;
bool fNewRecipientAllowed;
bool fFeeMinimized;
const PlatformStyle *platformStyle;
@@ -69,6 +70,8 @@ private:
// Additional parameter msgArg can be used via .arg(msgArg).
void processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg = QString());
void minimizeFeeSection(bool fMinimize);
+ // Format confirmation message
+ bool PrepareSendText(QString& question_string, QString& informative_text, QString& detailed_text);
void updateFeeMinimizedLabel();
// Update the passed in CCoinControl with state from the GUI
void updateCoinControlState(CCoinControl& ctrl);
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index e21f44fe57..5cfbb67449 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -11,7 +11,7 @@
#include <qt/walletmodel.h>
#include <key_io.h>
-#include <util/validation.h> // For strMessageMagic
+#include <util/message.h> // For MessageSign(), MessageVerify()
#include <wallet/wallet.h>
#include <vector>
@@ -135,30 +135,34 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
return;
}
- CKey key;
- if (!model->wallet().getPrivKey(GetScriptForDestination(destination), CKeyID(*pkhash), key))
- {
- ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
- ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
- return;
+ const std::string& message = ui->messageIn_SM->document()->toPlainText().toStdString();
+ std::string signature;
+ SigningResult res = model->wallet().signMessage(message, *pkhash, signature);
+
+ QString error;
+ switch (res) {
+ case SigningResult::OK:
+ error = tr("No error");
+ break;
+ case SigningResult::PRIVATE_KEY_NOT_AVAILABLE:
+ error = tr("Private key for the entered address is not available.");
+ break;
+ case SigningResult::SIGNING_FAILED:
+ error = tr("Message signing failed.");
+ break;
+ // no default case, so the compiler can warn about missing cases
}
- CHashWriter ss(SER_GETHASH, 0);
- ss << strMessageMagic;
- ss << ui->messageIn_SM->document()->toPlainText().toStdString();
-
- std::vector<unsigned char> vchSig;
- if (!key.SignCompact(ss.GetHash(), vchSig))
- {
+ if (res != SigningResult::OK) {
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
- ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signing failed.") + QString("</nobr>"));
+ ui->statusLabel_SM->setText(QString("<nobr>") + error + QString("</nobr>"));
return;
}
ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
- ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(vchSig.data(), vchSig.size())));
+ ui->signatureOut_SM->setText(QString::fromStdString(signature));
}
void SignVerifyMessageDialog::on_copySignatureButton_SM_clicked()
@@ -191,51 +195,57 @@ void SignVerifyMessageDialog::on_addressBookButton_VM_clicked()
void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
{
- CTxDestination destination = DecodeDestination(ui->addressIn_VM->text().toStdString());
- if (!IsValidDestination(destination)) {
+ const std::string& address = ui->addressIn_VM->text().toStdString();
+ const std::string& signature = ui->signatureIn_VM->text().toStdString();
+ const std::string& message = ui->messageIn_VM->document()->toPlainText().toStdString();
+
+ const auto result = MessageVerify(address, signature, message);
+
+ if (result == MessageVerificationResult::OK) {
+ ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
+ } else {
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
- ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
- return;
}
- if (!boost::get<PKHash>(&destination)) {
+
+ switch (result) {
+ case MessageVerificationResult::OK:
+ ui->statusLabel_VM->setText(
+ QString("<nobr>") + tr("Message verified.") + QString("</nobr>")
+ );
+ return;
+ case MessageVerificationResult::ERR_INVALID_ADDRESS:
+ ui->statusLabel_VM->setText(
+ tr("The entered address is invalid.") + QString(" ") +
+ tr("Please check the address and try again.")
+ );
+ return;
+ case MessageVerificationResult::ERR_ADDRESS_NO_KEY:
ui->addressIn_VM->setValid(false);
- ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
- ui->statusLabel_VM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
+ ui->statusLabel_VM->setText(
+ tr("The entered address does not refer to a key.") + QString(" ") +
+ tr("Please check the address and try again.")
+ );
return;
- }
-
- bool fInvalid = false;
- std::vector<unsigned char> vchSig = DecodeBase64(ui->signatureIn_VM->text().toStdString().c_str(), &fInvalid);
-
- if (fInvalid)
- {
+ case MessageVerificationResult::ERR_MALFORMED_SIGNATURE:
ui->signatureIn_VM->setValid(false);
- ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
- ui->statusLabel_VM->setText(tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again."));
+ ui->statusLabel_VM->setText(
+ tr("The signature could not be decoded.") + QString(" ") +
+ tr("Please check the signature and try again.")
+ );
return;
- }
-
- CHashWriter ss(SER_GETHASH, 0);
- ss << strMessageMagic;
- ss << ui->messageIn_VM->document()->toPlainText().toStdString();
-
- CPubKey pubkey;
- if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
- {
+ case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED:
ui->signatureIn_VM->setValid(false);
- ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
- ui->statusLabel_VM->setText(tr("The signature did not match the message digest.") + QString(" ") + tr("Please check the signature and try again."));
+ ui->statusLabel_VM->setText(
+ tr("The signature did not match the message digest.") + QString(" ") +
+ tr("Please check the signature and try again.")
+ );
return;
- }
-
- if (!(CTxDestination(PKHash(pubkey)) == destination)) {
- ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
- ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
+ case MessageVerificationResult::ERR_NOT_SIGNED:
+ ui->statusLabel_VM->setText(
+ QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>")
+ );
return;
}
-
- ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
- ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verified.") + QString("</nobr>"));
}
void SignVerifyMessageDialog::on_clearButton_VM_clicked()
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index dc62f776b6..ced6a299d5 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -139,7 +139,7 @@ SplashScreen::~SplashScreen()
bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) {
if (ev->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
- if(keyEvent->text()[0] == 'q') {
+ if (keyEvent->key() == Qt::Key_Q) {
m_node.startShutdown();
}
}
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index 0f082802cc..476128520c 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -8,6 +8,7 @@
#include <interfaces/chain.h>
#include <interfaces/node.h>
+#include <qt/clientmodel.h>
#include <qt/editaddressdialog.h>
#include <qt/optionsmodel.h>
#include <qt/platformstyle.h>
@@ -97,7 +98,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
auto check_addbook_size = [&wallet](int expected_size) {
LOCK(wallet->cs_wallet);
- QCOMPARE(static_cast<int>(wallet->mapAddressBook.size()), expected_size);
+ QCOMPARE(static_cast<int>(wallet->m_address_book.size()), expected_size);
};
// We should start with the two addresses we added earlier and nothing else.
@@ -106,8 +107,9 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
// Initialize relevant QT models.
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
OptionsModel optionsModel(node);
+ ClientModel clientModel(node, &optionsModel);
AddWallet(wallet);
- WalletModel walletModel(interfaces::MakeWallet(wallet), node, platformStyle.get(), &optionsModel);
+ WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get());
RemoveWallet(wallet);
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel());
diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp
index 14a75b23f3..f88d57c716 100644
--- a/src/qt/test/apptests.cpp
+++ b/src/qt/test/apptests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
@@ -82,6 +82,7 @@ void AppTests::appTests()
// Reset global state to avoid interfering with later tests.
AbortShutdown();
UnloadBlockIndex();
+ WITH_LOCK(::cs_main, g_chainman.Reset());
}
//! Entry point for BitcoinGUI tests.
diff --git a/src/qt/test/apptests.h b/src/qt/test/apptests.h
index d16c9fe487..f0a555005d 100644
--- a/src/qt/test/apptests.h
+++ b/src/qt/test/apptests.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
diff --git a/src/qt/test/util.cpp b/src/qt/test/util.cpp
index e09f0ad77d..759832381b 100644
--- a/src/qt/test/util.cpp
+++ b/src/qt/test/util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-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.
diff --git a/src/qt/test/util.h b/src/qt/test/util.h
index 763847606a..950314da3b 100644
--- a/src/qt/test/util.h
+++ b/src/qt/test/util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-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.
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index c1a0f63f73..2ee9ae0d86 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -8,6 +8,7 @@
#include <interfaces/chain.h>
#include <interfaces/node.h>
#include <qt/bitcoinamountfield.h>
+#include <qt/clientmodel.h>
#include <qt/optionsmodel.h>
#include <qt/platformstyle.h>
#include <qt/qvalidatedlineedit.h>
@@ -144,19 +145,15 @@ void TestGUI(interfaces::Node& node)
wallet->LoadWallet(firstRun);
{
auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
- auto locked_chain = wallet->chain().lock();
LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
wallet->SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type), "", "receive");
spk_man->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
wallet->SetLastBlockProcessed(105, ::ChainActive().Tip()->GetBlockHash());
}
{
- auto locked_chain = wallet->chain().lock();
- LockAssertion lock(::cs_main);
-
- WalletRescanReserver reserver(wallet.get());
+ WalletRescanReserver reserver(*wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet->ScanForWalletTransactions(locked_chain->getBlockHash(0), {} /* stop_block */, reserver, true /* fUpdate */);
+ CWallet::ScanResult result = wallet->ScanForWalletTransactions(Params().GetConsensus().hashGenesisBlock, 0 /* block height */, {} /* max height */, reserver, true /* fUpdate */);
QCOMPARE(result.status, CWallet::ScanResult::SUCCESS);
QCOMPARE(result.last_scanned_block, ::ChainActive().Tip()->GetBlockHash());
QVERIFY(result.last_failed_block.IsNull());
@@ -168,8 +165,9 @@ void TestGUI(interfaces::Node& node)
SendCoinsDialog sendCoinsDialog(platformStyle.get());
TransactionView transactionView(platformStyle.get());
OptionsModel optionsModel(node);
+ ClientModel clientModel(node, &optionsModel);
AddWallet(wallet);
- WalletModel walletModel(interfaces::MakeWallet(wallet), node, platformStyle.get(), &optionsModel);
+ WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get());
RemoveWallet(wallet);
sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel);
diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h
index af5890ba24..7e8bfb2337 100644
--- a/src/qt/trafficgraphwidget.h
+++ b/src/qt/trafficgraphwidget.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/transactiondescdialog.h b/src/qt/transactiondescdialog.h
index 74e34cde87..3204b22657 100644
--- a/src/qt/transactiondescdialog.h
+++ b/src/qt/transactiondescdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 64e9c856db..18554aef1f 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -5,6 +5,7 @@
#include <qt/transactiontablemodel.h>
#include <qt/addresstablemodel.h>
+#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
@@ -175,7 +176,7 @@ public:
return cachedWallet.size();
}
- TransactionRecord *index(interfaces::Wallet& wallet, int idx)
+ TransactionRecord *index(interfaces::Wallet& wallet, const int cur_num_blocks, const int idx)
{
if(idx >= 0 && idx < cachedWallet.size())
{
@@ -191,7 +192,7 @@ public:
interfaces::WalletTxStatus wtx;
int numBlocks;
int64_t block_time;
- if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time) && rec->statusUpdateNeeded(numBlocks)) {
+ if (rec->statusUpdateNeeded(cur_num_blocks) && wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time)) {
rec->updateStatus(wtx, numBlocks, block_time);
}
return rec;
@@ -663,10 +664,10 @@ QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientat
QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent);
- TransactionRecord *data = priv->index(walletModel->wallet(), row);
+ TransactionRecord *data = priv->index(walletModel->wallet(), walletModel->clientModel().getNumBlocks(), row);
if(data)
{
- return createIndex(row, column, priv->index(walletModel->wallet(), row));
+ return createIndex(row, column, data);
}
return QModelIndex();
}
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 95942295ab..01922cf996 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h
index 833b86fd3e..b6a42d3d9d 100644
--- a/src/qt/utilitydialog.h
+++ b/src/qt/utilitydialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-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.
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index 7413a1f09e..9c1488fb0e 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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 <qt/walletcontroller.h>
#include <qt/askpassphrasedialog.h>
+#include <qt/clientmodel.h>
#include <qt/createwalletdialog.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
@@ -24,13 +25,14 @@
#include <QTimer>
#include <QWindow>
-WalletController::WalletController(interfaces::Node& node, const PlatformStyle* platform_style, OptionsModel* options_model, QObject* parent)
+WalletController::WalletController(ClientModel& client_model, const PlatformStyle* platform_style, QObject* parent)
: QObject(parent)
, m_activity_thread(new QThread(this))
, m_activity_worker(new QObject)
- , m_node(node)
+ , m_client_model(client_model)
+ , m_node(client_model.node())
, m_platform_style(platform_style)
- , m_options_model(options_model)
+ , m_options_model(client_model.getOptionsModel())
{
m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
getOrCreateWallet(std::move(wallet));
@@ -104,7 +106,7 @@ WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wal
}
// Instantiate model and register it.
- WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, m_platform_style, m_options_model, nullptr);
+ 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.
wallet_model->moveToThread(thread());
wallet_model->setParent(this);
@@ -116,7 +118,7 @@ WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wal
const bool called = QMetaObject::invokeMethod(wallet_model, "startPollBalance");
assert(called);
- connect(wallet_model, &WalletModel::unload, [this, wallet_model] {
+ connect(wallet_model, &WalletModel::unload, this, [this, wallet_model] {
// Defer removeAndDeleteWallet when no modal widget is active.
// TODO: remove this workaround by removing usage of QDiallog::exec.
if (QApplication::activeModalWidget()) {
@@ -128,7 +130,7 @@ WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wal
} else {
removeAndDeleteWallet(wallet_model);
}
- });
+ }, Qt::QueuedConnection);
// Re-emit coinsSent signal from wallet model.
connect(wallet_model, &WalletModel::coinsSent, this, &WalletController::coinsSent);
@@ -166,6 +168,7 @@ WalletControllerActivity::~WalletControllerActivity()
void WalletControllerActivity::showProgressDialog(const QString& label_text)
{
+ assert(!m_progress_dialog);
m_progress_dialog = new QProgressDialog(m_parent_widget);
m_progress_dialog->setLabelText(label_text);
@@ -175,6 +178,13 @@ void WalletControllerActivity::showProgressDialog(const QString& label_text)
GUIUtil::PolishProgressDialog(m_progress_dialog);
}
+void WalletControllerActivity::destroyProgressDialog()
+{
+ assert(m_progress_dialog);
+ delete m_progress_dialog;
+ m_progress_dialog = nullptr;
+}
+
CreateWalletActivity::CreateWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
: WalletControllerActivity(wallet_controller, parent_widget)
{
@@ -216,10 +226,13 @@ void CreateWalletActivity::createWallet()
if (m_create_wallet_dialog->isMakeBlankWalletChecked()) {
flags |= WALLET_FLAG_BLANK_WALLET;
}
+ if (m_create_wallet_dialog->isDescriptorWalletChecked()) {
+ flags |= WALLET_FLAG_DESCRIPTORS;
+ }
QTimer::singleShot(500, worker(), [this, name, flags] {
- std::unique_ptr<interfaces::Wallet> wallet;
- WalletCreationStatus status = node().createWallet(m_passphrase, flags, name, m_error_message, m_warning_message, wallet);
+ WalletCreationStatus status;
+ std::unique_ptr<interfaces::Wallet> wallet = node().createWallet(m_passphrase, flags, name, m_error_message, m_warning_message, status);
if (status == WalletCreationStatus::SUCCESS) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));
@@ -229,7 +242,7 @@ void CreateWalletActivity::createWallet()
void CreateWalletActivity::finish()
{
- m_progress_dialog->hide();
+ destroyProgressDialog();
if (!m_error_message.empty()) {
QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message));
@@ -270,7 +283,7 @@ OpenWalletActivity::OpenWalletActivity(WalletController* wallet_controller, QWid
void OpenWalletActivity::finish()
{
- m_progress_dialog->hide();
+ destroyProgressDialog();
if (!m_error_message.empty()) {
QMessageBox::critical(m_parent_widget, tr("Open wallet failed"), QString::fromStdString(m_error_message));
diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h
index 956245775e..3808b7d8bf 100644
--- a/src/qt/walletcontroller.h
+++ b/src/qt/walletcontroller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -21,6 +21,7 @@
#include <QTimer>
#include <QString>
+class ClientModel;
class OptionsModel;
class PlatformStyle;
class WalletModel;
@@ -47,7 +48,7 @@ class WalletController : public QObject
void removeAndDeleteWallet(WalletModel* wallet_model);
public:
- WalletController(interfaces::Node& node, const PlatformStyle* platform_style, OptionsModel* options_model, QObject* parent);
+ WalletController(ClientModel& client_model, const PlatformStyle* platform_style, QObject* parent);
~WalletController();
//! Returns wallet models currently open.
@@ -70,6 +71,7 @@ Q_SIGNALS:
private:
QThread* const m_activity_thread;
QObject* const m_activity_worker;
+ ClientModel& m_client_model;
interfaces::Node& m_node;
const PlatformStyle* const m_platform_style;
OptionsModel* const m_options_model;
@@ -96,6 +98,7 @@ protected:
QObject* worker() const { return m_wallet_controller->m_activity_worker; }
void showProgressDialog(const QString& label_text);
+ void destroyProgressDialog();
WalletController* const m_wallet_controller;
QWidget* const m_parent_widget;
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 656fffd067..02a9583ae9 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -37,6 +37,10 @@ WalletFrame::~WalletFrame()
void WalletFrame::setClientModel(ClientModel *_clientModel)
{
this->clientModel = _clientModel;
+
+ for (auto i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) {
+ i.value()->setClientModel(_clientModel);
+ }
}
bool WalletFrame::addWallet(WalletModel *walletModel)
@@ -159,6 +163,14 @@ void WalletFrame::gotoVerifyMessageTab(QString addr)
walletView->gotoVerifyMessageTab(addr);
}
+void WalletFrame::gotoLoadPSBT()
+{
+ WalletView *walletView = currentWalletView();
+ if (walletView) {
+ walletView->gotoLoadPSBT();
+ }
+}
+
void WalletFrame::encryptWallet(bool status)
{
WalletView *walletView = currentWalletView();
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index 20fad08b0e..d90ade5005 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -78,6 +78,9 @@ public Q_SLOTS:
/** Show Sign/Verify Message dialog and switch to verify message tab */
void gotoVerifyMessageTab(QString addr = "");
+ /** Load Partially Signed Bitcoin Transaction */
+ void gotoLoadPSBT();
+
/** Encrypt the wallet */
void encryptWallet(bool status);
/** Backup the wallet */
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 6c3a06f3a2..e7581cd64e 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -9,6 +9,7 @@
#include <qt/walletmodel.h>
#include <qt/addresstablemodel.h>
+#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
@@ -20,10 +21,11 @@
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <key_io.h>
+#include <psbt.h>
#include <ui_interface.h>
#include <util/system.h> // for GetBoolArg
#include <wallet/coincontrol.h>
-#include <wallet/wallet.h>
+#include <wallet/wallet.h> // for CRecipient
#include <stdint.h>
@@ -33,8 +35,13 @@
#include <QTimer>
-WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *_optionsModel, QObject *parent) :
- QObject(parent), m_wallet(std::move(wallet)), m_node(node), optionsModel(_optionsModel), addressTableModel(nullptr),
+WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, ClientModel& client_model, const PlatformStyle *platformStyle, QObject *parent) :
+ QObject(parent),
+ m_wallet(std::move(wallet)),
+ m_client_model(client_model),
+ m_node(client_model.node()),
+ optionsModel(client_model.getOptionsModel()),
+ addressTableModel(nullptr),
transactionTableModel(nullptr),
recentRequestsTableModel(nullptr),
cachedEncryptionStatus(Unencrypted),
@@ -78,21 +85,18 @@ void WalletModel::pollBalanceChanged()
// rescan.
interfaces::WalletBalances new_balances;
int numBlocks = -1;
- if (!m_wallet->tryGetBalances(new_balances, numBlocks)) {
+ if (!m_wallet->tryGetBalances(new_balances, numBlocks, fForceCheckBalanceChanged, cachedNumBlocks)) {
return;
}
- if(fForceCheckBalanceChanged || m_node.getNumBlocks() != cachedNumBlocks)
- {
- fForceCheckBalanceChanged = false;
+ fForceCheckBalanceChanged = false;
- // Balance and number of transactions might have changed
- cachedNumBlocks = m_node.getNumBlocks();
+ // Balance and number of transactions might have changed
+ cachedNumBlocks = numBlocks;
- checkBalanceChanged(new_balances);
- if(transactionTableModel)
- transactionTableModel->updateConfirmations();
- }
+ checkBalanceChanged(new_balances);
+ if(transactionTableModel)
+ transactionTableModel->updateConfirmations();
}
void WalletModel::checkBalanceChanged(const interfaces::WalletBalances& new_balances)
@@ -184,7 +188,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
std::string strFailReason;
auto& newTx = transaction.getWtx();
- newTx = m_wallet->createTransaction(vecSend, coinControl, !privateKeysDisabled() /* sign */, nChangePosRet, nFeeRequired, strFailReason);
+ newTx = m_wallet->createTransaction(vecSend, coinControl, !wallet().privateKeysDisabled() /* sign */, nChangePosRet, nFeeRequired, strFailReason);
transaction.setTransactionFee(nFeeRequired);
if (fSubtractFeeFromAmount && newTx)
transaction.reassignAmounts(nChangePosRet);
@@ -482,13 +486,13 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
CAmount old_fee;
CAmount new_fee;
CMutableTransaction mtx;
- if (!m_wallet->createBumpTransaction(hash, coin_control, 0 /* totalFee */, errors, old_fee, new_fee, mtx)) {
+ if (!m_wallet->createBumpTransaction(hash, coin_control, errors, old_fee, new_fee, mtx)) {
QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" +
(errors.size() ? QString::fromStdString(errors[0]) : "") +")");
return false;
}
- const bool create_psbt = privateKeysDisabled();
+ const bool create_psbt = m_wallet->privateKeysDisabled();
// allow a user based fee verification
QString questionString = create_psbt ? tr("Do you want to draft a transaction with fee increase?") : tr("Do you want to increase the fee?");
@@ -526,7 +530,7 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
if (create_psbt) {
PartiallySignedTransaction psbtx(mtx);
bool complete = false;
- const TransactionError err = wallet().fillPSBT(psbtx, complete, SIGHASH_ALL, false /* sign */, true /* bip32derivs */);
+ const TransactionError err = wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, psbtx, complete);
if (err != TransactionError::OK || complete) {
QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Can't draft transaction."));
return false;
@@ -558,16 +562,6 @@ bool WalletModel::isWalletEnabled()
return !gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET);
}
-bool WalletModel::privateKeysDisabled() const
-{
- return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
-}
-
-bool WalletModel::canGetAddresses() const
-{
- return m_wallet->canGetAddresses();
-}
-
QString WalletModel::getWalletName() const
{
return QString::fromStdString(m_wallet->getWalletName());
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 8087356f5e..07004b7c6b 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -24,6 +24,7 @@
enum class OutputType;
class AddressTableModel;
+class ClientModel;
class OptionsModel;
class PlatformStyle;
class RecentRequestsTableModel;
@@ -52,7 +53,7 @@ class WalletModel : public QObject
Q_OBJECT
public:
- explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *optionsModel, QObject *parent = nullptr);
+ explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, ClientModel& client_model, const PlatformStyle *platformStyle, QObject *parent = nullptr);
~WalletModel();
enum StatusCode // Returned by sendCoins
@@ -140,11 +141,10 @@ public:
bool bumpFee(uint256 hash, uint256& new_hash);
static bool isWalletEnabled();
- bool privateKeysDisabled() const;
- bool canGetAddresses() const;
interfaces::Node& node() const { return m_node; }
interfaces::Wallet& wallet() const { return *m_wallet; }
+ ClientModel& clientModel() const { return m_client_model; }
QString getWalletName() const;
QString getDisplayName() const;
@@ -161,6 +161,7 @@ private:
std::unique_ptr<interfaces::Handler> m_handler_show_progress;
std::unique_ptr<interfaces::Handler> m_handler_watch_only_changed;
std::unique_ptr<interfaces::Handler> m_handler_can_get_addrs_changed;
+ ClientModel& m_client_model;
interfaces::Node& m_node;
bool fHaveWatchOnly;
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index bdcb82e06b..5d9b420df7 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -1,9 +1,12 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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 <qt/walletview.h>
+#include <node/psbt.h>
+#include <node/transaction.h>
+#include <policy/policy.h>
#include <qt/addressbookpage.h>
#include <qt/askpassphrasedialog.h>
#include <qt/clientmodel.h>
@@ -20,6 +23,7 @@
#include <interfaces/node.h>
#include <ui_interface.h>
+#include <util/strencodings.h>
#include <QAction>
#include <QActionGroup>
@@ -197,6 +201,80 @@ void WalletView::gotoVerifyMessageTab(QString addr)
signVerifyMessageDialog->setAddress_VM(addr);
}
+void WalletView::gotoLoadPSBT()
+{
+ QString filename = GUIUtil::getOpenFileName(this,
+ tr("Load Transaction Data"), QString(),
+ tr("Partially Signed Transaction (*.psbt)"), nullptr);
+ if (filename.isEmpty()) return;
+ if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) == MAX_FILE_SIZE_PSBT) {
+ Q_EMIT message(tr("Error"), tr("PSBT file must be smaller than 100 MiB"), CClientUIInterface::MSG_ERROR);
+ return;
+ }
+ std::ifstream in(filename.toLocal8Bit().data(), std::ios::binary);
+ std::string data(std::istreambuf_iterator<char>{in}, {});
+
+ std::string error;
+ PartiallySignedTransaction psbtx;
+ if (!DecodeRawPSBT(psbtx, data, error)) {
+ Q_EMIT message(tr("Error"), tr("Unable to decode PSBT file") + "\n" + QString::fromStdString(error), CClientUIInterface::MSG_ERROR);
+ return;
+ }
+
+ CMutableTransaction mtx;
+ bool complete = false;
+ PSBTAnalysis analysis = AnalyzePSBT(psbtx);
+ QMessageBox msgBox;
+ msgBox.setText("PSBT");
+ switch (analysis.next) {
+ case PSBTRole::CREATOR:
+ case PSBTRole::UPDATER:
+ msgBox.setInformativeText("PSBT is incomplete. Copy to clipboard for manual inspection?");
+ break;
+ case PSBTRole::SIGNER:
+ msgBox.setInformativeText("Transaction needs more signatures. Copy to clipboard?");
+ break;
+ case PSBTRole::FINALIZER:
+ case PSBTRole::EXTRACTOR:
+ complete = FinalizeAndExtractPSBT(psbtx, mtx);
+ if (complete) {
+ msgBox.setInformativeText(tr("Would you like to send this transaction?"));
+ } else {
+ // The analyzer missed something, e.g. if there are final_scriptSig/final_scriptWitness
+ // but with invalid signatures.
+ msgBox.setInformativeText(tr("There was an unexpected problem processing the PSBT. Copy to clipboard for manual inspection?"));
+ }
+ }
+
+ msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
+ switch (msgBox.exec()) {
+ case QMessageBox::Yes: {
+ if (complete) {
+ std::string err_string;
+ CTransactionRef tx = MakeTransactionRef(mtx);
+
+ TransactionError result = BroadcastTransaction(*clientModel->node().context(), tx, err_string, DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK(), /* relay */ true, /* wait_callback */ false);
+ if (result == TransactionError::OK) {
+ Q_EMIT message(tr("Success"), tr("Broadcasted transaction sucessfully."), CClientUIInterface::MSG_INFORMATION | CClientUIInterface::MODAL);
+ } else {
+ Q_EMIT message(tr("Error"), QString::fromStdString(err_string), CClientUIInterface::MSG_ERROR);
+ }
+ } else {
+ // Serialize the PSBT
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ ssTx << psbtx;
+ GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str());
+ Q_EMIT message(tr("PSBT copied"), "Copied to clipboard", CClientUIInterface::MSG_INFORMATION);
+ return;
+ }
+ }
+ case QMessageBox::Cancel:
+ break;
+ default:
+ assert(false);
+ }
+}
+
bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient)
{
return sendCoinsPage->handlePaymentRequest(recipient);
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index 86e46348be..11f894e7f8 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -66,7 +66,7 @@ private:
TransactionView *transactionView;
- QProgressDialog *progressDialog;
+ QProgressDialog* progressDialog{nullptr};
const PlatformStyle *platformStyle;
public Q_SLOTS:
@@ -83,6 +83,8 @@ public Q_SLOTS:
void gotoSignMessageTab(QString addr = "");
/** Show Sign/Verify Message dialog and switch to verify message tab */
void gotoVerifyMessageTab(QString addr = "");
+ /** Load Partially Signed Bitcoin Transaction */
+ void gotoLoadPSBT();
/** Show incoming transaction notification for new transactions.
diff --git a/src/random.cpp b/src/random.cpp
index f0082cf3e0..b408b1e13e 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -15,7 +15,7 @@
#endif
#include <logging.h> // for LogPrintf()
#include <sync.h> // for Mutex
-#include <util/time.h> // for GetTime()
+#include <util/time.h> // for GetTimeMicros()
#include <stdlib.h>
#include <thread>
@@ -315,19 +315,16 @@ void GetOSRand(unsigned char *ent32)
RandFailure();
}
#elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
- // We need a fallback for OSX < 10.12
- if (&getentropy != nullptr) {
- if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
- RandFailure();
- }
- } else {
- GetDevURandom(ent32);
+ /* getentropy() is available on macOS 10.12 and later.
+ */
+ if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
+ RandFailure();
}
#elif defined(HAVE_SYSCTL_ARND)
- /* FreeBSD and similar. It is possible for the call to return less
+ /* FreeBSD, NetBSD and similar. It is possible for the call to return less
* bytes than requested, so need to read in a loop.
*/
- static const int name[2] = {CTL_KERN, KERN_ARND};
+ static int name[2] = {CTL_KERN, KERN_ARND};
int have = 0;
do {
size_t len = NUM_OS_RANDOM_BYTES - have;
@@ -595,6 +592,11 @@ std::chrono::microseconds GetRandMicros(std::chrono::microseconds duration_max)
return std::chrono::microseconds{GetRand(duration_max.count())};
}
+std::chrono::milliseconds GetRandMillis(std::chrono::milliseconds duration_max) noexcept
+{
+ return std::chrono::milliseconds{GetRand(duration_max.count())};
+}
+
int GetRandInt(int nMax) noexcept
{
return GetRand(nMax);
diff --git a/src/random.h b/src/random.h
index 518a5cd3e3..690125079b 100644
--- a/src/random.h
+++ b/src/random.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -69,6 +69,7 @@
void GetRandBytes(unsigned char* buf, int num) noexcept;
uint64_t GetRand(uint64_t nMax) noexcept;
std::chrono::microseconds GetRandMicros(std::chrono::microseconds duration_max) noexcept;
+std::chrono::milliseconds GetRandMillis(std::chrono::milliseconds duration_max) noexcept;
int GetRandInt(int nMax) noexcept;
uint256 GetRandHash() noexcept;
@@ -103,7 +104,8 @@ void RandAddEvent(const uint32_t event_info) noexcept;
*
* This class is not thread-safe.
*/
-class FastRandomContext {
+class FastRandomContext
+{
private:
bool requires_seed;
ChaCha20 rng;
@@ -155,7 +157,8 @@ public:
}
/** Generate a random (bits)-bit integer. */
- uint64_t randbits(int bits) noexcept {
+ uint64_t randbits(int bits) noexcept
+ {
if (bits == 0) {
return 0;
} else if (bits > 32) {
@@ -169,7 +172,9 @@ public:
}
}
- /** Generate a random integer in the range [0..range). */
+ /** Generate a random integer in the range [0..range).
+ * Precondition: range > 0.
+ */
uint64_t randrange(uint64_t range) noexcept
{
assert(range);
@@ -210,7 +215,7 @@ public:
* debug mode detects and panics on. This is a known issue, see
* https://stackoverflow.com/questions/22915325/avoiding-self-assignment-in-stdshuffle
*/
-template<typename I, typename R>
+template <typename I, typename R>
void Shuffle(I first, I last, R&& rng)
{
while (first != last) {
@@ -233,7 +238,7 @@ static const int NUM_OS_RANDOM_BYTES = 32;
/** Get 32 bytes of system entropy. Do not use this in application code: use
* GetStrongRandBytes instead.
*/
-void GetOSRand(unsigned char *ent32);
+void GetOSRand(unsigned char* ent32);
/** Check that OS randomness is available and returning the requested number
* of bytes.
diff --git a/src/randomenv.cpp b/src/randomenv.cpp
index 6992c720ff..073d82b491 100644
--- a/src/randomenv.cpp
+++ b/src/randomenv.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -38,11 +38,6 @@
#include <sys/utsname.h>
#include <unistd.h>
#endif
-#ifdef __MACH__
-#include <mach/clock.h>
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-#endif
#if HAVE_DECL_GETIFADDRS
#include <ifaddrs.h>
#endif
@@ -237,8 +232,6 @@ void RandAddDynamicEnv(CSHA512& hasher)
GetSystemTimeAsFileTime(&ftime);
hasher << ftime;
#else
-# ifndef __MACH__
- // On non-MacOS systems, use various clock_gettime() calls.
struct timespec ts = {};
# ifdef CLOCK_MONOTONIC
clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -252,18 +245,6 @@ void RandAddDynamicEnv(CSHA512& hasher)
clock_gettime(CLOCK_BOOTTIME, &ts);
hasher << ts;
# endif
-# else
- // On MacOS use mach_absolute_time (number of CPU ticks since boot) as a replacement for CLOCK_MONOTONIC,
- // and clock_get_time for CALENDAR_CLOCK as a replacement for CLOCK_REALTIME.
- hasher << mach_absolute_time();
- // From https://gist.github.com/jbenet/1087739
- clock_serv_t cclock;
- mach_timespec_t mts = {};
- if (host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock) == KERN_SUCCESS && clock_get_time(cclock, &mts) == KERN_SUCCESS) {
- hasher << mts;
- mach_port_deallocate(mach_task_self(), cclock);
- }
-# endif
// gettimeofday is available on all UNIX systems, but only has microsecond precision.
struct timeval tv = {};
gettimeofday(&tv, nullptr);
diff --git a/src/rest.cpp b/src/rest.cpp
index 0629557584..5f99e26bad 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -206,7 +206,7 @@ static bool rest_headers(HTTPRequest* req,
return true;
}
default: {
- return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: .bin, .hex)");
+ return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: .bin, .hex, .json)");
}
}
}
@@ -607,7 +607,7 @@ static bool rest_blockhash_by_height(HTTPRequest* req,
std::string height_str;
const RetFormat rf = ParseDataFormat(height_str, str_uri_part);
- int32_t blockheight;
+ int32_t blockheight = -1; // Initialization done only to prevent valgrind false positive, see https://github.com/bitcoin/bitcoin/pull/18785
if (!ParseInt32(height_str, &blockheight) || blockheight < 0) {
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid height: " + SanitizeString(height_str));
}
diff --git a/src/reverselock.h b/src/reverselock.h
deleted file mode 100644
index 9d9cc9fd77..0000000000
--- a/src/reverselock.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2015-2016 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_REVERSELOCK_H
-#define BITCOIN_REVERSELOCK_H
-
-/**
- * An RAII-style reverse lock. Unlocks on construction and locks on destruction.
- */
-template<typename Lock>
-class reverse_lock
-{
-public:
-
- explicit reverse_lock(Lock& _lock) : lock(_lock) {
- _lock.unlock();
- _lock.swap(templock);
- }
-
- ~reverse_lock() {
- templock.lock();
- templock.swap(lock);
- }
-
-private:
- reverse_lock(reverse_lock const&);
- reverse_lock& operator=(reverse_lock const&);
-
- Lock& lock;
- Lock templock;
-};
-
-#endif // BITCOIN_REVERSELOCK_H
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index eb5148eebd..f7ccbae706 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -31,7 +31,6 @@
#include <undo.h>
#include <util/strencodings.h>
#include <util/system.h>
-#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
#include <warnings.h>
@@ -178,8 +177,7 @@ static UniValue getblockcount(const JSONRPCRequest& request)
"The genesis block has height 0.\n",
{},
RPCResult{
- "n (numeric) The current block count\n"
- },
+ RPCResult::Type::NUM, "", "The current block count"},
RPCExamples{
HelpExampleCli("getblockcount", "")
+ HelpExampleRpc("getblockcount", "")
@@ -196,8 +194,7 @@ static UniValue getbestblockhash(const JSONRPCRequest& request)
"\nReturns the hash of the best (tip) block in the most-work fully-validated chain.\n",
{},
RPCResult{
- "\"hex\" (string) the block hash, hex-encoded\n"
- },
+ RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"},
RPCExamples{
HelpExampleCli("getbestblockhash", "")
+ HelpExampleRpc("getbestblockhash", "")
@@ -227,11 +224,11 @@ static UniValue waitfornewblock(const JSONRPCRequest& request)
{"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
},
RPCResult{
- "{ (json object)\n"
- " \"hash\" : { (string) The blockhash\n"
- " \"height\" : { (int) Block height\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
+ {RPCResult::Type::NUM, "height", "Block height"},
+ }},
RPCExamples{
HelpExampleCli("waitfornewblock", "1000")
+ HelpExampleRpc("waitfornewblock", "1000")
@@ -267,13 +264,13 @@ static UniValue waitforblock(const JSONRPCRequest& request)
{"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
},
RPCResult{
- "{ (json object)\n"
- " \"hash\" : { (string) The blockhash\n"
- " \"height\" : { (int) Block height\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
+ {RPCResult::Type::NUM, "height", "Block height"},
+ }},
RPCExamples{
- HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
+ HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\" 1000")
+ HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
},
}.Check(request);
@@ -311,14 +308,14 @@ static UniValue waitforblockheight(const JSONRPCRequest& request)
{"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
},
RPCResult{
- "{ (json object)\n"
- " \"hash\" : { (string) The blockhash\n"
- " \"height\" : { (int) Block height\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
+ {RPCResult::Type::NUM, "height", "Block height"},
+ }},
RPCExamples{
- HelpExampleCli("waitforblockheight", "\"100\", 1000")
- + HelpExampleRpc("waitforblockheight", "\"100\", 1000")
+ HelpExampleCli("waitforblockheight", "100 1000")
+ + HelpExampleRpc("waitforblockheight", "100, 1000")
},
}.Check(request);
int timeout = 0;
@@ -348,7 +345,7 @@ static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request)
RPCHelpMan{"syncwithvalidationinterfacequeue",
"\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("syncwithvalidationinterfacequeue","")
+ HelpExampleRpc("syncwithvalidationinterfacequeue","")
@@ -365,8 +362,7 @@ static UniValue getdifficulty(const JSONRPCRequest& request)
"\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n",
{},
RPCResult{
- "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
- },
+ RPCResult::Type::NUM, "", "the proof-of-work difficulty as a multiple of the minimum difficulty."},
RPCExamples{
HelpExampleCli("getdifficulty", "")
+ HelpExampleRpc("getdifficulty", "")
@@ -377,37 +373,33 @@ static UniValue getdifficulty(const JSONRPCRequest& request)
return GetDifficulty(::ChainActive().Tip());
}
-static std::string EntryDescriptionString()
-{
- return " \"vsize\" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.\n"
- " \"size\" : n, (numeric) (DEPRECATED) same as vsize. Only returned if bitcoind is started with -deprecatedrpc=size\n"
- " size will be completely removed in v0.20.\n"
- " \"weight\" : n, (numeric) transaction weight as defined in BIP 141.\n"
- " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)\n"
- " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority (DEPRECATED)\n"
- " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
- " \"height\" : n, (numeric) block height when transaction entered pool\n"
- " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n"
- " \"descendantsize\" : n, (numeric) virtual transaction size of in-mempool descendants (including this one)\n"
- " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) (DEPRECATED)\n"
- " \"ancestorcount\" : n, (numeric) number of in-mempool ancestor transactions (including this one)\n"
- " \"ancestorsize\" : n, (numeric) virtual transaction size of in-mempool ancestors (including this one)\n"
- " \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) (DEPRECATED)\n"
- " \"wtxid\" : hash, (string) hash of serialized transaction, including witness data\n"
- " \"fees\" : {\n"
- " \"base\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n"
- " \"modified\" : n, (numeric) transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT + "\n"
- " \"ancestor\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT + "\n"
- " \"descendant\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT + "\n"
- " }\n"
- " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
- " \"transactionid\", (string) parent transaction id\n"
- " ... ]\n"
- " \"spentby\" : [ (array) unconfirmed transactions spending outputs from this transaction\n"
- " \"transactionid\", (string) child transaction id\n"
- " ... ]\n"
- " \"bip125-replaceable\" : true|false, (boolean) Whether this transaction could be replaced due to BIP125 (replace-by-fee)\n";
-}
+static std::vector<RPCResult> MempoolEntryDescription() { return {
+ RPCResult{RPCResult::Type::NUM, "vsize", "virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."},
+ RPCResult{RPCResult::Type::NUM, "weight", "transaction weight as defined in BIP 141."},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "fee", "transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)"},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee", "transaction fee with fee deltas used for mining priority (DEPRECATED)"},
+ RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"},
+ RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"},
+ RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"},
+ RPCResult{RPCResult::Type::NUM, "descendantsize", "virtual transaction size of in-mempool descendants (including this one)"},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees", "modified fees (see above) of in-mempool descendants (including this one) (DEPRECATED)"},
+ RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"},
+ RPCResult{RPCResult::Type::NUM, "ancestorsize", "virtual transaction size of in-mempool ancestors (including this one)"},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees", "modified fees (see above) of in-mempool ancestors (including this one) (DEPRECATED)"},
+ RPCResult{RPCResult::Type::STR_HEX, "wtxid", "hash of serialized transaction, including witness data"},
+ RPCResult{RPCResult::Type::OBJ, "fees", "",
+ {
+ RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT},
+ }},
+ RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction",
+ {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}},
+ RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction",
+ {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}},
+ RPCResult{RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction could be replaced due to BIP125 (replace-by-fee)"},
+};}
static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
{
@@ -421,7 +413,6 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool
info.pushKV("fees", fees);
info.pushKV("vsize", (int)e.GetTxSize());
- if (IsDeprecatedRPCEnabled("size")) info.pushKV("size", (int)e.GetTxSize());
info.pushKV("weight", (int)e.GetTxWeight());
info.pushKV("fee", ValueFromAmount(e.GetFee()));
info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee()));
@@ -506,17 +497,17 @@ static UniValue getrawmempool(const JSONRPCRequest& request)
{
{"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"},
},
- RPCResult{"for verbose = false",
- "[ (json array of string)\n"
- " \"transactionid\" (string) The transaction id\n"
- " ,...\n"
- "]\n"
- "\nResult: (for verbose = true):\n"
- "{ (json object)\n"
- " \"transactionid\" : { (json object)\n"
- + EntryDescriptionString()
- + " }, ...\n"
- "}\n"
+ {
+ RPCResult{"for verbose = false",
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "", "The transaction id"},
+ }},
+ RPCResult{"for verbose = true",
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ_DYN, "transactionid", "", MempoolEntryDescription()},
+ }},
},
RPCExamples{
HelpExampleCli("getrawmempool", "true")
@@ -541,18 +532,10 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request)
},
{
RPCResult{"for verbose = false",
- "[ (json array of strings)\n"
- " \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n"
- " ,...\n"
- "]\n"
- },
+ RPCResult::Type::ARR, "", "",
+ {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool ancestor transaction"}}},
RPCResult{"for verbose = true",
- "{ (json object)\n"
- " \"transactionid\" : { (json object)\n"
- + EntryDescriptionString()
- + " }, ...\n"
- "}\n"
- },
+ RPCResult::Type::OBJ_DYN, "transactionid", "", MempoolEntryDescription()},
},
RPCExamples{
HelpExampleCli("getmempoolancestors", "\"mytxid\"")
@@ -609,18 +592,13 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request)
},
{
RPCResult{"for verbose = false",
- "[ (json array of strings)\n"
- " \"transactionid\" (string) The transaction id of an in-mempool descendant transaction\n"
- " ,...\n"
- "]\n"
- },
+ RPCResult::Type::ARR, "", "",
+ {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool descendant transaction"}}},
RPCResult{"for verbose = true",
- "{ (json object)\n"
- " \"transactionid\" : { (json object)\n"
- + EntryDescriptionString()
- + " }, ...\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ_DYN, "transactionid", "", MempoolEntryDescription()},
+ }},
},
RPCExamples{
HelpExampleCli("getmempooldescendants", "\"mytxid\"")
@@ -675,10 +653,7 @@ static UniValue getmempoolentry(const JSONRPCRequest& request)
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
},
RPCResult{
- "{ (json object)\n"
- + EntryDescriptionString()
- + "}\n"
- },
+ RPCResult::Type::OBJ_DYN, "", "", MempoolEntryDescription()},
RPCExamples{
HelpExampleCli("getmempoolentry", "\"mytxid\"")
+ HelpExampleRpc("getmempoolentry", "\"mytxid\"")
@@ -709,8 +684,7 @@ static UniValue getblockhash(const JSONRPCRequest& request)
{"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The height index"},
},
RPCResult{
- "\"hash\" (string) The block hash\n"
- },
+ RPCResult::Type::STR_HEX, "", "The block hash"},
RPCExamples{
HelpExampleCli("getblockhash", "1000")
+ HelpExampleRpc("getblockhash", "1000")
@@ -738,27 +712,26 @@ static UniValue getblockheader(const JSONRPCRequest& request)
},
{
RPCResult{"for verbose = true",
- "{\n"
- " \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
- " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
- " \"height\" : n, (numeric) The block height or index\n"
- " \"version\" : n, (numeric) The block version\n"
- " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
- " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
- " \"time\" : ttt, (numeric) The block time expressed in " + UNIX_EPOCH_TIME + "\n"
- " \"mediantime\" : ttt, (numeric) The median block time expressed in " + UNIX_EPOCH_TIME + "\n"
- " \"nonce\" : n, (numeric) The nonce\n"
- " \"bits\" : \"1d00ffff\", (string) The bits\n"
- " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
- " \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n"
- " \"nTx\" : n, (numeric) The number of transactions in the block.\n"
- " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
- " \"nextblockhash\" : \"hash\", (string) The hash of the next block\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "the block hash (same as provided)"},
+ {RPCResult::Type::NUM, "confirmations", "The number of confirmations, or -1 if the block is not on the main chain"},
+ {RPCResult::Type::NUM, "height", "The block height or index"},
+ {RPCResult::Type::NUM, "version", "The block version"},
+ {RPCResult::Type::STR_HEX, "versionHex", "The block version formatted in hexadecimal"},
+ {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"},
+ {RPCResult::Type::NUM_TIME, "time", "The block time expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM, "nonce", "The nonce"},
+ {RPCResult::Type::STR_HEX, "bits", "The bits"},
+ {RPCResult::Type::NUM, "difficulty", "The difficulty"},
+ {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the current chain"},
+ {RPCResult::Type::NUM, "nTx", "The number of transactions in the block"},
+ {RPCResult::Type::STR_HEX, "previousblockhash", "The hash of the previous block"},
+ {RPCResult::Type::STR_HEX, "nextblockhash", "The hash of the next block"},
+ }},
RPCResult{"for verbose=false",
- "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
- },
+ RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"},
},
RPCExamples{
HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
@@ -836,48 +809,49 @@ static UniValue getblock(const JSONRPCRequest& request)
"If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n",
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
- {"verbosity", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"},
+ {"verbosity|verbose", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"},
},
{
RPCResult{"for verbosity = 0",
- "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
- },
+ RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"},
RPCResult{"for verbosity = 1",
- "{\n"
- " \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
- " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
- " \"size\" : n, (numeric) The block size\n"
- " \"strippedsize\" : n, (numeric) The block size excluding witness data\n"
- " \"weight\" : n (numeric) The block weight as defined in BIP 141\n"
- " \"height\" : n, (numeric) The block height or index\n"
- " \"version\" : n, (numeric) The block version\n"
- " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
- " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
- " \"tx\" : [ (array of string) The transaction ids\n"
- " \"transactionid\" (string) The transaction id\n"
- " ,...\n"
- " ],\n"
- " \"time\" : ttt, (numeric) The block time expressed in " + UNIX_EPOCH_TIME + "\n"
- " \"mediantime\" : ttt, (numeric) The median block time expressed in " + UNIX_EPOCH_TIME + "\n"
- " \"nonce\" : n, (numeric) The nonce\n"
- " \"bits\" : \"1d00ffff\", (string) The bits\n"
- " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
- " \"chainwork\" : \"xxxx\", (string) Expected number of hashes required to produce the chain up to this block (in hex)\n"
- " \"nTx\" : n, (numeric) The number of transactions in the block.\n"
- " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
- " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "the block hash (same as provided)"},
+ {RPCResult::Type::NUM, "confirmations", "The number of confirmations, or -1 if the block is not on the main chain"},
+ {RPCResult::Type::NUM, "size", "The block size"},
+ {RPCResult::Type::NUM, "strippedsize", "The block size excluding witness data"},
+ {RPCResult::Type::NUM, "weight", "The block weight as defined in BIP 141"},
+ {RPCResult::Type::NUM, "height", "The block height or index"},
+ {RPCResult::Type::NUM, "version", "The block version"},
+ {RPCResult::Type::STR_HEX, "versionHex", "The block version formatted in hexadecimal"},
+ {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"},
+ {RPCResult::Type::ARR, "tx", "The transaction ids",
+ {{RPCResult::Type::STR_HEX, "", "The transaction id"}}},
+ {RPCResult::Type::NUM_TIME, "time", "The block time expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM, "nonce", "The nonce"},
+ {RPCResult::Type::STR_HEX, "bits", "The bits"},
+ {RPCResult::Type::NUM, "difficulty", "The difficulty"},
+ {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the chain up to this block (in hex)"},
+ {RPCResult::Type::NUM, "nTx", "The number of transactions in the block"},
+ {RPCResult::Type::STR_HEX, "previousblockhash", "The hash of the previous block"},
+ {RPCResult::Type::STR_HEX, "nextblockhash", "The hash of the next block"},
+ }},
RPCResult{"for verbosity = 2",
- "{\n"
- " ..., Same output as verbosity = 1.\n"
- " \"tx\" : [ (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result.\n"
- " ,...\n"
- " ],\n"
- " ,... Same output as verbosity = 1.\n"
- "}\n"
- },
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::ELISION, "", "Same output as verbosity = 1"},
+ {RPCResult::Type::ARR, "tx", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::ELISION, "", "The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result"},
+ }},
+ }},
+ {RPCResult::Type::ELISION, "", "Same output as verbosity = 1"},
+ }},
+ },
RPCExamples{
HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
@@ -928,8 +902,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
" to prune blocks whose block time is at least 2 hours older than the provided timestamp."},
},
RPCResult{
- "n (numeric) Height of the last block pruned.\n"
- },
+ RPCResult::Type::NUM, "", "Height of the last block pruned"},
RPCExamples{
HelpExampleCli("pruneblockchain", "1000")
+ HelpExampleRpc("pruneblockchain", "1000")
@@ -983,17 +956,17 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
"Note this call may take some time.\n",
{},
RPCResult{
- "{\n"
- " \"height\":n, (numeric) The current block height (index)\n"
- " \"bestblock\": \"hex\", (string) The hash of the block at the tip of the chain\n"
- " \"transactions\": n, (numeric) The number of transactions with unspent outputs\n"
- " \"txouts\": n, (numeric) The number of unspent transaction outputs\n"
- " \"bogosize\": n, (numeric) A meaningless metric for UTXO set size\n"
- " \"hash_serialized_2\": \"hash\", (string) The serialized hash\n"
- " \"disk_size\": n, (numeric) The estimated size of the chainstate on disk\n"
- " \"total_amount\": x.xxx (numeric) The total amount\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "height", "The current block height (index)"},
+ {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"},
+ {RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"},
+ {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"},
+ {RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"},
+ {RPCResult::Type::STR_HEX, "hash_serialized_2", "The serialized hash"},
+ {RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk"},
+ {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount"},
+ }},
RPCExamples{
HelpExampleCli("gettxoutsetinfo", "")
+ HelpExampleRpc("gettxoutsetinfo", "")
@@ -1031,23 +1004,22 @@ UniValue gettxout(const JSONRPCRequest& request)
{"include_mempool", RPCArg::Type::BOOL, /* default */ "true", "Whether to include the mempool. Note that an unspent output that is spent in the mempool won't appear."},
},
RPCResult{
- "{\n"
- " \"bestblock\": \"hash\", (string) The hash of the block at the tip of the chain\n"
- " \"confirmations\" : n, (numeric) The number of confirmations\n"
- " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n"
- " \"scriptPubKey\" : { (json object)\n"
- " \"asm\" : \"code\", (string) \n"
- " \"hex\" : \"hex\", (string) \n"
- " \"reqSigs\" : n, (numeric) Number of required signatures\n"
- " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
- " \"addresses\" : [ (array of string) array of bitcoin addresses\n"
- " \"address\" (string) bitcoin address\n"
- " ,...\n"
- " ]\n"
- " },\n"
- " \"coinbase\" : true|false (boolean) Coinbase or not\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"},
+ {RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
+ {RPCResult::Type::STR_AMOUNT, "value", "The transaction value in " + CURRENCY_UNIT},
+ {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {
+ {RPCResult::Type::STR_HEX, "asm", ""},
+ {RPCResult::Type::STR_HEX, "hex", ""},
+ {RPCResult::Type::NUM, "reqSigs", "Number of required signatures"},
+ {RPCResult::Type::STR_HEX, "type", "The type, eg pubkeyhash"},
+ {RPCResult::Type::ARR, "addresses", "array of bitcoin addresses",
+ {{RPCResult::Type::STR, "address", "bitcoin address"}}},
+ }},
+ {RPCResult::Type::BOOL, "coinbase", "Coinbase or not"},
+ }},
RPCExamples{
"\nGet unspent transactions\n"
+ HelpExampleCli("listunspent", "") +
@@ -1103,32 +1075,26 @@ UniValue gettxout(const JSONRPCRequest& request)
static UniValue verifychain(const JSONRPCRequest& request)
{
- int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL);
- int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS);
RPCHelpMan{"verifychain",
"\nVerifies blockchain database.\n",
{
- {"checklevel", RPCArg::Type::NUM, /* default */ strprintf("%d, range=0-4", nCheckLevel), "How thorough the block verification is."},
- {"nblocks", RPCArg::Type::NUM, /* default */ strprintf("%d, 0=all", nCheckDepth), "The number of blocks to check."},
+ {"checklevel", RPCArg::Type::NUM, /* default */ strprintf("%d, range=0-4", DEFAULT_CHECKLEVEL), "How thorough the block verification is."},
+ {"nblocks", RPCArg::Type::NUM, /* default */ strprintf("%d, 0=all", DEFAULT_CHECKBLOCKS), "The number of blocks to check."},
},
RPCResult{
- "true|false (boolean) Verified or not\n"
- },
+ RPCResult::Type::BOOL, "", "Verified or not"},
RPCExamples{
HelpExampleCli("verifychain", "")
+ HelpExampleRpc("verifychain", "")
},
}.Check(request);
- LOCK(cs_main);
+ const int check_level(request.params[0].isNull() ? DEFAULT_CHECKLEVEL : request.params[0].get_int());
+ const int check_depth{request.params[1].isNull() ? DEFAULT_CHECKBLOCKS : request.params[1].get_int()};
- if (!request.params[0].isNull())
- nCheckLevel = request.params[0].get_int();
- if (!request.params[1].isNull())
- nCheckDepth = request.params[1].get_int();
+ LOCK(cs_main);
- return CVerifyDB().VerifyDB(
- Params(), &::ChainstateActive().CoinsTip(), nCheckLevel, nCheckDepth);
+ return CVerifyDB().VerifyDB(Params(), &::ChainstateActive().CoinsTip(), check_level, check_depth);
}
static void BuriedForkDescPushBack(UniValue& softforks, const std::string &name, int height) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -1203,45 +1169,49 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
"Returns an object containing various state info regarding blockchain processing.\n",
{},
RPCResult{
- "{\n"
- " \"chain\": \"xxxx\", (string) current network name (main, test, regtest)\n"
- " \"blocks\": xxxxxx, (numeric) the height of the most-work fully-validated chain. The genesis block has height 0\n"
- " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n"
- " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
- " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
- " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n"
- " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
- " \"initialblockdownload\": xxxx, (bool) (debug information) estimate of whether this node is in Initial Block Download mode.\n"
- " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
- " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n"
- " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n"
- " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n"
- " \"automatic_pruning\": xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n"
- " \"prune_target_size\": xxxxxx, (numeric) the target size used by pruning (only present if automatic pruning is enabled)\n"
- " \"softforks\": { (object) status of softforks\n"
- " \"xxxx\" : { (string) name of the softfork\n"
- " \"type\": \"xxxx\", (string) one of \"buried\", \"bip9\"\n"
- " \"bip9\": { (object) status of bip9 softforks (only for \"bip9\" type)\n"
- " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n"
- " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n"
- " \"start_time\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
- " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
- " \"since\": xx, (numeric) height of the first block to which the status applies\n"
- " \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork\n"
- " \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n"
- " \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n"
- " \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n"
- " \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n"
- " \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n"
- " }\n"
- " },\n"
- " \"height\": \"xxxxxx\", (numeric) height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)\n"
- " \"active\": xx, (boolean) true if the rules are enforced for the mempool and the next block\n"
- " }\n"
- " }\n"
- " \"warnings\" : \"...\", (string) any network and blockchain warnings.\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "chain", "current network name (main, test, regtest)"},
+ {RPCResult::Type::NUM, "blocks", "the height of the most-work fully-validated chain. The genesis block has height 0"},
+ {RPCResult::Type::NUM, "headers", "the current number of headers we have validated"},
+ {RPCResult::Type::STR, "bestblockhash", "the hash of the currently best block"},
+ {RPCResult::Type::NUM, "difficulty", "the current difficulty"},
+ {RPCResult::Type::NUM, "mediantime", "median time for the current best block"},
+ {RPCResult::Type::NUM, "verificationprogress", "estimate of verification progress [0..1]"},
+ {RPCResult::Type::BOOL, "initialblockdownload", "(debug information) estimate of whether this node is in Initial Block Download mode"},
+ {RPCResult::Type::STR_HEX, "chainwork", "total amount of work in active chain, in hexadecimal"},
+ {RPCResult::Type::NUM, "size_on_disk", "the estimated size of the block and undo files on disk"},
+ {RPCResult::Type::BOOL, "pruned", "if the blocks are subject to pruning"},
+ {RPCResult::Type::NUM, "pruneheight", "lowest-height complete block stored (only present if pruning is enabled)"},
+ {RPCResult::Type::BOOL, "automatic_pruning", "whether automatic pruning is enabled (only present if pruning is enabled)"},
+ {RPCResult::Type::NUM, "prune_target_size", "the target size used by pruning (only present if automatic pruning is enabled)"},
+ {RPCResult::Type::OBJ_DYN, "softforks", "status of softforks",
+ {
+ {RPCResult::Type::OBJ, "xxxx", "name of the softfork",
+ {
+ {RPCResult::Type::STR, "type", "one of \"buried\", \"bip9\""},
+ {RPCResult::Type::OBJ, "bip9", "status of bip9 softforks (only for \"bip9\" type)",
+ {
+ {RPCResult::Type::STR, "status", "one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\""},
+ {RPCResult::Type::NUM, "bit", "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)"},
+ {RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"},
+ {RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"},
+ {RPCResult::Type::NUM, "since", "height of the first block to which the status applies"},
+ {RPCResult::Type::OBJ, "statistics", "numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)",
+ {
+ {RPCResult::Type::NUM, "period", "the length in blocks of the BIP9 signalling period"},
+ {RPCResult::Type::NUM, "threshold", "the number of blocks with the version bit set required to activate the feature"},
+ {RPCResult::Type::NUM, "elapsed", "the number of blocks elapsed since the beginning of the current period"},
+ {RPCResult::Type::NUM, "count", "the number of blocks with the version bit set in the current period"},
+ {RPCResult::Type::BOOL, "possible", "returns false if there are not enough blocks left in this period to pass activation threshold"},
+ }},
+ }},
+ {RPCResult::Type::NUM, "height", "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"},
+ {RPCResult::Type::BOOL, "active", "true if the rules are enforced for the mempool and the next block"},
+ }},
+ }},
+ {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"},
+ }},
RPCExamples{
HelpExampleCli("getblockchaininfo", "")
+ HelpExampleRpc("getblockchaininfo", "")
@@ -1316,27 +1286,20 @@ static UniValue getchaintips(const JSONRPCRequest& request)
" including the main chain as well as orphaned branches.\n",
{},
RPCResult{
- "[\n"
- " {\n"
- " \"height\": xxxx, (numeric) height of the chain tip\n"
- " \"hash\": \"xxxx\", (string) block hash of the tip\n"
- " \"branchlen\": 0 (numeric) zero for main chain\n"
- " \"status\": \"active\" (string) \"active\" for the main chain\n"
- " },\n"
- " {\n"
- " \"height\": xxxx,\n"
- " \"hash\": \"xxxx\",\n"
- " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
- " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
- " }\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {{RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "height", "height of the chain tip"},
+ {RPCResult::Type::STR_HEX, "hash", "block hash of the tip"},
+ {RPCResult::Type::NUM, "branchlen", "zero for main chain, otherwise length of branch connecting the tip to the main chain"},
+ {RPCResult::Type::STR, "status", "status of the chain, \"active\" for the main chain\n"
"Possible values for status:\n"
"1. \"invalid\" This branch contains at least one invalid block\n"
"2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
"3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
"4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
- "5. \"active\" This is the tip of the active main chain, which is certainly valid\n"
- },
+ "5. \"active\" This is the tip of the active main chain, which is certainly valid"},
+ }}}},
RPCExamples{
HelpExampleCli("getchaintips", "")
+ HelpExampleRpc("getchaintips", "")
@@ -1348,7 +1311,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
/*
* Idea: the set of chain tips is ::ChainActive().tip, plus orphan blocks which do not have another orphan building off of them.
* Algorithm:
- * - Make one pass through g_blockman.m_block_index, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
+ * - Make one pass through BlockIndex(), picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
* - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
* - add ::ChainActive().Tip()
*/
@@ -1436,16 +1399,16 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request)
"\nReturns details on the active state of the TX memory pool.\n",
{},
RPCResult{
- "{\n"
- " \"loaded\": true|false (boolean) True if the mempool is fully loaded\n"
- " \"size\": xxxxx, (numeric) Current tx count\n"
- " \"bytes\": xxxxx, (numeric) Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted\n"
- " \"usage\": xxxxx, (numeric) Total memory usage for the mempool\n"
- " \"maxmempool\": xxxxx, (numeric) Maximum memory usage for the mempool\n"
- " \"mempoolminfee\": xxxxx (numeric) Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee\n"
- " \"minrelaytxfee\": xxxxx (numeric) Current minimum relay fee for transactions\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "loaded", "True if the mempool is fully loaded"},
+ {RPCResult::Type::NUM, "size", "Current tx count"},
+ {RPCResult::Type::NUM, "bytes", "Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted"},
+ {RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"},
+ {RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"},
+ {RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"},
+ {RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"},
+ }},
RPCExamples{
HelpExampleCli("getmempoolinfo", "")
+ HelpExampleRpc("getmempoolinfo", "")
@@ -1464,7 +1427,7 @@ static UniValue preciousblock(const JSONRPCRequest& request)
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as precious"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("preciousblock", "\"blockhash\"")
+ HelpExampleRpc("preciousblock", "\"blockhash\"")
@@ -1486,7 +1449,7 @@ static UniValue preciousblock(const JSONRPCRequest& request)
PreciousBlock(state, Params(), pblockindex);
if (!state.IsValid()) {
- throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
}
return NullUniValue;
@@ -1499,7 +1462,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as invalid"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("invalidateblock", "\"blockhash\"")
+ HelpExampleRpc("invalidateblock", "\"blockhash\"")
@@ -1524,7 +1487,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
}
if (!state.IsValid()) {
- throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
}
return NullUniValue;
@@ -1538,7 +1501,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to reconsider"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("reconsiderblock", "\"blockhash\"")
+ HelpExampleRpc("reconsiderblock", "\"blockhash\"")
@@ -1561,7 +1524,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
ActivateBestChain(state, Params());
if (!state.IsValid()) {
- throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
}
return NullUniValue;
@@ -1576,17 +1539,17 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
{"blockhash", RPCArg::Type::STR_HEX, /* default */ "chain tip", "The hash of the block that ends the window."},
},
RPCResult{
- "{\n"
- " \"time\": xxxxx, (numeric) The timestamp for the final block in the window, expressed in " + UNIX_EPOCH_TIME + ".\n"
- " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
- " \"window_final_block_hash\": \"...\", (string) The hash of the final block in the window.\n"
- " \"window_final_block_height\": xxxxx, (numeric) The height of the final block in the window.\n"
- " \"window_block_count\": xxxxx, (numeric) Size of the window in number of blocks.\n"
- " \"window_tx_count\": xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n"
- " \"window_interval\": xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n"
- " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM_TIME, "time", "The timestamp for the final block in the window, expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM, "txcount", "The total number of transactions in the chain up to that point"},
+ {RPCResult::Type::STR_HEX, "window_final_block_hash", "The hash of the final block in the window"},
+ {RPCResult::Type::NUM, "window_final_block_height", "The height of the final block in the window."},
+ {RPCResult::Type::NUM, "window_block_count", "Size of the window in number of blocks"},
+ {RPCResult::Type::NUM, "window_tx_count", "The number of transactions in the window. Only returned if \"window_block_count\" is > 0"},
+ {RPCResult::Type::NUM, "window_interval", "The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0"},
+ {RPCResult::Type::NUM, "txrate", "The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0"},
+ }},
RPCExamples{
HelpExampleCli("getchaintxstats", "")
+ HelpExampleRpc("getchaintxstats", "2016")
@@ -1715,47 +1678,50 @@ static UniValue getblockstats(const JSONRPCRequest& request)
"stats"},
},
RPCResult{
- "{ (json object)\n"
- " \"avgfee\": xxxxx, (numeric) Average fee in the block\n"
- " \"avgfeerate\": xxxxx, (numeric) Average feerate (in satoshis per virtual byte)\n"
- " \"avgtxsize\": xxxxx, (numeric) Average transaction size\n"
- " \"blockhash\": xxxxx, (string) The block hash (to check for potential reorgs)\n"
- " \"feerate_percentiles\": [ (array of numeric) Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)\n"
- " \"10th_percentile_feerate\", (numeric) The 10th percentile feerate\n"
- " \"25th_percentile_feerate\", (numeric) The 25th percentile feerate\n"
- " \"50th_percentile_feerate\", (numeric) The 50th percentile feerate\n"
- " \"75th_percentile_feerate\", (numeric) The 75th percentile feerate\n"
- " \"90th_percentile_feerate\", (numeric) The 90th percentile feerate\n"
- " ],\n"
- " \"height\": xxxxx, (numeric) The height of the block\n"
- " \"ins\": xxxxx, (numeric) The number of inputs (excluding coinbase)\n"
- " \"maxfee\": xxxxx, (numeric) Maximum fee in the block\n"
- " \"maxfeerate\": xxxxx, (numeric) Maximum feerate (in satoshis per virtual byte)\n"
- " \"maxtxsize\": xxxxx, (numeric) Maximum transaction size\n"
- " \"medianfee\": xxxxx, (numeric) Truncated median fee in the block\n"
- " \"mediantime\": xxxxx, (numeric) The block median time past\n"
- " \"mediantxsize\": xxxxx, (numeric) Truncated median transaction size\n"
- " \"minfee\": xxxxx, (numeric) Minimum fee in the block\n"
- " \"minfeerate\": xxxxx, (numeric) Minimum feerate (in satoshis per virtual byte)\n"
- " \"mintxsize\": xxxxx, (numeric) Minimum transaction size\n"
- " \"outs\": xxxxx, (numeric) The number of outputs\n"
- " \"subsidy\": xxxxx, (numeric) The block subsidy\n"
- " \"swtotal_size\": xxxxx, (numeric) Total size of all segwit transactions\n"
- " \"swtotal_weight\": xxxxx, (numeric) Total weight of all segwit transactions divided by segwit scale factor (4)\n"
- " \"swtxs\": xxxxx, (numeric) The number of segwit transactions\n"
- " \"time\": xxxxx, (numeric) The block time\n"
- " \"total_out\": xxxxx, (numeric) Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])\n"
- " \"total_size\": xxxxx, (numeric) Total size of all non-coinbase transactions\n"
- " \"total_weight\": xxxxx, (numeric) Total weight of all non-coinbase transactions divided by segwit scale factor (4)\n"
- " \"totalfee\": xxxxx, (numeric) The fee total\n"
- " \"txs\": xxxxx, (numeric) The number of transactions (excluding coinbase)\n"
- " \"utxo_increase\": xxxxx, (numeric) The increase/decrease in the number of unspent outputs\n"
- " \"utxo_size_inc\": xxxxx, (numeric) The increase/decrease in size for the utxo index (not discounting op_return and similar)\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "avgfee", "Average fee in the block"},
+ {RPCResult::Type::NUM, "avgfeerate", "Average feerate (in satoshis per virtual byte)"},
+ {RPCResult::Type::NUM, "avgtxsize", "Average transaction size"},
+ {RPCResult::Type::STR_HEX, "blockhash", "The block hash (to check for potential reorgs)"},
+ {RPCResult::Type::ARR_FIXED, "feerate_percentiles", "Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)",
+ {
+ {RPCResult::Type::NUM, "10th_percentile_feerate", "The 10th percentile feerate"},
+ {RPCResult::Type::NUM, "25th_percentile_feerate", "The 25th percentile feerate"},
+ {RPCResult::Type::NUM, "50th_percentile_feerate", "The 50th percentile feerate"},
+ {RPCResult::Type::NUM, "75th_percentile_feerate", "The 75th percentile feerate"},
+ {RPCResult::Type::NUM, "90th_percentile_feerate", "The 90th percentile feerate"},
+ }},
+ {RPCResult::Type::NUM, "height", "The height of the block"},
+ {RPCResult::Type::NUM, "ins", "The number of inputs (excluding coinbase)"},
+ {RPCResult::Type::NUM, "maxfee", "Maximum fee in the block"},
+ {RPCResult::Type::NUM, "maxfeerate", "Maximum feerate (in satoshis per virtual byte)"},
+ {RPCResult::Type::NUM, "maxtxsize", "Maximum transaction size"},
+ {RPCResult::Type::NUM, "medianfee", "Truncated median fee in the block"},
+ {RPCResult::Type::NUM, "mediantime", "The block median time past"},
+ {RPCResult::Type::NUM, "mediantxsize", "Truncated median transaction size"},
+ {RPCResult::Type::NUM, "minfee", "Minimum fee in the block"},
+ {RPCResult::Type::NUM, "minfeerate", "Minimum feerate (in satoshis per virtual byte)"},
+ {RPCResult::Type::NUM, "mintxsize", "Minimum transaction size"},
+ {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, "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, "totalfee", "The fee total"},
+ {RPCResult::Type::NUM, "txs", "The number of transactions (excluding coinbase)"},
+ {RPCResult::Type::NUM, "utxo_increase", "The increase/decrease in the number of unspent outputs"},
+ {RPCResult::Type::NUM, "utxo_size_inc", "The increase/decrease in size for the utxo index (not discounting op_return and similar)"},
+ }},
RPCExamples{
- HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
- + HelpExampleRpc("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
+ HelpExampleCli("getblockstats", R"('"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"' '["minfeerate","avgfeerate"]')") +
+ HelpExampleCli("getblockstats", R"(1000 '["minfeerate","avgfeerate"]')") +
+ HelpExampleRpc("getblockstats", R"("00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09", ["minfeerate","avgfeerate"])") +
+ HelpExampleRpc("getblockstats", R"(1000, ["minfeerate","avgfeerate"])")
},
}.Check(request);
@@ -1961,7 +1927,7 @@ static UniValue savemempool(const JSONRPCRequest& request)
RPCHelpMan{"savemempool",
"\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("savemempool", "")
+ HelpExampleRpc("savemempool", "")
@@ -2075,24 +2041,26 @@ UniValue scantxoutset(const JSONRPCRequest& request)
"[scanobjects,...]"},
},
RPCResult{
- "{\n"
- " \"success\": true|false, (boolean) Whether the scan was completed\n"
- " \"txouts\": n, (numeric) The number of unspent transaction outputs scanned\n"
- " \"height\": n, (numeric) The current block height (index)\n"
- " \"bestblock\": \"hex\", (string) The hash of the block at the tip of the chain\n"
- " \"unspents\": [\n"
- " {\n"
- " \"txid\": \"hash\", (string) The transaction id\n"
- " \"vout\": n, (numeric) The vout value\n"
- " \"scriptPubKey\": \"script\", (string) The script key\n"
- " \"desc\": \"descriptor\", (string) A specialized descriptor for the matched scriptPubKey\n"
- " \"amount\": x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " of the unspent output\n"
- " \"height\": n, (numeric) Height of the unspent transaction output\n"
- " }\n"
- " ,...],\n"
- " \"total_amount\": x.xxx, (numeric) The total amount of all found unspent outputs in " + CURRENCY_UNIT + "\n"
- "]\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "success", "Whether the scan was completed"},
+ {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs scanned"},
+ {RPCResult::Type::NUM, "height", "The current block height (index)"},
+ {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"},
+ {RPCResult::Type::ARR, "unspents", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
+ {RPCResult::Type::NUM, "vout", "The vout value"},
+ {RPCResult::Type::STR_HEX, "scriptPubKey", "The script key"},
+ {RPCResult::Type::STR, "desc", "A specialized descriptor for the matched scriptPubKey"},
+ {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the unspent output"},
+ {RPCResult::Type::NUM, "height", "Height of the unspent transaction output"},
+ }},
+ }},
+ {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of all found unspent outputs in " + CURRENCY_UNIT},
+ }},
RPCExamples{""},
}.Check(request);
@@ -2198,13 +2166,14 @@ static UniValue getblockfilter(const JSONRPCRequest& request)
{"filtertype", RPCArg::Type::STR, /*default*/ "basic", "The type name of the filter"},
},
RPCResult{
- "{\n"
- " \"filter\" : (string) the hex-encoded filter data\n"
- " \"header\" : (string) the hex-encoded filter header\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "filter", "the hex-encoded filter data"},
+ {RPCResult::Type::STR_HEX, "header", "the hex-encoded filter header"},
+ }},
RPCExamples{
- HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"")
+ HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"") +
+ HelpExampleRpc("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\", \"basic\"")
}
}.Check(request);
@@ -2273,8 +2242,7 @@ UniValue dumptxoutset(const JSONRPCRequest& request)
{
RPCHelpMan{
"dumptxoutset",
- "\nWrite the serialized UTXO set to disk.\n"
- "Incidentally flushes the latest coinsdb (leveldb) to disk.\n",
+ "\nWrite the serialized UTXO set to disk.\n",
{
{"path",
RPCArg::Type::STR,
@@ -2283,12 +2251,13 @@ UniValue dumptxoutset(const JSONRPCRequest& request)
"path to the output file. If relative, will be prefixed by datadir."},
},
RPCResult{
- "{\n"
- " \"coins_written\": n, (numeric) the number of coins written in the snapshot\n"
- " \"base_hash\": \"...\", (string) the hash of the base of the snapshot\n"
- " \"base_height\": n, (string) the height of the base of the snapshot\n"
- " \"path\": \"...\" (string) the absolute path that the snapshot was written to\n"
- "]\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "coins_written", "the number of coins written in the snapshot"},
+ {RPCResult::Type::STR_HEX, "base_hash", "the hash of the base of the snapshot"},
+ {RPCResult::Type::NUM, "base_height", "the height of the base of the snapshot"},
+ {RPCResult::Type::STR, "path", "the absolute path that the snapshot was written to"},
+ }
},
RPCExamples{
HelpExampleCli("dumptxoutset", "utxo.dat")
@@ -2371,6 +2340,8 @@ UniValue dumptxoutset(const JSONRPCRequest& request)
return result;
}
+void RegisterBlockchainRPCCommands(CRPCTable &t)
+{
// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
@@ -2411,8 +2382,6 @@ static const CRPCCommand commands[] =
};
// clang-format on
-void RegisterBlockchainRPCCommands(CRPCTable &t)
-{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 2eaa3427eb..3045a74d7a 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -27,11 +27,13 @@ public:
static const CRPCConvertParam vRPCConvertParams[] =
{
{ "setmocktime", 0, "timestamp" },
+ { "mockscheduler", 0, "delta_time" },
{ "utxoupdatepsbt", 1, "descriptors" },
{ "generatetoaddress", 0, "nblocks" },
{ "generatetoaddress", 2, "maxtries" },
{ "generatetodescriptor", 0, "num_blocks" },
{ "generatetodescriptor", 2, "maxtries" },
+ { "generateblock", 1, "transactions" },
{ "getnetworkhashps", 0, "nblocks" },
{ "getnetworkhashps", 1, "height" },
{ "sendtoaddress", 1, "amount" },
@@ -96,10 +98,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "signrawtransactionwithkey", 1, "privkeys" },
{ "signrawtransactionwithkey", 2, "prevtxs" },
{ "signrawtransactionwithwallet", 1, "prevtxs" },
- { "sendrawtransaction", 1, "allowhighfees" },
{ "sendrawtransaction", 1, "maxfeerate" },
{ "testmempoolaccept", 0, "rawtxs" },
- { "testmempoolaccept", 1, "allowhighfees" },
{ "testmempoolaccept", 1, "maxfeerate" },
{ "combinerawtransaction", 0, "txs" },
{ "fundrawtransaction", 1, "options" },
@@ -131,6 +131,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "importpubkey", 2, "rescan" },
{ "importmulti", 0, "requests" },
{ "importmulti", 1, "options" },
+ { "importdescriptors", 0, "requests" },
{ "verifychain", 0, "checklevel" },
{ "verifychain", 1, "nblocks" },
{ "getblockstats", 0, "hash_or_height" },
@@ -153,6 +154,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "logging", 0, "include" },
{ "logging", 1, "exclude" },
{ "disconnectnode", 1, "nodeid" },
+ { "upgradewallet", 0, "version" },
// Echo with conversion (For testing only)
{ "echojson", 0, "arg0" },
{ "echojson", 1, "arg1" },
@@ -169,6 +171,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "createwallet", 1, "disable_private_keys"},
{ "createwallet", 2, "blank"},
{ "createwallet", 4, "avoid_reuse"},
+ { "createwallet", 5, "descriptors"},
{ "getnodeaddresses", 0, "count"},
{ "stop", 0, "wait" },
};
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index e5994b172b..05d3fd6afb 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -27,8 +27,8 @@
#include <univalue.h>
#include <util/fees.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <util/system.h>
-#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
#include <versionbitsinfo.h>
@@ -90,8 +90,7 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request)
{"height", RPCArg::Type::NUM, /* default */ "-1", "To estimate at the time of the given height."},
},
RPCResult{
- "x (numeric) Hashes per second estimated\n"
- },
+ RPCResult::Type::NUM, "", "Hashes per second estimated"},
RPCExamples{
HelpExampleCli("getnetworkhashps", "")
+ HelpExampleRpc("getnetworkhashps", "")
@@ -102,6 +101,36 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request)
return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1);
}
+static bool GenerateBlock(CBlock& block, uint64_t& max_tries, unsigned int& extra_nonce, uint256& block_hash)
+{
+ block_hash.SetNull();
+
+ {
+ LOCK(cs_main);
+ IncrementExtraNonce(&block, ::ChainActive().Tip(), extra_nonce);
+ }
+
+ CChainParams chainparams(Params());
+
+ while (max_tries > 0 && block.nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus()) && !ShutdownRequested()) {
+ ++block.nNonce;
+ --max_tries;
+ }
+ if (max_tries == 0 || ShutdownRequested()) {
+ return false;
+ }
+ if (block.nNonce == std::numeric_limits<uint32_t>::max()) {
+ return true;
+ }
+
+ std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
+ if (!ProcessNewBlock(chainparams, shared_pblock, true, nullptr))
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
+
+ block_hash = block.GetHash();
+ return true;
+}
+
static UniValue generateBlocks(const CTxMemPool& mempool, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
{
int nHeightEnd = 0;
@@ -120,29 +149,54 @@ static UniValue generateBlocks(const CTxMemPool& mempool, const CScript& coinbas
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
- {
- LOCK(cs_main);
- IncrementExtraNonce(pblock, ::ChainActive().Tip(), nExtraNonce);
- }
- while (nMaxTries > 0 && pblock->nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus()) && !ShutdownRequested()) {
- ++pblock->nNonce;
- --nMaxTries;
- }
- if (nMaxTries == 0 || ShutdownRequested()) {
+
+ uint256 block_hash;
+ if (!GenerateBlock(*pblock, nMaxTries, nExtraNonce, block_hash)) {
break;
}
- if (pblock->nNonce == std::numeric_limits<uint32_t>::max()) {
- continue;
+
+ if (!block_hash.IsNull()) {
+ ++nHeight;
+ blockHashes.push_back(block_hash.GetHex());
}
- std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
- if (!ProcessNewBlock(Params(), shared_pblock, true, nullptr))
- throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
- ++nHeight;
- blockHashes.push_back(pblock->GetHash().GetHex());
}
return blockHashes;
}
+static bool getScriptFromDescriptor(const std::string& descriptor, CScript& script, std::string& error)
+{
+ FlatSigningProvider key_provider;
+ const auto desc = Parse(descriptor, key_provider, error, /* require_checksum = */ false);
+ if (desc) {
+ if (desc->IsRange()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptor not accepted. Maybe pass through deriveaddresses first?");
+ }
+
+ FlatSigningProvider provider;
+ std::vector<CScript> scripts;
+ if (!desc->Expand(0, key_provider, scripts, provider)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
+ }
+
+ // Combo desriptors can have 2 or 4 scripts, so we can't just check scripts.size() == 1
+ CHECK_NONFATAL(scripts.size() > 0 && scripts.size() <= 4);
+
+ if (scripts.size() == 1) {
+ script = scripts.at(0);
+ } else if (scripts.size() == 4) {
+ // For uncompressed keys, take the 3rd script, since it is p2wpkh
+ script = scripts.at(2);
+ } else {
+ // Else take the 2nd script, since it is p2pkh
+ script = scripts.at(1);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
static UniValue generatetodescriptor(const JSONRPCRequest& request)
{
RPCHelpMan{
@@ -154,7 +208,11 @@ static UniValue generatetodescriptor(const JSONRPCRequest& request)
{"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."},
},
RPCResult{
- "[ blockhashes ] (array) hashes of blocks generated\n"},
+ RPCResult::Type::ARR, "", "hashes of blocks generated",
+ {
+ {RPCResult::Type::STR_HEX, "", "blockhash"},
+ }
+ },
RPCExamples{
"\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
}
@@ -163,27 +221,15 @@ static UniValue generatetodescriptor(const JSONRPCRequest& request)
const int num_blocks{request.params[0].get_int()};
const int64_t max_tries{request.params[2].isNull() ? 1000000 : request.params[2].get_int()};
- FlatSigningProvider key_provider;
+ CScript coinbase_script;
std::string error;
- const auto desc = Parse(request.params[1].get_str(), key_provider, error, /* require_checksum = */ false);
- if (!desc) {
+ if (!getScriptFromDescriptor(request.params[1].get_str(), coinbase_script, error)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
}
- if (desc->IsRange()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptor not accepted. Maybe pass through deriveaddresses first?");
- }
-
- FlatSigningProvider provider;
- std::vector<CScript> coinbase_script;
- if (!desc->Expand(0, key_provider, coinbase_script, provider)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
- }
const CTxMemPool& mempool = EnsureMemPool();
- CHECK_NONFATAL(coinbase_script.size() == 1);
-
- return generateBlocks(mempool, coinbase_script.at(0), num_blocks, max_tries);
+ return generateBlocks(mempool, coinbase_script, num_blocks, max_tries);
}
static UniValue generatetoaddress(const JSONRPCRequest& request)
@@ -196,8 +242,10 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
{"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."},
},
RPCResult{
- "[ blockhashes ] (array) hashes of blocks generated\n"
- },
+ RPCResult::Type::ARR, "", "hashes of blocks generated",
+ {
+ {RPCResult::Type::STR_HEX, "", "blockhash"},
+ }},
RPCExamples{
"\nGenerate 11 blocks to myaddress\n"
+ HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
@@ -224,23 +272,130 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
return generateBlocks(mempool, coinbase_script, nGenerate, nMaxTries);
}
+static UniValue generateblock(const JSONRPCRequest& request)
+{
+ RPCHelpMan{"generateblock",
+ "\nMine a block with a set of ordered transactions immediately to a specified address or descriptor (before the RPC call returns)\n",
+ {
+ {"output", RPCArg::Type::STR, RPCArg::Optional::NO, "The address or descriptor to send the newly generated bitcoin to."},
+ {"transactions", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings which are either txids or raw transactions.\n"
+ "Txids must reference transactions currently in the mempool.\n"
+ "All transactions must be valid and in valid order, otherwise the block will be rejected.",
+ {
+ {"rawtx/txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
+ },
+ },
+ },
+ RPCResult{
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "hash of generated block"},
+ }
+ },
+ RPCExamples{
+ "\nGenerate a block to myaddress, with txs rawtx and mempool_txid\n"
+ + HelpExampleCli("generateblock", R"("myaddress" '["rawtx", "mempool_txid"]')")
+ },
+ }.Check(request);
+
+ const auto address_or_descriptor = request.params[0].get_str();
+ CScript coinbase_script;
+ std::string error;
+
+ if (!getScriptFromDescriptor(address_or_descriptor, coinbase_script, error)) {
+ const auto destination = DecodeDestination(address_or_descriptor);
+ if (!IsValidDestination(destination)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address or descriptor");
+ }
+
+ coinbase_script = GetScriptForDestination(destination);
+ }
+
+ const CTxMemPool& mempool = EnsureMemPool();
+
+ std::vector<CTransactionRef> txs;
+ const auto raw_txs_or_txids = request.params[1].get_array();
+ for (size_t i = 0; i < raw_txs_or_txids.size(); i++) {
+ const auto str(raw_txs_or_txids[i].get_str());
+
+ uint256 hash;
+ CMutableTransaction mtx;
+ if (ParseHashStr(str, hash)) {
+
+ const auto tx = mempool.get(hash);
+ if (!tx) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Transaction %s not in mempool.", str));
+ }
+
+ txs.emplace_back(tx);
+
+ } else if (DecodeHexTx(mtx, str)) {
+ txs.push_back(MakeTransactionRef(std::move(mtx)));
+
+ } else {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("Transaction decode failed for %s", str));
+ }
+ }
+
+ CChainParams chainparams(Params());
+ CBlock block;
+
+ {
+ LOCK(cs_main);
+
+ CTxMemPool empty_mempool;
+ std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler(empty_mempool, chainparams).CreateNewBlock(coinbase_script));
+ if (!blocktemplate) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
+ }
+ block = blocktemplate->block;
+ }
+
+ CHECK_NONFATAL(block.vtx.size() == 1);
+
+ // Add transactions
+ block.vtx.insert(block.vtx.end(), txs.begin(), txs.end());
+ RegenerateCommitments(block);
+
+ {
+ LOCK(cs_main);
+
+ BlockValidationState state;
+ if (!TestBlockValidity(state, chainparams, block, LookupBlockIndex(block.hashPrevBlock), false, false)) {
+ throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString()));
+ }
+ }
+
+ uint256 block_hash;
+ uint64_t max_tries{1000000};
+ unsigned int extra_nonce{0};
+
+ if (!GenerateBlock(block, max_tries, extra_nonce, block_hash) || block_hash.IsNull()) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block.");
+ }
+
+ UniValue obj(UniValue::VOBJ);
+ obj.pushKV("hash", block_hash.GetHex());
+ return obj;
+}
+
static UniValue getmininginfo(const JSONRPCRequest& request)
{
RPCHelpMan{"getmininginfo",
"\nReturns a json object containing mining-related information.",
{},
RPCResult{
- "{\n"
- " \"blocks\": nnn, (numeric) The current block\n"
- " \"currentblockweight\": nnn, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled)\n"
- " \"currentblocktx\": nnn, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)\n"
- " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
- " \"networkhashps\": nnn, (numeric) The network hashes per second\n"
- " \"pooledtx\": n (numeric) The size of the mempool\n"
- " \"chain\": \"xxxx\", (string) current network name (main, test, regtest)\n"
- " \"warnings\": \"...\" (string) any network and blockchain warnings\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "blocks", "The current block"},
+ {RPCResult::Type::NUM, "currentblockweight", /* optional */ true, "The block weight of the last assembled block (only present if a block was ever assembled)"},
+ {RPCResult::Type::NUM, "currentblocktx", /* optional */ true, "The number of block transactions of the last assembled block (only present if a block was ever assembled)"},
+ {RPCResult::Type::NUM, "difficulty", "The current difficulty"},
+ {RPCResult::Type::NUM, "networkhashps", "The network hashes per second"},
+ {RPCResult::Type::NUM, "pooledtx", "The size of the mempool"},
+ {RPCResult::Type::STR, "chain", "current network name (main, test, regtest)"},
+ {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"},
+ }},
RPCExamples{
HelpExampleCli("getmininginfo", "")
+ HelpExampleRpc("getmininginfo", "")
@@ -278,8 +433,7 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request)
" considers the transaction as it would have paid a higher (or lower) fee."},
},
RPCResult{
- "true (boolean) Returns true\n"
- },
+ RPCResult::Type::BOOL, "", "Returns true"},
RPCExamples{
HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
+ HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
@@ -307,7 +461,7 @@ static UniValue BIP22ValidationResult(const BlockValidationState& state)
return NullUniValue;
if (state.IsError())
- throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
if (state.IsInvalid())
{
std::string strRejectReason = state.GetRejectReason();
@@ -339,7 +493,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
" https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
" https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n",
{
- {"template_request", RPCArg::Type::OBJ, "{}", "A json object in the following spec",
+ {"template_request", RPCArg::Type::OBJ, "{}", "Format of the template",
{
{"mode", RPCArg::Type::STR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"},
{"capabilities", RPCArg::Type::ARR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "A list of strings",
@@ -356,48 +510,58 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
"\"template_request\""},
},
RPCResult{
- "{\n"
- " \"version\" : n, (numeric) The preferred block version\n"
- " \"rules\" : [ \"rulename\", ... ], (array of strings) specific block rules that are to be enforced\n"
- " \"vbavailable\" : { (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n"
- " \"rulename\" : bitnumber (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n"
- " ,...\n"
- " },\n"
- " \"vbrequired\" : n, (numeric) bit mask of versionbits the server requires set in submissions\n"
- " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n"
- " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
- " {\n"
- " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
- " \"txid\" : \"xxxx\", (string) transaction id encoded in little-endian hexadecimal\n"
- " \"hash\" : \"xxxx\", (string) hash encoded in little-endian hexadecimal (including witness data)\n"
- " \"depends\" : [ (array) array of numbers \n"
- " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
- " ,...\n"
- " ],\n"
- " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
- " \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n"
- " \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n"
- " }\n"
- " ,...\n"
- " ],\n"
- " \"coinbaseaux\" : { ... }, (json object) data that should be included in the coinbase's scriptSig content\n"
- " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)\n"
- " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n"
- " \"target\" : \"xxxx\", (string) The hash target\n"
- " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for the next block time, expressed in " + UNIX_EPOCH_TIME + "\n"
- " \"mutable\" : [ (array of string) list of ways the block template may be changed \n"
- " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
- " ,...\n"
- " ],\n"
- " \"noncerange\" : \"00000000ffffffff\",(string) A range of valid nonces\n"
- " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n"
- " \"sizelimit\" : n, (numeric) limit of block size\n"
- " \"weightlimit\" : n, (numeric) limit of block weight\n"
- " \"curtime\" : ttt, (numeric) current timestamp in " + UNIX_EPOCH_TIME + "\n"
- " \"bits\" : \"xxxxxxxx\", (string) compressed target of next block\n"
- " \"height\" : n (numeric) The height of the next block\n"
- "}\n"
- },
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "version", "The preferred block version"},
+ {RPCResult::Type::ARR, "rules", "specific block rules that are to be enforced",
+ {
+ {RPCResult::Type::STR, "", "rulename"},
+ }},
+ {RPCResult::Type::OBJ_DYN, "vbavailable", "set of pending, supported versionbit (BIP 9) softfork deployments",
+ {
+ {RPCResult::Type::NUM, "rulename", "identifies the bit number as indicating acceptance and readiness for the named softfork rule"},
+ }},
+ {RPCResult::Type::NUM, "vbrequired", "bit mask of versionbits the server requires set in submissions"},
+ {RPCResult::Type::STR, "previousblockhash", "The hash of current highest block"},
+ {RPCResult::Type::ARR, "", "contents of non-coinbase transactions that should be included in the next block",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "data", "transaction data encoded in hexadecimal (byte-for-byte)"},
+ {RPCResult::Type::STR_HEX, "txid", "transaction id encoded in little-endian hexadecimal"},
+ {RPCResult::Type::STR_HEX, "hash", "hash encoded in little-endian hexadecimal (including witness data)"},
+ {RPCResult::Type::ARR, "depends", "array of numbers",
+ {
+ {RPCResult::Type::NUM, "", "transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is"},
+ }},
+ {RPCResult::Type::NUM, "fee", "difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one"},
+ {RPCResult::Type::NUM, "sigops", "total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero"},
+ {RPCResult::Type::NUM, "weight", "total transaction weight, as counted for purposes of block limits"},
+ }},
+ }},
+ {RPCResult::Type::OBJ, "coinbaseaux", "data that should be included in the coinbase's scriptSig content",
+ {
+ {RPCResult::Type::ELISION, "", ""},
+ }},
+ {RPCResult::Type::NUM, "coinbasevalue", "maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)"},
+ {RPCResult::Type::OBJ, "coinbasetxn", "information for coinbase transaction",
+ {
+ {RPCResult::Type::ELISION, "", ""},
+ }},
+ {RPCResult::Type::STR, "target", "The hash target"},
+ {RPCResult::Type::NUM_TIME, "mintime", "The minimum timestamp appropriate for the next block time, expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::ARR, "mutable", "list of ways the block template may be changed",
+ {
+ {RPCResult::Type::STR, "value", "A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'"},
+ }},
+ {RPCResult::Type::STR_HEX, "noncerange", "A range of valid nonces"},
+ {RPCResult::Type::NUM, "sigoplimit", "limit of sigops in blocks"},
+ {RPCResult::Type::NUM, "sizelimit", "limit of block size"},
+ {RPCResult::Type::NUM, "weightlimit", "limit of block weight"},
+ {RPCResult::Type::NUM_TIME, "curtime", "current timestamp in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::STR, "bits", "compressed target of next block"},
+ {RPCResult::Type::NUM, "height", "The height of the next block"},
+ }},
RPCExamples{
HelpExampleCli("getblocktemplate", "'{\"rules\": [\"segwit\"]}'")
+ HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}")
@@ -681,7 +845,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
result.pushKV("transactions", transactions);
result.pushKV("coinbaseaux", aux);
result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue);
- result.pushKV("longpollid", ::ChainActive().Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast));
+ result.pushKV("longpollid", ::ChainActive().Tip()->GetBlockHash().GetHex() + ToString(nTransactionsUpdatedLast));
result.pushKV("target", hashTarget.GetHex());
result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
result.pushKV("mutable", aMutable);
@@ -738,7 +902,7 @@ static UniValue submitblock(const JSONRPCRequest& request)
{"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block data to submit"},
{"dummy", RPCArg::Type::STR, /* default */ "ignored", "dummy value, for compatibility with BIP22. This value is ignored."},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", "Returns JSON Null when valid, a string according to BIP22 otherwise"},
RPCExamples{
HelpExampleCli("submitblock", "\"mydata\"")
+ HelpExampleRpc("submitblock", "\"mydata\"")
@@ -800,8 +964,7 @@ static UniValue submitheader(const JSONRPCRequest& request)
{"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"},
},
RPCResult{
- "None"
- },
+ RPCResult::Type::NONE, "", "None"},
RPCExamples{
HelpExampleCli("submitheader", "\"aabbcc\"") +
HelpExampleRpc("submitheader", "\"aabbcc\"")
@@ -823,7 +986,7 @@ static UniValue submitheader(const JSONRPCRequest& request)
ProcessNewBlockHeaders({h}, state, Params());
if (state.IsValid()) return NullUniValue;
if (state.IsError()) {
- throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
}
throw JSONRPCError(RPC_VERIFY_ERROR, state.GetRejectReason());
}
@@ -848,17 +1011,19 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request)
" \"CONSERVATIVE\""},
},
RPCResult{
- "{\n"
- " \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n"
- " \"errors\": [ str... ] (json array of strings, optional) Errors encountered during processing\n"
- " \"blocks\" : n (numeric) block number where estimate was found\n"
- "}\n"
- "\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "feerate", /* optional */ true, "estimate fee rate in " + CURRENCY_UNIT + "/kB (only present if no errors were encountered)"},
+ {RPCResult::Type::ARR, "errors", "Errors encountered during processing",
+ {
+ {RPCResult::Type::STR, "", "error"},
+ }},
+ {RPCResult::Type::NUM, "blocks", "block number where estimate was found\n"
"The request target will be clamped between 2 and the highest target\n"
"fee estimation is able to return based on how long it has been running.\n"
"An error is returned if not enough transactions and blocks\n"
- "have been observed to make an estimate for any number of blocks.\n"
- },
+ "have been observed to make an estimate for any number of blocks."},
+ }},
RPCExamples{
HelpExampleCli("estimatesmartfee", "6")
},
@@ -908,28 +1073,40 @@ static UniValue estimaterawfee(const JSONRPCRequest& request)
" lower buckets."},
},
RPCResult{
- "{\n"
- " \"short\" : { (json object, optional) estimate for short time horizon\n"
- " \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n"
- " \"decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n"
- " \"scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n"
- " \"pass\" : { (json object, optional) information about the lowest range of feerates to succeed in meeting the threshold\n"
- " \"startrange\" : x.x, (numeric) start of feerate range\n"
- " \"endrange\" : x.x, (numeric) end of feerate range\n"
- " \"withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n"
- " \"totalconfirmed\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed at any point\n"
- " \"inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n"
- " \"leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n"
- " },\n"
- " \"fail\" : { ... }, (json object, optional) information about the highest range of feerates to fail to meet the threshold\n"
- " \"errors\": [ str... ] (json array of strings, optional) Errors encountered during processing\n"
- " },\n"
- " \"medium\" : { ... }, (json object, optional) estimate for medium time horizon\n"
- " \"long\" : { ... } (json object) estimate for long time horizon\n"
- "}\n"
- "\n"
- "Results are returned for any horizon which tracks blocks up to the confirmation target.\n"
- },
+ RPCResult::Type::OBJ, "", "Results are returned for any horizon which tracks blocks up to the confirmation target",
+ {
+ {RPCResult::Type::OBJ, "short", /* optional */ true, "estimate for short time horizon",
+ {
+ {RPCResult::Type::NUM, "feerate", /* optional */ true, "estimate fee rate in " + CURRENCY_UNIT + "/kB"},
+ {RPCResult::Type::NUM, "decay", "exponential decay (per block) for historical moving average of confirmation data"},
+ {RPCResult::Type::NUM, "scale", "The resolution of confirmation targets at this time horizon"},
+ {RPCResult::Type::OBJ, "pass", /* optional */ true, "information about the lowest range of feerates to succeed in meeting the threshold",
+ {
+ {RPCResult::Type::NUM, "startrange", "start of feerate range"},
+ {RPCResult::Type::NUM, "endrange", "end of feerate range"},
+ {RPCResult::Type::NUM, "withintarget", "number of txs over history horizon in the feerate range that were confirmed within target"},
+ {RPCResult::Type::NUM, "totalconfirmed", "number of txs over history horizon in the feerate range that were confirmed at any point"},
+ {RPCResult::Type::NUM, "inmempool", "current number of txs in mempool in the feerate range unconfirmed for at least target blocks"},
+ {RPCResult::Type::NUM, "leftmempool", "number of txs over history horizon in the feerate range that left mempool unconfirmed after target"},
+ }},
+ {RPCResult::Type::OBJ, "fail", /* optional */ true, "information about the highest range of feerates to fail to meet the threshold",
+ {
+ {RPCResult::Type::ELISION, "", ""},
+ }},
+ {RPCResult::Type::ARR, "errors", /* optional */ true, "Errors encountered during processing",
+ {
+ {RPCResult::Type::STR, "error", ""},
+ }},
+ }},
+ {RPCResult::Type::OBJ, "medium", /* optional */ true, "estimate for medium time horizon",
+ {
+ {RPCResult::Type::ELISION, "", ""},
+ }},
+ {RPCResult::Type::OBJ, "long", /* optional */ true, "estimate for long time horizon",
+ {
+ {RPCResult::Type::ELISION, "", ""},
+ }},
+ }},
RPCExamples{
HelpExampleCli("estimaterawfee", "6 0.9")
},
@@ -995,6 +1172,8 @@ static UniValue estimaterawfee(const JSONRPCRequest& request)
return result;
}
+void RegisterMiningRPCCommands(CRPCTable &t)
+{
// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
@@ -1009,6 +1188,7 @@ static const CRPCCommand commands[] =
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
{ "generating", "generatetodescriptor", &generatetodescriptor, {"num_blocks","descriptor","maxtries"} },
+ { "generating", "generateblock", &generateblock, {"output","transactions"} },
{ "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
@@ -1016,8 +1196,6 @@ static const CRPCCommand commands[] =
};
// clang-format on
-void RegisterMiningRPCCommands(CRPCTable &t)
-{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 56bd33b0ec..f3c5fed858 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -1,19 +1,22 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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 <httpserver.h>
+#include <interfaces/chain.h>
#include <key_io.h>
+#include <node/context.h>
#include <outputtype.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <rpc/util.h>
+#include <scheduler.h>
#include <script/descriptor.h>
#include <util/check.h>
+#include <util/message.h> // For MessageSign(), MessageVerify()
#include <util/strencodings.h>
#include <util/system.h>
-#include <util/validation.h>
#include <stdint.h>
#include <tuple>
@@ -31,19 +34,20 @@ static UniValue validateaddress(const JSONRPCRequest& request)
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to validate"},
},
RPCResult{
- "{\n"
- " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
- " \"address\" : \"address\", (string) The bitcoin address validated\n"
- " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n"
- " \"isscript\" : true|false, (boolean) If the key is a script\n"
- " \"iswitness\" : true|false, (boolean) If the address is a witness address\n"
- " \"witness_version\" : version (numeric, optional) The version number of the witness program\n"
- " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "isvalid", "If the address is valid or not. If not, this is the only property returned."},
+ {RPCResult::Type::STR, "address", "The bitcoin address validated"},
+ {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address"},
+ {RPCResult::Type::BOOL, "isscript", "If the key is a script"},
+ {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address"},
+ {RPCResult::Type::NUM, "witness_version", /* optional */ true, "The version number of the witness program"},
+ {RPCResult::Type::STR_HEX, "witness_program", /* optional */ true, "The hex value of the witness program"},
+ }
},
RPCExamples{
- HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
- + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ HelpExampleCli("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
+ HelpExampleRpc("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"")
},
}.Check(request);
@@ -73,17 +77,19 @@ static UniValue createmultisig(const JSONRPCRequest& request)
"It returns a json object with the address and redeemScript.\n",
{
{"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys."},
- {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of hex-encoded public keys.",
+ {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The hex-encoded public keys.",
{
{"key", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The hex-encoded public key"},
}},
{"address_type", RPCArg::Type::STR, /* default */ "legacy", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
},
RPCResult{
- "{\n"
- " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
- " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "address", "The value of the new multisig address."},
+ {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script."},
+ {RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"},
+ }
},
RPCExamples{
"\nCreate a multisig address from 2 public keys\n"
@@ -119,9 +125,13 @@ static UniValue createmultisig(const JSONRPCRequest& request)
CScript inner;
const CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, keystore, inner);
+ // Make the descriptor
+ std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), keystore);
+
UniValue result(UniValue::VOBJ);
result.pushKV("address", EncodeDestination(dest));
result.pushKV("redeemScript", HexStr(inner.begin(), inner.end()));
+ result.pushKV("descriptor", descriptor->ToString());
return result;
}
@@ -134,13 +144,14 @@ UniValue getdescriptorinfo(const JSONRPCRequest& request)
{"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."},
},
RPCResult{
- "{\n"
- " \"descriptor\" : \"desc\", (string) The descriptor in canonical form, without private keys\n"
- " \"checksum\" : \"chksum\", (string) The checksum for the input descriptor\n"
- " \"isrange\" : true|false, (boolean) Whether the descriptor is ranged\n"
- " \"issolvable\" : true|false, (boolean) Whether the descriptor is solvable\n"
- " \"hasprivatekeys\" : true|false, (boolean) Whether the input descriptor contained at least one private key\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "descriptor", "The descriptor in canonical form, without private keys"},
+ {RPCResult::Type::STR, "checksum", "The checksum for the input descriptor"},
+ {RPCResult::Type::BOOL, "isrange", "Whether the descriptor is ranged"},
+ {RPCResult::Type::BOOL, "issolvable", "Whether the descriptor is solvable"},
+ {RPCResult::Type::BOOL, "hasprivatekeys", "Whether the input descriptor contained at least one private key"},
+ }
},
RPCExamples{
"Analyse a descriptor\n" +
@@ -182,7 +193,10 @@ UniValue deriveaddresses(const JSONRPCRequest& request)
{"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."},
},
RPCResult{
- "[ address ] (array) the derived addresses\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::STR, "address", "the derived addresses"},
+ }
},
RPCExamples{
"First three native segwit receive addresses\n" +
@@ -251,7 +265,7 @@ static UniValue verifymessage(const JSONRPCRequest& request)
{"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."},
},
RPCResult{
- "true|false (boolean) If the signature is verified or not.\n"
+ RPCResult::Type::BOOL, "", "If the signature is verified or not."
},
RPCExamples{
"\nUnlock the wallet for 30 seconds\n"
@@ -271,31 +285,21 @@ static UniValue verifymessage(const JSONRPCRequest& request)
std::string strSign = request.params[1].get_str();
std::string strMessage = request.params[2].get_str();
- CTxDestination destination = DecodeDestination(strAddress);
- if (!IsValidDestination(destination)) {
+ switch (MessageVerify(strAddress, strSign, strMessage)) {
+ case MessageVerificationResult::ERR_INVALID_ADDRESS:
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
- }
-
- const PKHash *pkhash = boost::get<PKHash>(&destination);
- if (!pkhash) {
+ case MessageVerificationResult::ERR_ADDRESS_NO_KEY:
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
- }
-
- bool fInvalid = false;
- std::vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
-
- if (fInvalid)
+ case MessageVerificationResult::ERR_MALFORMED_SIGNATURE:
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
-
- CHashWriter ss(SER_GETHASH, 0);
- ss << strMessageMagic;
- ss << strMessage;
-
- CPubKey pubkey;
- if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
+ case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED:
+ case MessageVerificationResult::ERR_NOT_SIGNED:
return false;
+ case MessageVerificationResult::OK:
+ return true;
+ }
- return (pubkey.GetID() == *pkhash);
+ return false;
}
static UniValue signmessagewithprivkey(const JSONRPCRequest& request)
@@ -307,7 +311,7 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request)
{"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
},
RPCResult{
- "\"signature\" (string) The signature of the message encoded in base 64\n"
+ RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
},
RPCExamples{
"\nCreate the signature\n"
@@ -327,15 +331,13 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
}
- CHashWriter ss(SER_GETHASH, 0);
- ss << strMessageMagic;
- ss << strMessage;
+ std::string signature;
- std::vector<unsigned char> vchSig;
- if (!key.SignCompact(ss.GetHash(), vchSig))
+ if (!MessageSign(key, strMessage, signature)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
+ }
- return EncodeBase64(vchSig.data(), vchSig.size());
+ return signature;
}
static UniValue setmocktime(const JSONRPCRequest& request)
@@ -346,12 +348,13 @@ static UniValue setmocktime(const JSONRPCRequest& request)
{"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, UNIX_EPOCH_TIME + "\n"
" Pass 0 to go back to using the system time."},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{""},
}.Check(request);
- if (!Params().MineBlocksOnDemand())
- throw std::runtime_error("setmocktime for regression testing (-regtest mode) only");
+ if (!Params().IsMockableChain()) {
+ throw std::runtime_error("setmocktime is for regression testing (-regtest mode) only");
+ }
// For now, don't change mocktime if we're in the middle of validation, as
// this could have an effect on mempool time-based eviction, as well as
@@ -361,7 +364,43 @@ static UniValue setmocktime(const JSONRPCRequest& request)
LOCK(cs_main);
RPCTypeCheck(request.params, {UniValue::VNUM});
- SetMockTime(request.params[0].get_int64());
+ int64_t time = request.params[0].get_int64();
+ SetMockTime(time);
+ if (g_rpc_node) {
+ for (const auto& chain_client : g_rpc_node->chain_clients) {
+ chain_client->setMockTime(time);
+ }
+ }
+
+ return NullUniValue;
+}
+
+static UniValue mockscheduler(const JSONRPCRequest& request)
+{
+ RPCHelpMan{"mockscheduler",
+ "\nBump the scheduler into the future (-regtest only)\n",
+ {
+ {"delta_time", RPCArg::Type::NUM, RPCArg::Optional::NO, "Number of seconds to forward the scheduler into the future." },
+ },
+ RPCResult{RPCResult::Type::NONE, "", ""},
+ RPCExamples{""},
+ }.Check(request);
+
+ if (!Params().IsMockableChain()) {
+ throw std::runtime_error("mockscheduler is for regression testing (-regtest mode) only");
+ }
+
+ // check params are valid values
+ RPCTypeCheck(request.params, {UniValue::VNUM});
+ int64_t delta_seconds = request.params[0].get_int64();
+ if ((delta_seconds <= 0) || (delta_seconds > 3600)) {
+ throw std::runtime_error("delta_time must be between 1 and 3600 seconds (1 hr)");
+ }
+
+ // protect against null pointer dereference
+ CHECK_NONFATAL(g_rpc_node);
+ CHECK_NONFATAL(g_rpc_node->scheduler);
+ g_rpc_node->scheduler->MockForward(std::chrono::seconds(delta_seconds));
return NullUniValue;
}
@@ -412,19 +451,21 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request)
},
{
RPCResult{"mode \"stats\"",
- "{\n"
- " \"locked\": { (json object) Information about locked memory manager\n"
- " \"used\": xxxxx, (numeric) Number of bytes used\n"
- " \"free\": xxxxx, (numeric) Number of bytes available in current arenas\n"
- " \"total\": xxxxxxx, (numeric) Total number of bytes managed\n"
- " \"locked\": xxxxxx, (numeric) Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk.\n"
- " \"chunks_used\": xxxxx, (numeric) Number allocated chunks\n"
- " \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
- " }\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ, "locked", "Information about locked memory manager",
+ {
+ {RPCResult::Type::NUM, "used", "Number of bytes used"},
+ {RPCResult::Type::NUM, "free", "Number of bytes available in current arenas"},
+ {RPCResult::Type::NUM, "total", "Total number of bytes managed"},
+ {RPCResult::Type::NUM, "locked", "Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk."},
+ {RPCResult::Type::NUM, "chunks_used", "Number allocated chunks"},
+ {RPCResult::Type::NUM, "chunks_free", "Number unused chunks"},
+ }},
+ }
},
RPCResult{"mode \"mallocinfo\"",
- "\"<malloc version=\"1\">...\"\n"
+ RPCResult::Type::STR, "", "\"<malloc version=\"1\">...\""
},
},
RPCExamples{
@@ -475,26 +516,26 @@ UniValue logging(const JSONRPCRequest& request)
"When called with arguments, adds or removes categories from debug logging and return the lists above.\n"
"The arguments are evaluated in order \"include\", \"exclude\".\n"
"If an item is both included and excluded, it will thus end up being excluded.\n"
- "The valid logging categories are: " + ListLogCategories() + "\n"
+ "The valid logging categories are: " + LogInstance().LogCategoriesString() + "\n"
"In addition, the following are available as category names with special meanings:\n"
" - \"all\", \"1\" : represent all logging categories.\n"
" - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n"
,
{
- {"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of categories to add debug logging",
+ {"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The categories to add to debug logging",
{
{"include_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
}},
- {"exclude", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of categories to remove debug logging",
+ {"exclude", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The categories to remove from debug logging",
{
{"exclude_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
}},
},
RPCResult{
- "{ (json object where keys are the logging categories, and values indicates its status\n"
- " \"category\": true|false, (bool) if being debug logged or not. false:inactive, true:active\n"
- " ...\n"
- "}\n"
+ RPCResult::Type::OBJ_DYN, "", "keys are the logging categories, and values indicates its status",
+ {
+ {RPCResult::Type::BOOL, "category", "if being debug logged or not. false:inactive, true:active"},
+ }
},
RPCExamples{
HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"")
@@ -527,8 +568,7 @@ UniValue logging(const JSONRPCRequest& request)
}
UniValue result(UniValue::VOBJ);
- std::vector<CLogCategoryActive> vLogCatActive = ListActiveLogCategories();
- for (const auto& logCatActive : vLogCatActive) {
+ for (const auto& logCatActive : LogInstance().LogCategoriesList()) {
result.pushKV(logCatActive.category, logCatActive.active);
}
@@ -545,7 +585,7 @@ static UniValue echo(const JSONRPCRequest& request)
"\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in "
"bitcoin-cli and the GUI. There is no server-side difference.",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", "Returns whatever was passed in"},
RPCExamples{""},
}.ToString()
);
@@ -555,6 +595,8 @@ static UniValue echo(const JSONRPCRequest& request)
return request.params;
}
+void RegisterMiscRPCCommands(CRPCTable &t)
+{
// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
@@ -570,13 +612,12 @@ static const CRPCCommand commands[] =
/* Not shown in help */
{ "hidden", "setmocktime", &setmocktime, {"timestamp"}},
+ { "hidden", "mockscheduler", &mockscheduler, {"delta_time"}},
{ "hidden", "echo", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
{ "hidden", "echojson", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
};
// clang-format on
-void RegisterMiscRPCCommands(CRPCTable &t)
-{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 1ce49709b2..d6d15f8b56 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -20,6 +20,7 @@
#include <sync.h>
#include <timedata.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <util/system.h>
#include <validation.h>
#include <version.h>
@@ -33,7 +34,7 @@ static UniValue getconnectioncount(const JSONRPCRequest& request)
"\nReturns the number of connections to other nodes.\n",
{},
RPCResult{
- "n (numeric) The connection count\n"
+ RPCResult::Type::NUM, "", "The connection count"
},
RPCExamples{
HelpExampleCli("getconnectioncount", "")
@@ -54,7 +55,7 @@ static UniValue ping(const JSONRPCRequest& request)
"Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
"Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("ping", "")
+ HelpExampleRpc("ping", "")
@@ -77,57 +78,60 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
"\nReturns data about each connected network node as a json array of objects.\n",
{},
RPCResult{
- "[\n"
- " {\n"
- " \"id\": n, (numeric) Peer index\n"
- " \"addr\":\"host:port\", (string) The IP address and port of the peer\n"
- " \"addrbind\":\"ip:port\", (string) Bind address of the connection to the peer\n"
- " \"addrlocal\":\"ip:port\", (string) Local address as reported by the peer\n"
- " \"mapped_as\":\"mapped_as\", (string) The AS in the BGP route to the peer used for diversifying peer selection\n"
- " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
- " \"servicesnames\":[ (array) the services offered, in human-readable form\n"
- " \"SERVICE_NAME\", (string) the service name if it is recognised\n"
- " ...\n"
- " ],\n"
- " \"relaytxes\":true|false, (boolean) Whether peer has asked us to relay transactions to it\n"
- " \"lastsend\": ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the last send\n"
- " \"lastrecv\": ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the last receive\n"
- " \"bytessent\": n, (numeric) The total bytes sent\n"
- " \"bytesrecv\": n, (numeric) The total bytes received\n"
- " \"conntime\": ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the connection\n"
- " \"timeoffset\": ttt, (numeric) The time offset in seconds\n"
- " \"pingtime\": n, (numeric) ping time (if available)\n"
- " \"minping\": n, (numeric) minimum observed ping time (if any at all)\n"
- " \"pingwait\": n, (numeric) ping wait (if non-zero)\n"
- " \"version\": v, (numeric) The peer version, such as 70001\n"
- " \"subver\": \"/Satoshi:0.8.5/\", (string) The string version\n"
- " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
- " \"addnode\": true|false, (boolean) Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n"
- " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
- " \"banscore\": n, (numeric) The ban score\n"
- " \"synced_headers\": n, (numeric) The last header we have in common with this peer\n"
- " \"synced_blocks\": n, (numeric) The last block we have in common with this peer\n"
- " \"inflight\": [\n"
- " n, (numeric) The heights of blocks we're currently asking from this peer\n"
- " ...\n"
- " ],\n"
- " \"whitelisted\": true|false, (boolean) Whether the peer is whitelisted\n"
- " \"minfeefilter\": n, (numeric) The minimum fee rate for transactions this peer accepts\n"
- " \"bytessent_per_msg\": {\n"
- " \"msg\": n, (numeric) The total bytes sent aggregated by message type\n"
- " When a message type is not listed in this json object, the bytes sent are 0.\n"
- " Only known message types can appear as keys in the object.\n"
- " ...\n"
- " },\n"
- " \"bytesrecv_per_msg\": {\n"
- " \"msg\": n, (numeric) 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+"'.\n"
- " ...\n"
- " }\n"
- " }\n"
- " ,...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {
+ {RPCResult::Type::NUM, "id", "Peer index"},
+ {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::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"},
+ {RPCResult::Type::ARR, "servicesnames", "the services offered, in human-readable form",
+ {
+ {RPCResult::Type::STR, "SERVICE_NAME", "the service name if it is recognised"}
+ }},
+ {RPCResult::Type::BOOL, "relaytxes", "Whether peer has asked us to relay transactions to it"},
+ {RPCResult::Type::NUM_TIME, "lastsend", "The " + UNIX_EPOCH_TIME + " of the last send"},
+ {RPCResult::Type::NUM_TIME, "lastrecv", "The " + UNIX_EPOCH_TIME + " of the last receive"},
+ {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
+ {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
+ {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
+ {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
+ {RPCResult::Type::NUM, "pingtime", "ping time (if available)"},
+ {RPCResult::Type::NUM, "minping", "minimum observed ping time (if any at all)"},
+ {RPCResult::Type::NUM, "pingwait", "ping wait (if non-zero)"},
+ {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, "addnode", "Whether connection was due to addnode/-connect or if it was an automatic/inbound connection"},
+ {RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"},
+ {RPCResult::Type::NUM, "banscore", "The ban score"},
+ {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
+ {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},
+ {RPCResult::Type::ARR, "inflight", "",
+ {
+ {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::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
+ {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
+ {
+ {RPCResult::Type::NUM, "msg", "The total bytes sent aggregated by message type\n"
+ "When a message type is not listed in this json object, the bytes sent are 0.\n"
+ "Only known message types can appear as keys in the object."}
+ }},
+ {RPCResult::Type::OBJ, "bytesrecv_per_msg", "",
+ {
+ {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+"'."}
+ }},
+ }},
+ }},
},
RPCExamples{
HelpExampleCli("getpeerinfo", "")
@@ -165,12 +169,15 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
obj.pushKV("bytesrecv", stats.nRecvBytes);
obj.pushKV("conntime", stats.nTimeConnected);
obj.pushKV("timeoffset", stats.nTimeOffset);
- if (stats.dPingTime > 0.0)
- obj.pushKV("pingtime", stats.dPingTime);
- if (stats.dMinPing < static_cast<double>(std::numeric_limits<int64_t>::max())/1e6)
- obj.pushKV("minping", stats.dMinPing);
- if (stats.dPingWait > 0.0)
- obj.pushKV("pingwait", stats.dPingWait);
+ if (stats.m_ping_usec > 0) {
+ obj.pushKV("pingtime", ((double)stats.m_ping_usec) / 1e6);
+ }
+ if (stats.m_min_ping_usec < std::numeric_limits<int64_t>::max()) {
+ obj.pushKV("minping", ((double)stats.m_min_ping_usec) / 1e6);
+ }
+ if (stats.m_ping_wait_usec > 0) {
+ obj.pushKV("pingwait", ((double)stats.m_ping_wait_usec) / 1e6);
+ }
obj.pushKV("version", stats.nVersion);
// Use the sanitized form of subver here, to avoid tricksy remote peers from
// corrupting or modifying the JSON output by putting special characters in
@@ -234,7 +241,7 @@ static UniValue addnode(const JSONRPCRequest& request)
{"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"},
{"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
+ HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
@@ -277,7 +284,7 @@ static UniValue disconnectnode(const JSONRPCRequest& request)
{"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"},
{"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
+ HelpExampleCli("disconnectnode", "\"\" 1")
@@ -320,19 +327,22 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request)
{"node", RPCArg::Type::STR, /* default */ "all nodes", "If provided, return information about this specific node, otherwise all nodes are returned."},
},
RPCResult{
- "[\n"
- " {\n"
- " \"addednode\" : \"192.168.0.201\", (string) The node IP address or name (as provided to addnode)\n"
- " \"connected\" : true|false, (boolean) If connected\n"
- " \"addresses\" : [ (list of objects) Only when connected = true\n"
- " {\n"
- " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server IP and port we're connected to\n"
- " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
- " }\n"
- " ]\n"
- " }\n"
- " ,...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "addednode", "The node IP address or name (as provided to addnode)"},
+ {RPCResult::Type::BOOL, "connected", "If connected"},
+ {RPCResult::Type::ARR, "addresses", "Only when connected = true",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "address", "The bitcoin server IP and port we're connected to"},
+ {RPCResult::Type::STR, "connected", "connection, inbound or outbound"},
+ }},
+ }},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
@@ -386,20 +396,21 @@ static UniValue getnettotals(const JSONRPCRequest& request)
"and current time.\n",
{},
RPCResult{
- "{\n"
- " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
- " \"totalbytessent\": n, (numeric) Total bytes sent\n"
- " \"timemillis\": t, (numeric) Current UNIX time in milliseconds\n"
- " \"uploadtarget\":\n"
- " {\n"
- " \"timeframe\": n, (numeric) Length of the measuring timeframe in seconds\n"
- " \"target\": n, (numeric) Target in bytes\n"
- " \"target_reached\": true|false, (boolean) True if target is reached\n"
- " \"serve_historical_blocks\": true|false, (boolean) True if serving historical blocks\n"
- " \"bytes_left_in_cycle\": t, (numeric) Bytes left in current time cycle\n"
- " \"time_left_in_cycle\": t (numeric) Seconds left in current time cycle\n"
- " }\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"},
+ {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},
+ {RPCResult::Type::NUM_TIME, "timemillis", "Current UNIX time in milliseconds"},
+ {RPCResult::Type::OBJ, "uploadtarget", "",
+ {
+ {RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"},
+ {RPCResult::Type::NUM, "target", "Target in bytes"},
+ {RPCResult::Type::BOOL, "target_reached", "True if target is reached"},
+ {RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"},
+ {RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"},
+ {RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("getnettotals", "")
@@ -452,41 +463,44 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
"Returns an object containing various state info regarding P2P networking.\n",
{},
RPCResult{
- "{\n"
- " \"version\": xxxxx, (numeric) the server version\n"
- " \"subversion\": \"/Satoshi:x.x.x/\", (string) the server subversion string\n"
- " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
- " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
- " \"localservicesnames\": [ (array) the services we offer to the network, in human-readable form\n"
- " \"SERVICE_NAME\", (string) the service name\n"
- " ...\n"
- " ],\n"
- " \"localrelay\": true|false, (bool) true if transaction relay is requested from peers\n"
- " \"timeoffset\": xxxxx, (numeric) the time offset\n"
- " \"connections\": xxxxx, (numeric) the number of connections\n"
- " \"networkactive\": true|false, (bool) whether p2p networking is enabled\n"
- " \"networks\": [ (array) information per network\n"
- " {\n"
- " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
- " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n"
- " \"reachable\": true|false, (boolean) is the network reachable?\n"
- " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
- " \"proxy_randomize_credentials\": true|false, (string) Whether randomized credentials are used\n"
- " }\n"
- " ,...\n"
- " ],\n"
- " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n"
- " \"incrementalfee\": x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB\n"
- " \"localaddresses\": [ (array) list of local addresses\n"
- " {\n"
- " \"address\": \"xxxx\", (string) network address\n"
- " \"port\": xxx, (numeric) network port\n"
- " \"score\": xxx (numeric) relative score\n"
- " }\n"
- " ,...\n"
- " ]\n"
- " \"warnings\": \"...\" (string) any network and blockchain warnings\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "version", "the server version"},
+ {RPCResult::Type::STR, "subversion", "the server subversion string"},
+ {RPCResult::Type::NUM, "protocolversion", "the protocol version"},
+ {RPCResult::Type::STR_HEX, "localservices", "the services we offer to the network"},
+ {RPCResult::Type::ARR, "localservicesnames", "the services we offer to the network, in human-readable form",
+ {
+ {RPCResult::Type::STR, "SERVICE_NAME", "the service name"},
+ }},
+ {RPCResult::Type::BOOL, "localrelay", "true if transaction relay is requested from peers"},
+ {RPCResult::Type::NUM, "timeoffset", "the time offset"},
+ {RPCResult::Type::NUM, "connections", "the number of connections"},
+ {RPCResult::Type::BOOL, "networkactive", "whether p2p networking is enabled"},
+ {RPCResult::Type::ARR, "networks", "information per network",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "name", "network (ipv4, ipv6 or onion)"},
+ {RPCResult::Type::BOOL, "limited", "is the network limited using -onlynet?"},
+ {RPCResult::Type::BOOL, "reachable", "is the network reachable?"},
+ {RPCResult::Type::STR, "proxy", "(\"host:port\") the proxy that is used for this network, or empty if none"},
+ {RPCResult::Type::BOOL, "proxy_randomize_credentials", "Whether randomized credentials are used"},
+ }},
+ }},
+ {RPCResult::Type::NUM, "relayfee", "minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB"},
+ {RPCResult::Type::NUM, "incrementalfee", "minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB"},
+ {RPCResult::Type::ARR, "localaddresses", "list of local addresses",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "address", "network address"},
+ {RPCResult::Type::NUM, "port", "network port"},
+ {RPCResult::Type::NUM, "score", "relative score"},
+ }},
+ }},
+ {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"},
+ }
},
RPCExamples{
HelpExampleCli("getnetworkinfo", "")
@@ -540,7 +554,7 @@ static UniValue setban(const JSONRPCRequest& request)
{"bantime", RPCArg::Type::NUM, /* default */ "0", "time in seconds how long (or until when if [absolute] is set) the IP is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)"},
{"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp expressed in " + UNIX_EPOCH_TIME},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
+ HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
@@ -615,7 +629,16 @@ static UniValue listbanned(const JSONRPCRequest& request)
RPCHelpMan{"listbanned",
"\nList all banned IPs/Subnets.\n",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "address", ""},
+ {RPCResult::Type::NUM_TIME, "banned_until", ""},
+ {RPCResult::Type::NUM_TIME, "ban_created", ""},
+ {RPCResult::Type::STR, "ban_reason", ""},
+ }},
+ }},
RPCExamples{
HelpExampleCli("listbanned", "")
+ HelpExampleRpc("listbanned", "")
@@ -650,7 +673,7 @@ static UniValue clearbanned(const JSONRPCRequest& request)
RPCHelpMan{"clearbanned",
"\nClear all banned IPs.\n",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("clearbanned", "")
+ HelpExampleRpc("clearbanned", "")
@@ -672,7 +695,7 @@ static UniValue setnetworkactive(const JSONRPCRequest& request)
{
{"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"},
RPCExamples{""},
}.Check(request);
@@ -690,18 +713,19 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
RPCHelpMan{"getnodeaddresses",
"\nReturn known addresses which can potentially be used to find new nodes in the network\n",
{
- {"count", RPCArg::Type::NUM, /* default */ "1", "How many addresses to return. Limited to the smaller of " + std::to_string(ADDRMAN_GETADDR_MAX) + " or " + std::to_string(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses."},
+ {"count", RPCArg::Type::NUM, /* default */ "1", "How many addresses to return. Limited to the smaller of " + ToString(ADDRMAN_GETADDR_MAX) + " or " + ToString(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses."},
},
RPCResult{
- "[\n"
- " {\n"
- " \"time\": ttt, (numeric) The " + UNIX_EPOCH_TIME + " of when the node was last seen\n"
- " \"services\": n, (numeric) The services offered\n"
- " \"address\": \"host\", (string) The address of the node\n"
- " \"port\": n (numeric) The port of the node\n"
- " }\n"
- " ,....\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " of when the node was last seen"},
+ {RPCResult::Type::NUM, "services", "The services offered"},
+ {RPCResult::Type::STR, "address", "The address of the node"},
+ {RPCResult::Type::NUM, "port", "The port of the node"},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("getnodeaddresses", "8")
@@ -736,6 +760,8 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
return ret;
}
+void RegisterNetRPCCommands(CRPCTable &t)
+{
// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
@@ -756,8 +782,6 @@ static const CRPCCommand commands[] =
};
// clang-format on
-void RegisterNetRPCCommands(CRPCTable &t)
-{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index cea59b2c7a..063ee1697c 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -30,6 +30,7 @@
#include <uint256.h>
#include <util/moneystr.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <validation.h>
#include <validationinterface.h>
@@ -39,12 +40,6 @@
#include <univalue.h>
-/** Maximum fee rate for sendrawtransaction and testmempoolaccept.
- * By default, a transaction with a fee rate higher than this will be rejected
- * by the RPCs. This can be overridden with the maxfeerate argument.
- */
-static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE{COIN / 10};
-
static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
// Call into TxToUniv() in bitcoin-common to decode the transaction hex.
@@ -94,54 +89,62 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
},
{
RPCResult{"if verbose is not set or set to false",
- "\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
+ RPCResult::Type::STR, "data", "The serialized, hex-encoded data for 'txid'"
},
RPCResult{"if verbose is set to true",
- "{\n"
- " \"in_active_chain\": b, (bool) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n"
- " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n"
- " \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
- " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n"
- " \"size\" : n, (numeric) The serialized transaction size\n"
- " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n"
- " \"weight\" : n, (numeric) The transaction's weight (between vsize*4-3 and vsize*4)\n"
- " \"version\" : n, (numeric) The version\n"
- " \"locktime\" : ttt, (numeric) The lock time\n"
- " \"vin\" : [ (array of json objects)\n"
- " {\n"
- " \"txid\": \"id\", (string) The transaction id\n"
- " \"vout\": n, (numeric) \n"
- " \"scriptSig\": { (json object) The script\n"
- " \"asm\": \"asm\", (string) asm\n"
- " \"hex\": \"hex\" (string) hex\n"
- " },\n"
- " \"sequence\": n (numeric) The script sequence number\n"
- " \"txinwitness\": [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n"
- " }\n"
- " ,...\n"
- " ],\n"
- " \"vout\" : [ (array of json objects)\n"
- " {\n"
- " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n"
- " \"n\" : n, (numeric) index\n"
- " \"scriptPubKey\" : { (json object)\n"
- " \"asm\" : \"asm\", (string) the asm\n"
- " \"hex\" : \"hex\", (string) the hex\n"
- " \"reqSigs\" : n, (numeric) The required sigs\n"
- " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
- " \"addresses\" : [ (json array of string)\n"
- " \"address\" (string) bitcoin address\n"
- " ,...\n"
- " ]\n"
- " }\n"
- " }\n"
- " ,...\n"
- " ],\n"
- " \"blockhash\" : \"hash\", (string) the block hash\n"
- " \"confirmations\" : n, (numeric) The confirmations\n"
- " \"blocktime\" : ttt (numeric) The block time expressed in " + UNIX_EPOCH_TIME + "\n"
- " \"time\" : ttt, (numeric) Same as \"blocktime\"\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "in_active_chain", "Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)"},
+ {RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded data for 'txid'"},
+ {RPCResult::Type::STR_HEX, "txid", "The transaction id (same as provided)"},
+ {RPCResult::Type::STR_HEX, "hash", "The transaction hash (differs from txid for witness transactions)"},
+ {RPCResult::Type::NUM, "size", "The serialized transaction size"},
+ {RPCResult::Type::NUM, "vsize", "The virtual transaction size (differs from size for witness transactions)"},
+ {RPCResult::Type::NUM, "weight", "The transaction's weight (between vsize*4-3 and vsize*4)"},
+ {RPCResult::Type::NUM, "version", "The version"},
+ {RPCResult::Type::NUM_TIME, "locktime", "The lock time"},
+ {RPCResult::Type::ARR, "vin", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
+ {RPCResult::Type::STR, "vout", ""},
+ {RPCResult::Type::OBJ, "scriptSig", "The script",
+ {
+ {RPCResult::Type::STR, "asm", "asm"},
+ {RPCResult::Type::STR_HEX, "hex", "hex"},
+ }},
+ {RPCResult::Type::NUM, "sequence", "The script sequence number"},
+ {RPCResult::Type::ARR, "txinwitness", "",
+ {
+ {RPCResult::Type::STR_HEX, "hex", "hex-encoded witness data (if any)"},
+ }},
+ }},
+ }},
+ {RPCResult::Type::ARR, "vout", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "value", "The value in " + CURRENCY_UNIT},
+ {RPCResult::Type::NUM, "n", "index"},
+ {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {
+ {RPCResult::Type::STR, "asm", "the asm"},
+ {RPCResult::Type::STR, "hex", "the hex"},
+ {RPCResult::Type::NUM, "reqSigs", "The required sigs"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ {RPCResult::Type::ARR, "addresses", "",
+ {
+ {RPCResult::Type::STR, "address", "bitcoin address"},
+ }},
+ }},
+ }},
+ }},
+ {RPCResult::Type::STR_HEX, "blockhash", "the block hash"},
+ {RPCResult::Type::NUM, "confirmations", "The confirmations"},
+ {RPCResult::Type::NUM_TIME, "blocktime", "The block time expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM, "time", "Same as \"blocktime\""},
+ }
},
},
RPCExamples{
@@ -222,7 +225,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
"you need to maintain a transaction index, using the -txindex command line option or\n"
"specify the block in which the transaction is included manually (by blockhash).\n",
{
- {"txids", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of txids to filter",
+ {"txids", RPCArg::Type::ARR, RPCArg::Optional::NO, "The txids to filter",
{
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A transaction hash"},
},
@@ -230,7 +233,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "If specified, looks for txid in the block with this hash"},
},
RPCResult{
- "\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n"
+ RPCResult::Type::STR, "data", "A string that is a serialized, hex-encoded data for the proof."
},
RPCExamples{""},
}.Check(request);
@@ -315,7 +318,10 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request)
{"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"},
},
RPCResult{
- "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof can not be validated.\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The txid(s) which the proof commits to, or empty array if the proof can not be validated."},
+ }
},
RPCExamples{""},
}.Check(request);
@@ -357,7 +363,7 @@ static UniValue createrawtransaction(const JSONRPCRequest& request)
"Note that the transaction's inputs are not signed, and\n"
"it is not stored in the wallet or transmitted to the network.\n",
{
- {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects",
+ {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The inputs",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -368,7 +374,7 @@ static UniValue createrawtransaction(const JSONRPCRequest& request)
},
},
},
- {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n"
+ {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs (key-value pairs), where none of the keys are duplicated.\n"
"That is, each address can only appear once and there can only be one 'data' object.\n"
"For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
" accepted as second parameter.",
@@ -390,7 +396,7 @@ static UniValue createrawtransaction(const JSONRPCRequest& request)
" Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
},
RPCResult{
- "\"transaction\" (string) hex string of the transaction\n"
+ RPCResult::Type::STR_HEX, "transaction", "hex string of the transaction"
},
RPCExamples{
HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"")
@@ -432,45 +438,53 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request)
},
},
RPCResult{
- "{\n"
- " \"txid\" : \"id\", (string) The transaction id\n"
- " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n"
- " \"size\" : n, (numeric) The transaction size\n"
- " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n"
- " \"weight\" : n, (numeric) The transaction's weight (between vsize*4 - 3 and vsize*4)\n"
- " \"version\" : n, (numeric) The version\n"
- " \"locktime\" : ttt, (numeric) The lock time\n"
- " \"vin\" : [ (array of json objects)\n"
- " {\n"
- " \"txid\": \"id\", (string) The transaction id\n"
- " \"vout\": n, (numeric) The output number\n"
- " \"scriptSig\": { (json object) The script\n"
- " \"asm\": \"asm\", (string) asm\n"
- " \"hex\": \"hex\" (string) hex\n"
- " },\n"
- " \"txinwitness\": [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n"
- " \"sequence\": n (numeric) The script sequence number\n"
- " }\n"
- " ,...\n"
- " ],\n"
- " \"vout\" : [ (array of json objects)\n"
- " {\n"
- " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n"
- " \"n\" : n, (numeric) index\n"
- " \"scriptPubKey\" : { (json object)\n"
- " \"asm\" : \"asm\", (string) the asm\n"
- " \"hex\" : \"hex\", (string) the hex\n"
- " \"reqSigs\" : n, (numeric) The required sigs\n"
- " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
- " \"addresses\" : [ (json array of string)\n"
- " \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) bitcoin address\n"
- " ,...\n"
- " ]\n"
- " }\n"
- " }\n"
- " ,...\n"
- " ],\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
+ {RPCResult::Type::STR_HEX, "hash", "The transaction hash (differs from txid for witness transactions)"},
+ {RPCResult::Type::NUM, "size", "The transaction size"},
+ {RPCResult::Type::NUM, "vsize", "The virtual transaction size (differs from size for witness transactions)"},
+ {RPCResult::Type::NUM, "weight", "The transaction's weight (between vsize*4 - 3 and vsize*4)"},
+ {RPCResult::Type::NUM, "version", "The version"},
+ {RPCResult::Type::NUM_TIME, "locktime", "The lock time"},
+ {RPCResult::Type::ARR, "vin", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
+ {RPCResult::Type::NUM, "vout", "The output number"},
+ {RPCResult::Type::OBJ, "scriptSig", "The script",
+ {
+ {RPCResult::Type::STR, "asm", "asm"},
+ {RPCResult::Type::STR_HEX, "hex", "hex"},
+ }},
+ {RPCResult::Type::ARR, "txinwitness", "",
+ {
+ {RPCResult::Type::STR_HEX, "hex", "hex-encoded witness data (if any)"},
+ }},
+ {RPCResult::Type::NUM, "sequence", "The script sequence number"},
+ }},
+ }},
+ {RPCResult::Type::ARR, "vout", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "value", "The value in " + CURRENCY_UNIT},
+ {RPCResult::Type::NUM, "n", "index"},
+ {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {
+ {RPCResult::Type::STR, "asm", "the asm"},
+ {RPCResult::Type::STR_HEX, "hex", "the hex"},
+ {RPCResult::Type::NUM, "reqSigs", "The required sigs"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ {RPCResult::Type::ARR, "addresses", "",
+ {
+ {RPCResult::Type::STR, "address", "bitcoin address"},
+ }},
+ }},
+ }},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("decoderawtransaction", "\"hexstring\"")
@@ -513,26 +527,29 @@ static UniValue decodescript(const JSONRPCRequest& request)
{"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded script"},
},
RPCResult{
- "{\n"
- " \"asm\":\"asm\", (string) Script public key\n"
- " \"type\":\"type\", (string) The output type (e.g. "+GetAllOutputTypes()+")\n"
- " \"reqSigs\": n, (numeric) The required signatures\n"
- " \"addresses\": [ (json array of string)\n"
- " \"address\" (string) bitcoin address\n"
- " ,...\n"
- " ],\n"
- " \"p2sh\":\"str\" (string) address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).\n"
- " \"segwit\": { (json object) Result of a witness script public key wrapping this redeem script (not returned if the script is a P2SH or witness).\n"
- " \"asm\":\"str\", (string) String representation of the script public key\n"
- " \"hex\":\"hexstr\", (string) Hex string of the script public key\n"
- " \"type\":\"str\", (string) The type of the script public key (e.g. witness_v0_keyhash or witness_v0_scripthash)\n"
- " \"reqSigs\": n, (numeric) The required signatures (always 1)\n"
- " \"addresses\": [ (json array of string) (always length 1)\n"
- " \"address\" (string) segwit address\n"
- " ,...\n"
- " ],\n"
- " \"p2sh-segwit\":\"str\" (string) address of the P2SH script wrapping this witness redeem script.\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "asm", "Script public key"},
+ {RPCResult::Type::STR, "type", "The output type (e.g. "+GetAllOutputTypes()+")"},
+ {RPCResult::Type::NUM, "reqSigs", "The required signatures"},
+ {RPCResult::Type::ARR, "addresses", "",
+ {
+ {RPCResult::Type::STR, "address", "bitcoin address"},
+ }},
+ {RPCResult::Type::STR, "p2sh", "address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH)"},
+ {RPCResult::Type::OBJ, "segwit", "Result of a witness script public key wrapping this redeem script (not returned if the script is a P2SH or witness)",
+ {
+ {RPCResult::Type::STR, "asm", "String representation of the script public key"},
+ {RPCResult::Type::STR_HEX, "hex", "Hex string of the script public key"},
+ {RPCResult::Type::STR, "type", "The type of the script public key (e.g. witness_v0_keyhash or witness_v0_scripthash)"},
+ {RPCResult::Type::NUM, "reqSigs", "The required signatures (always 1)"},
+ {RPCResult::Type::ARR, "addresses", "(always length 1)",
+ {
+ {RPCResult::Type::STR, "address", "segwit address"},
+ }},
+ {RPCResult::Type::STR, "p2sh-segwit", "address of the P2SH script wrapping this witness redeem script"},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("decodescript", "\"hexstring\"")
@@ -600,14 +617,14 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
"The combined transaction may be another partially signed transaction or a \n"
"fully signed transaction.",
{
- {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of hex strings of partially signed transactions",
+ {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The hex strings of partially signed transactions",
{
{"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A transaction hash"},
},
},
},
RPCResult{
- "\"hex\" (string) The hex-encoded raw transaction with signature(s)\n"
+ RPCResult::Type::STR, "", "The hex-encoded raw transaction with signature(s)"
},
RPCExamples{
HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')")
@@ -686,12 +703,12 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
"this transaction depends on but may not yet be in the block chain.\n",
{
{"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"},
- {"privkeys", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base58-encoded private keys for signing",
+ {"privkeys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base58-encoded private keys for signing",
{
{"privatekey", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "private key in base58-encoding"},
},
},
- {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of previous dependent transaction outputs",
+ {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The previous dependent transaction outputs",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -715,20 +732,22 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
},
},
RPCResult{
- "{\n"
- " \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
- " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
- " \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n"
- " {\n"
- " \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n"
- " \"vout\" : n, (numeric) The index of the output to spent and used as input\n"
- " \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n"
- " \"sequence\" : n, (numeric) Script sequence number\n"
- " \"error\" : \"text\" (string) Verification or signing error related to the input\n"
- " }\n"
- " ,...\n"
- " ]\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"},
+ {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
+ {RPCResult::Type::ARR, "errors", "Script verification errors (if there are any)",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"},
+ {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"},
+ {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"},
+ {RPCResult::Type::NUM, "sequence", "Script sequence number"},
+ {RPCResult::Type::STR, "error", "Verification or signing error related to the input"},
+ }},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("signrawtransactionwithkey", "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"")
@@ -784,7 +803,7 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request)
"/kB.\nSet to 0 to accept any fee rate.\n"},
},
RPCResult{
- "\"hex\" (string) The transaction hash in hex\n"
+ RPCResult::Type::STR_HEX, "", "The transaction hash in hex"
},
RPCExamples{
"\nCreate a transaction\n"
@@ -800,7 +819,7 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request)
RPCTypeCheck(request.params, {
UniValue::VSTR,
- UniValueType(), // NUM or BOOL, checked later
+ UniValueType(), // VNUM or VSTR, checked inside AmountFromValue()
});
// parse hex string from parameter
@@ -809,13 +828,9 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request)
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
- CFeeRate max_raw_tx_fee_rate = DEFAULT_MAX_RAW_TX_FEE_RATE;
- // TODO: temporary migration code for old clients. Remove in v0.20
- if (request.params[1].isBool()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and no longer supports a boolean. To allow a transaction with high fees, set maxfeerate to 0.");
- } else if (!request.params[1].isNull()) {
- max_raw_tx_fee_rate = CFeeRate(AmountFromValue(request.params[1]));
- }
+ const CFeeRate max_raw_tx_fee_rate = request.params[1].isNull() ?
+ DEFAULT_MAX_RAW_TX_FEE_RATE :
+ CFeeRate(AmountFromValue(request.params[1]));
int64_t virtual_size = GetVirtualTransactionSize(*tx);
CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
@@ -846,14 +861,16 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
{"maxfeerate", RPCArg::Type::AMOUNT, /* default */ FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK()), "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + "/kB\n"},
},
RPCResult{
- "[ (array) The result of the mempool acceptance test for each raw transaction in the input array.\n"
- " Length is exactly one for now.\n"
- " {\n"
- " \"txid\" (string) The transaction hash in hex\n"
- " \"allowed\" (boolean) If the mempool allows this tx to be inserted\n"
- " \"reject-reason\" (string) Rejection string (only present when 'allowed' is false)\n"
- " }\n"
- "]\n"
+ RPCResult::Type::ARR, "", "The result of the mempool acceptance test for each raw transaction in the input array.\n"
+ "Length is exactly one for now.",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
+ {RPCResult::Type::BOOL, "allowed", "If the mempool allows this tx to be inserted"},
+ {RPCResult::Type::STR, "reject-reason", "Rejection string (only present when 'allowed' is false)"},
+ }},
+ }
},
RPCExamples{
"\nCreate a transaction\n"
@@ -869,7 +886,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
RPCTypeCheck(request.params, {
UniValue::VARR,
- UniValueType(), // NUM or BOOL, checked later
+ UniValueType(), // VNUM or VSTR, checked inside AmountFromValue()
});
if (request.params[0].get_array().size() != 1) {
@@ -883,13 +900,9 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
const uint256& tx_hash = tx->GetHash();
- CFeeRate max_raw_tx_fee_rate = DEFAULT_MAX_RAW_TX_FEE_RATE;
- // TODO: temporary migration code for old clients. Remove in v0.20
- if (request.params[1].isBool()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and no longer supports a boolean. To allow a transaction with high fees, set maxfeerate to 0.");
- } else if (!request.params[1].isNull()) {
- max_raw_tx_fee_rate = CFeeRate(AmountFromValue(request.params[1]));
- }
+ const CFeeRate max_raw_tx_fee_rate = request.params[1].isNull() ?
+ DEFAULT_MAX_RAW_TX_FEE_RATE :
+ CFeeRate(AmountFromValue(request.params[1]));
CTxMemPool& mempool = EnsureMemPool();
int64_t virtual_size = GetVirtualTransactionSize(*tx);
@@ -934,7 +947,7 @@ static std::string WriteHDKeypath(std::vector<uint32_t>& keypath)
num &= ~0x80000000;
}
- keypath_str += std::to_string(num);
+ keypath_str += ToString(num);
if (hardened) {
keypath_str += "'";
}
@@ -950,92 +963,108 @@ UniValue decodepsbt(const JSONRPCRequest& request)
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The PSBT base64 string"},
},
RPCResult{
- "{\n"
- " \"tx\" : { (json object) The decoded network-serialized unsigned transaction.\n"
- " ... The layout is the same as the output of decoderawtransaction.\n"
- " },\n"
- " \"unknown\" : { (json object) The unknown global fields\n"
- " \"key\" : \"value\" (key-value pair) An unknown key-value pair\n"
- " ...\n"
- " },\n"
- " \"inputs\" : [ (array of json objects)\n"
- " {\n"
- " \"non_witness_utxo\" : { (json object, optional) Decoded network transaction for non-witness UTXOs\n"
- " ...\n"
- " },\n"
- " \"witness_utxo\" : { (json object, optional) Transaction output for witness UTXOs\n"
- " \"amount\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n"
- " \"scriptPubKey\" : { (json object)\n"
- " \"asm\" : \"asm\", (string) The asm\n"
- " \"hex\" : \"hex\", (string) The hex\n"
- " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
- " \"address\" : \"address\" (string) Bitcoin address if there is one\n"
- " }\n"
- " },\n"
- " \"partial_signatures\" : { (json object, optional)\n"
- " \"pubkey\" : \"signature\", (string) The public key and signature that corresponds to it.\n"
- " ,...\n"
- " }\n"
- " \"sighash\" : \"type\", (string, optional) The sighash type to be used\n"
- " \"redeem_script\" : { (json object, optional)\n"
- " \"asm\" : \"asm\", (string) The asm\n"
- " \"hex\" : \"hex\", (string) The hex\n"
- " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
- " }\n"
- " \"witness_script\" : { (json object, optional)\n"
- " \"asm\" : \"asm\", (string) The asm\n"
- " \"hex\" : \"hex\", (string) The hex\n"
- " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
- " }\n"
- " \"bip32_derivs\" : { (json object, optional)\n"
- " \"pubkey\" : { (json object, optional) The public key with the derivation path as the value.\n"
- " \"master_fingerprint\" : \"fingerprint\" (string) The fingerprint of the master key\n"
- " \"path\" : \"path\", (string) The path\n"
- " }\n"
- " ,...\n"
- " }\n"
- " \"final_scriptsig\" : { (json object, optional)\n"
- " \"asm\" : \"asm\", (string) The asm\n"
- " \"hex\" : \"hex\", (string) The hex\n"
- " }\n"
- " \"final_scriptwitness\": [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n"
- " \"unknown\" : { (json object) The unknown global fields\n"
- " \"key\" : \"value\" (key-value pair) An unknown key-value pair\n"
- " ...\n"
- " },\n"
- " }\n"
- " ,...\n"
- " ]\n"
- " \"outputs\" : [ (array of json objects)\n"
- " {\n"
- " \"redeem_script\" : { (json object, optional)\n"
- " \"asm\" : \"asm\", (string) The asm\n"
- " \"hex\" : \"hex\", (string) The hex\n"
- " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
- " }\n"
- " \"witness_script\" : { (json object, optional)\n"
- " \"asm\" : \"asm\", (string) The asm\n"
- " \"hex\" : \"hex\", (string) The hex\n"
- " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
- " }\n"
- " \"bip32_derivs\" : [ (array of json objects, optional)\n"
- " {\n"
- " \"pubkey\" : \"pubkey\", (string) The public key this path corresponds to\n"
- " \"master_fingerprint\" : \"fingerprint\" (string) The fingerprint of the master key\n"
- " \"path\" : \"path\", (string) The path\n"
- " }\n"
- " }\n"
- " ,...\n"
- " ],\n"
- " \"unknown\" : { (json object) The unknown global fields\n"
- " \"key\" : \"value\" (key-value pair) An unknown key-value pair\n"
- " ...\n"
- " },\n"
- " }\n"
- " ,...\n"
- " ]\n"
- " \"fee\" : fee (numeric, optional) The transaction fee paid if all UTXOs slots in the PSBT have been filled.\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ, "tx", "The decoded network-serialized unsigned transaction.",
+ {
+ {RPCResult::Type::ELISION, "", "The layout is the same as the output of decoderawtransaction."},
+ }},
+ {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",
+ {
+ {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
+ }},
+ {RPCResult::Type::ARR, "inputs", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ, "non_witness_utxo", /* optional */ true, "Decoded network transaction for non-witness UTXOs",
+ {
+ {RPCResult::Type::ELISION, "",""},
+ }},
+ {RPCResult::Type::OBJ, "witness_utxo", /* optional */ true, "Transaction output for witness UTXOs",
+ {
+ {RPCResult::Type::NUM, "amount", "The value in " + CURRENCY_UNIT},
+ {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {
+ {RPCResult::Type::STR, "asm", "The asm"},
+ {RPCResult::Type::STR_HEX, "hex", "The hex"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ {RPCResult::Type::STR, "address"," Bitcoin address if there is one"},
+ }},
+ }},
+ {RPCResult::Type::OBJ_DYN, "partial_signatures", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR, "pubkey", "The public key and signature that corresponds to it."},
+ }},
+ {RPCResult::Type::STR, "sighash", /* optional */ true, "The sighash type to be used"},
+ {RPCResult::Type::OBJ, "redeem_script", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR, "asm", "The asm"},
+ {RPCResult::Type::STR_HEX, "hex", "The hex"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ }},
+ {RPCResult::Type::OBJ, "witness_script", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR, "asm", "The asm"},
+ {RPCResult::Type::STR_HEX, "hex", "The hex"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ }},
+ {RPCResult::Type::ARR, "bip32_derivs", /* optional */ true, "",
+ {
+ {RPCResult::Type::OBJ, "pubkey", /* optional */ true, "The public key with the derivation path as the value.",
+ {
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
+ }},
+ }},
+ {RPCResult::Type::OBJ, "final_scriptsig", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR, "asm", "The asm"},
+ {RPCResult::Type::STR, "hex", "The hex"},
+ }},
+ {RPCResult::Type::ARR, "final_scriptwitness", "",
+ {
+ {RPCResult::Type::STR_HEX, "", "hex-encoded witness data (if any)"},
+ }},
+ {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",
+ {
+ {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
+ }},
+ }},
+ }},
+ {RPCResult::Type::ARR, "outputs", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ, "redeem_script", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR, "asm", "The asm"},
+ {RPCResult::Type::STR_HEX, "hex", "The hex"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ }},
+ {RPCResult::Type::OBJ, "witness_script", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR, "asm", "The asm"},
+ {RPCResult::Type::STR_HEX, "hex", "The hex"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ }},
+ {RPCResult::Type::ARR, "bip32_derivs", /* optional */ true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"},
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
+ }},
+ }},
+ {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",
+ {
+ {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
+ }},
+ }},
+ }},
+ {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The transaction fee paid if all UTXOs slots in the PSBT have been filled."},
+ }
},
RPCExamples{
HelpExampleCli("decodepsbt", "\"psbt\"")
@@ -1237,14 +1266,14 @@ UniValue combinepsbt(const JSONRPCRequest& request)
"\nCombine multiple partially signed Bitcoin transactions into one transaction.\n"
"Implements the Combiner role.\n",
{
- {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base64 strings of partially signed transactions",
+ {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base64 strings of partially signed transactions",
{
{"psbt", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A base64 string of a PSBT"},
},
},
},
RPCResult{
- " \"psbt\" (string) The base64-encoded partially signed transaction\n"
+ RPCResult::Type::STR, "", "The base64-encoded partially signed transaction"
},
RPCExamples{
HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')")
@@ -1292,12 +1321,12 @@ UniValue finalizepsbt(const JSONRPCRequest& request)
" extract and return the complete transaction in normal network serialization instead of the PSBT."},
},
RPCResult{
- "{\n"
- " \"psbt\" : \"value\", (string) The base64-encoded partially signed transaction if not extracted\n"
- " \"hex\" : \"value\", (string) The hex-encoded network transaction if extracted\n"
- " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
- " ]\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction if not extracted"},
+ {RPCResult::Type::STR_HEX, "hex", "The hex-encoded network transaction if extracted"},
+ {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
+ }
},
RPCExamples{
HelpExampleCli("finalizepsbt", "\"psbt\"")
@@ -1342,7 +1371,7 @@ UniValue createpsbt(const JSONRPCRequest& request)
"\nCreates a transaction in the Partially Signed Transaction format.\n"
"Implements the Creator role.\n",
{
- {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects",
+ {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The json objects",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -1353,7 +1382,7 @@ UniValue createpsbt(const JSONRPCRequest& request)
},
},
},
- {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n"
+ {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs (key-value pairs), where none of the keys are duplicated.\n"
"That is, each address can only appear once and there can only be one 'data' object.\n"
"For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
" accepted as second parameter.",
@@ -1375,7 +1404,7 @@ UniValue createpsbt(const JSONRPCRequest& request)
" Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
},
RPCResult{
- " \"psbt\" (string) The resulting raw transaction (base64-encoded string)\n"
+ RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)"
},
RPCExamples{
HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
@@ -1432,7 +1461,7 @@ UniValue converttopsbt(const JSONRPCRequest& request)
},
},
RPCResult{
- " \"psbt\" (string) The resulting raw transaction (base64-encoded string)\n"
+ RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)"
},
RPCExamples{
"\nCreate a transaction\n"
@@ -1496,7 +1525,7 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request)
}},
},
RPCResult {
- " \"psbt\" (string) The base64-encoded partially signed transaction with inputs updated\n"
+ RPCResult::Type::STR, "", "The base64-encoded partially signed transaction with inputs updated"
},
RPCExamples {
HelpExampleCli("utxoupdatepsbt", "\"psbt\"")
@@ -1575,13 +1604,13 @@ UniValue joinpsbts(const JSONRPCRequest& request)
"\nJoins multiple distinct PSBTs with different inputs and outputs into one PSBT with inputs and outputs from all of the PSBTs\n"
"No input in any of the PSBTs can be in more than one of the PSBTs.\n",
{
- {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base64 strings of partially signed transactions",
+ {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base64 strings of partially signed transactions",
{
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
}}
},
RPCResult {
- " \"psbt\" (string) The base64-encoded partially signed transaction\n"
+ RPCResult::Type::STR, "", "The base64-encoded partially signed transaction"
},
RPCExamples {
HelpExampleCli("joinpsbts", "\"psbt\"")
@@ -1670,31 +1699,36 @@ UniValue analyzepsbt(const JSONRPCRequest& request)
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
},
RPCResult {
- "{\n"
- " \"inputs\" : [ (array of json objects)\n"
- " {\n"
- " \"has_utxo\" : true|false (boolean) Whether a UTXO is provided\n"
- " \"is_final\" : true|false (boolean) Whether the input is finalized\n"
- " \"missing\" : { (json object, optional) Things that are missing that are required to complete this input\n"
- " \"pubkeys\" : [ (array, optional)\n"
- " \"keyid\" (string) Public key ID, hash160 of the public key, of a public key whose BIP 32 derivation path is missing\n"
- " ]\n"
- " \"signatures\" : [ (array, optional)\n"
- " \"keyid\" (string) Public key ID, hash160 of the public key, of a public key whose signature is missing\n"
- " ]\n"
- " \"redeemscript\" : \"hash\" (string, optional) Hash160 of the redeemScript that is missing\n"
- " \"witnessscript\" : \"hash\" (string, optional) SHA256 of the witnessScript that is missing\n"
- " }\n"
- " \"next\" : \"role\" (string, optional) Role of the next person that this input needs to go to\n"
- " }\n"
- " ,...\n"
- " ]\n"
- " \"estimated_vsize\" : vsize (numeric, optional) Estimated vsize of the final signed transaction\n"
- " \"estimated_feerate\" : feerate (numeric, optional) Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kB. Shown only if all UTXO slots in the PSBT have been filled.\n"
- " \"fee\" : fee (numeric, optional) The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled.\n"
- " \"next\" : \"role\" (string) Role of the next person that this psbt needs to go to\n"
- " \"error\" : \"error\" (string) Error message if there is one\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::ARR, "inputs", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "has_utxo", "Whether a UTXO is provided"},
+ {RPCResult::Type::BOOL, "is_final", "Whether the input is finalized"},
+ {RPCResult::Type::OBJ, "missing", /* optional */ true, "Things that are missing that are required to complete this input",
+ {
+ {RPCResult::Type::ARR, "pubkeys", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR_HEX, "keyid", "Public key ID, hash160 of the public key, of a public key whose BIP 32 derivation path is missing"},
+ }},
+ {RPCResult::Type::ARR, "signatures", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR_HEX, "keyid", "Public key ID, hash160 of the public key, of a public key whose signature is missing"},
+ }},
+ {RPCResult::Type::STR_HEX, "redeemscript", /* optional */ true, "Hash160 of the redeemScript that is missing"},
+ {RPCResult::Type::STR_HEX, "witnessscript", /* optional */ true, "SHA256 of the witnessScript that is missing"},
+ }},
+ {RPCResult::Type::STR, "next", /* optional */ true, "Role of the next person that this input needs to go to"},
+ }},
+ }},
+ {RPCResult::Type::NUM, "estimated_vsize", /* optional */ true, "Estimated vsize of the final signed transaction"},
+ {RPCResult::Type::STR_AMOUNT, "estimated_feerate", /* optional */ true, "Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kB. Shown only if all UTXO slots in the PSBT have been filled"},
+ {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled"},
+ {RPCResult::Type::STR, "next", "Role of the next person that this psbt needs to go to"},
+ {RPCResult::Type::STR, "error", "Error message if there is one"},
+ }
},
RPCExamples {
HelpExampleCli("analyzepsbt", "\"psbt\"")
@@ -1765,6 +1799,8 @@ UniValue analyzepsbt(const JSONRPCRequest& request)
return result;
}
+void RegisterRawTransactionRPCCommands(CRPCTable &t)
+{
// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
@@ -1773,10 +1809,10 @@ static const CRPCCommand commands[] =
{ "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable"} },
{ "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring","iswitness"} },
{ "rawtransactions", "decodescript", &decodescript, {"hexstring"} },
- { "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","allowhighfees|maxfeerate"} },
+ { "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","maxfeerate"} },
{ "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} },
{ "rawtransactions", "signrawtransactionwithkey", &signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} },
- { "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","allowhighfees|maxfeerate"} },
+ { "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","maxfeerate"} },
{ "rawtransactions", "decodepsbt", &decodepsbt, {"psbt"} },
{ "rawtransactions", "combinepsbt", &combinepsbt, {"txs"} },
{ "rawtransactions", "finalizepsbt", &finalizepsbt, {"psbt", "extract"} },
@@ -1791,8 +1827,6 @@ static const CRPCCommand commands[] =
};
// clang-format on
-void RegisterRawTransactionRPCCommands(CRPCTable &t)
-{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index 40334883c5..bd82773bf2 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -216,7 +216,7 @@ void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keyst
keystore->AddCScript(script);
// Automatically also add the P2WSH wrapped version of the script (to deal with P2SH-P2WSH).
// This is done for redeemScript only for compatibility, it is encouraged to use the explicit witnessScript field instead.
- CScript witness_output_script{GetScriptForWitness(script)};
+ CScript witness_output_script{GetScriptForDestination(WitnessV0ScriptHash(script))};
keystore->AddCScript(witness_output_script);
if (!ws.isNull() && !rs.isNull()) {
@@ -272,55 +272,27 @@ void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
{
int nHashType = ParseSighashString(hashType);
- bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
-
// Script verification errors
- UniValue vErrors(UniValue::VARR);
-
- // Use CTransaction for the constant parts of the
- // transaction to avoid rehashing.
- const CTransaction txConst(mtx);
- // Sign what we can:
- for (unsigned int i = 0; i < mtx.vin.size(); i++) {
- CTxIn& txin = mtx.vin[i];
- auto coin = coins.find(txin.prevout);
- if (coin == coins.end() || coin->second.IsSpent()) {
- TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
- continue;
- }
- const CScript& prevPubKey = coin->second.out.scriptPubKey;
- const CAmount& amount = coin->second.out.nValue;
-
- SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
- // Only sign SIGHASH_SINGLE if there's a corresponding output:
- if (!fHashSingle || (i < mtx.vout.size())) {
- ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
- }
-
- UpdateInput(txin, sigdata);
+ std::map<int, std::string> input_errors;
- // amount must be specified for valid segwit signature
- if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) {
- throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin->second.out.ToString()));
- }
+ bool complete = SignTransaction(mtx, keystore, coins, nHashType, input_errors);
+ SignTransactionResultToJSON(mtx, complete, coins, input_errors, result);
+}
- ScriptError serror = SCRIPT_ERR_OK;
- if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
- if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
- // Unable to sign input and verification failed (possible attempt to partially sign).
- TxInErrorToJSON(txin, vErrors, "Unable to sign input, invalid stack size (possibly missing key)");
- } else if (serror == SCRIPT_ERR_SIG_NULLFAIL) {
- // Verification failed (possibly due to insufficient signatures).
- TxInErrorToJSON(txin, vErrors, "CHECK(MULTI)SIG failing with non-zero signature (possibly need more signatures)");
- } else {
- TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
- }
+void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, std::map<int, std::string>& input_errors, UniValue& result)
+{
+ // Make errors UniValue
+ UniValue vErrors(UniValue::VARR);
+ for (const auto& err_pair : input_errors) {
+ if (err_pair.second == "Missing amount") {
+ // This particular error needs to be an exception for some reason
+ throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coins.at(mtx.vin.at(err_pair.first).prevout).out.ToString()));
}
+ TxInErrorToJSON(mtx.vin.at(err_pair.first), vErrors, err_pair.second);
}
- bool fComplete = vErrors.empty();
result.pushKV("hex", EncodeHexTx(CTransaction(mtx)));
- result.pushKV("complete", fComplete);
+ result.pushKV("complete", complete);
if (!vErrors.empty()) {
if (result.exists("errors")) {
vErrors.push_backV(result["errors"].getValues());
diff --git a/src/rpc/rawtransaction_util.h b/src/rpc/rawtransaction_util.h
index 4750fd64ed..942314eccf 100644
--- a/src/rpc/rawtransaction_util.h
+++ b/src/rpc/rawtransaction_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -6,6 +6,7 @@
#define BITCOIN_RPC_RAWTRANSACTION_UTIL_H
#include <map>
+#include <string>
class FillableSigningProvider;
class UniValue;
@@ -24,6 +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);
/**
* Parse a prevtxs UniValue array and get the map of coins from it
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index df8e687d82..e2618c16da 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -137,7 +137,7 @@ UniValue help(const JSONRPCRequest& jsonRequest)
{"command", RPCArg::Type::STR, /* default */ "all commands", "The command to get help on"},
},
RPCResult{
- "\"text\" (string) The help text\n"
+ RPCResult::Type::STR, "", "The help text"
},
RPCExamples{""},
}.ToString()
@@ -153,6 +153,7 @@ UniValue help(const JSONRPCRequest& jsonRequest)
UniValue stop(const JSONRPCRequest& jsonRequest)
{
+ static const std::string RESULT{PACKAGE_NAME " stopping"};
// Accept the deprecated and ignored 'detach' boolean argument
// Also accept the hidden 'wait' integer argument (milliseconds)
// For instance, 'stop 1000' makes the call wait 1 second before returning
@@ -162,16 +163,16 @@ UniValue stop(const JSONRPCRequest& jsonRequest)
RPCHelpMan{"stop",
"\nRequest a graceful shutdown of " PACKAGE_NAME ".",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"},
RPCExamples{""},
}.ToString());
// Event loop will exit after current HTTP requests have been handled, so
// this reply will get back to the client.
StartShutdown();
if (jsonRequest.params[0].isNum()) {
- MilliSleep(jsonRequest.params[0].get_int());
+ UninterruptibleSleep(std::chrono::milliseconds{jsonRequest.params[0].get_int()});
}
- return PACKAGE_NAME " stopping";
+ return RESULT;
}
static UniValue uptime(const JSONRPCRequest& jsonRequest)
@@ -180,7 +181,7 @@ static UniValue uptime(const JSONRPCRequest& jsonRequest)
"\nReturns the total uptime of the server.\n",
{},
RPCResult{
- "ttt (numeric) The number of seconds that the server has been running\n"
+ RPCResult::Type::NUM, "", "The number of seconds that the server has been running"
},
RPCExamples{
HelpExampleCli("uptime", "")
@@ -197,16 +198,18 @@ static UniValue getrpcinfo(const JSONRPCRequest& request)
"\nReturns details of the RPC server.\n",
{},
RPCResult{
- "{\n"
- " \"active_commands\" (array) All active commands\n"
- " [\n"
- " { (object) Information about an active command\n"
- " \"method\" (string) The name of the RPC command \n"
- " \"duration\" (numeric) The running time in microseconds\n"
- " },...\n"
- " ],\n"
- " \"logpath\": \"xxx\" (string) The complete file path to the debug log\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::ARR, "active_commands", "All active commands",
+ {
+ {RPCResult::Type::OBJ, "", "Information about an active command",
+ {
+ {RPCResult::Type::STR, "method", "The name of the RPC command"},
+ {RPCResult::Type::NUM, "duration", "The running time in microseconds"},
+ }},
+ }},
+ {RPCResult::Type::STR, "logpath", "The complete file path to the debug log"},
+ }
},
RPCExamples{
HelpExampleCli("getrpcinfo", "")
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 78586c22f9..860fa198d5 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -13,7 +13,11 @@
#include <tuple>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
+
const std::string UNIX_EPOCH_TIME = "UNIX epoch time";
+const std::string EXAMPLE_ADDRESS[2] = {"bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl", "bc1q02ad21edsxd23d32dfgqqsz4vv4nmtfzuklhy3"};
void RPCTypeCheck(const UniValue& params,
const std::list<UniValueType>& typesExpected,
@@ -115,8 +119,8 @@ std::string HelpExampleCli(const std::string& methodname, const std::string& arg
std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
{
- return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
- "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
+ return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\": \"curltest\", "
+ "\"method\": \"" + methodname + "\", \"params\": [" + args + "]}' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
}
// Converts a hex string to a public key if possible
@@ -292,7 +296,7 @@ UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_s
struct Section {
Section(const std::string& left, const std::string& right)
: m_left{left}, m_right{right} {}
- const std::string m_left;
+ std::string m_left;
const std::string m_right;
};
@@ -311,20 +315,9 @@ struct Sections {
}
/**
- * Serializing RPCArgs depends on the outer type. Only arrays and
- * dictionaries can be nested in json. The top-level outer type is "named
- * arguments", a mix between a dictionary and arrays.
- */
- enum class OuterType {
- ARR,
- OBJ,
- NAMED_ARG, // Only set on first recursion
- };
-
- /**
* Recursive helper to translate an RPCArg into sections
*/
- void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NAMED_ARG)
+ void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NONE)
{
const auto indent = std::string(current_indent, ' ');
const auto indent_next = std::string(current_indent + 2, ' ');
@@ -337,10 +330,10 @@ struct Sections {
case RPCArg::Type::AMOUNT:
case RPCArg::Type::RANGE:
case RPCArg::Type::BOOL: {
- if (outer_type == OuterType::NAMED_ARG) return; // Nothing more to do for non-recursive types on first recursion
+ if (outer_type == OuterType::NONE) return; // Nothing more to do for non-recursive types on first recursion
auto left = indent;
if (arg.m_type_str.size() != 0 && push_name) {
- left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0);
+ left += "\"" + arg.GetName() + "\": " + arg.m_type_str.at(0);
} else {
left += push_name ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false);
}
@@ -350,28 +343,28 @@ struct Sections {
}
case RPCArg::Type::OBJ:
case RPCArg::Type::OBJ_USER_KEYS: {
- const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString();
- PushSection({indent + (push_name ? "\"" + arg.m_name + "\": " : "") + "{", right});
+ const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
+ PushSection({indent + (push_name ? "\"" + arg.GetName() + "\": " : "") + "{", right});
for (const auto& arg_inner : arg.m_inner) {
Push(arg_inner, current_indent + 2, OuterType::OBJ);
}
if (arg.m_type != RPCArg::Type::OBJ) {
PushSection({indent_next + "...", ""});
}
- PushSection({indent + "}" + (outer_type != OuterType::NAMED_ARG ? "," : ""), ""});
+ PushSection({indent + "}" + (outer_type != OuterType::NONE ? "," : ""), ""});
break;
}
case RPCArg::Type::ARR: {
auto left = indent;
- left += push_name ? "\"" + arg.m_name + "\": " : "";
+ left += push_name ? "\"" + arg.GetName() + "\": " : "";
left += "[";
- const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString();
+ const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
PushSection({left, right});
for (const auto& arg_inner : arg.m_inner) {
Push(arg_inner, current_indent + 2, OuterType::ARR);
}
PushSection({indent_next + "...", ""});
- PushSection({indent + "]" + (outer_type != OuterType::NAMED_ARG ? "," : ""), ""});
+ PushSection({indent + "]" + (outer_type != OuterType::NONE ? "," : ""), ""});
break;
}
@@ -429,8 +422,12 @@ RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RP
{
std::set<std::string> named_args;
for (const auto& arg : m_args) {
+ std::vector<std::string> names;
+ boost::split(names, arg.m_names, boost::is_any_of("|"));
// Should have unique named arguments
- CHECK_NONFATAL(named_args.insert(arg.m_name).second);
+ for (const std::string& name : names) {
+ CHECK_NONFATAL(named_args.insert(name).second);
+ }
}
}
@@ -443,7 +440,9 @@ std::string RPCResults::ToDescriptionString() const
} else {
result += "\nResult (" + r.m_cond + "):\n";
}
- result += r.m_result;
+ Sections sections;
+ r.ToSections(sections);
+ result += sections.ToString();
}
return result;
}
@@ -497,7 +496,7 @@ std::string RPCHelpMan::ToString() const
if (i == 0) ret += "\nArguments:\n";
// Push named argument name and description
- sections.m_sections.emplace_back(std::to_string(i + 1) + ". " + arg.m_name, arg.ToDescriptionString());
+ sections.m_sections.emplace_back(::ToString(i + 1) + ". " + arg.GetFirstName(), arg.ToDescriptionString());
sections.m_max_pad = std::max(sections.m_max_pad, sections.m_sections.back().m_left.size());
// Recursively push nested args
@@ -514,6 +513,17 @@ std::string RPCHelpMan::ToString() const
return ret;
}
+std::string RPCArg::GetFirstName() const
+{
+ return m_names.substr(0, m_names.find("|"));
+}
+
+std::string RPCArg::GetName() const
+{
+ CHECK_NONFATAL(std::string::npos == m_names.find("|"));
+ return m_names;
+}
+
bool RPCArg::IsOptional() const
{
if (m_fallback.which() == 1) {
@@ -590,11 +600,106 @@ std::string RPCArg::ToDescriptionString() const
return ret;
}
+void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const int current_indent) const
+{
+ // Indentation
+ const std::string indent(current_indent, ' ');
+ const std::string indent_next(current_indent + 2, ' ');
+
+ // Elements in a JSON structure (dictionary or array) are separated by a comma
+ const std::string maybe_separator{outer_type != OuterType::NONE ? "," : ""};
+
+ // The key name if recursed into an dictionary
+ const std::string maybe_key{
+ outer_type == OuterType::OBJ ?
+ "\"" + this->m_key_name + "\" : " :
+ ""};
+
+ // Format description with type
+ const auto Description = [&](const std::string& type) {
+ return "(" + type + (this->m_optional ? ", optional" : "") + ")" +
+ (this->m_description.empty() ? "" : " " + this->m_description);
+ };
+
+ switch (m_type) {
+ case Type::ELISION: {
+ // If the inner result is empty, use three dots for elision
+ sections.PushSection({indent + "..." + maybe_separator, m_description});
+ return;
+ }
+ case Type::NONE: {
+ sections.PushSection({indent + "null" + maybe_separator, Description("json null")});
+ return;
+ }
+ case Type::STR: {
+ sections.PushSection({indent + maybe_key + "\"str\"" + maybe_separator, Description("string")});
+ return;
+ }
+ case Type::STR_AMOUNT: {
+ sections.PushSection({indent + maybe_key + "n" + maybe_separator, Description("numeric")});
+ return;
+ }
+ case Type::STR_HEX: {
+ sections.PushSection({indent + maybe_key + "\"hex\"" + maybe_separator, Description("string")});
+ return;
+ }
+ case Type::NUM: {
+ sections.PushSection({indent + maybe_key + "n" + maybe_separator, Description("numeric")});
+ return;
+ }
+ case Type::NUM_TIME: {
+ sections.PushSection({indent + maybe_key + "xxx" + maybe_separator, Description("numeric")});
+ return;
+ }
+ case Type::BOOL: {
+ sections.PushSection({indent + maybe_key + "true|false" + maybe_separator, Description("boolean")});
+ return;
+ }
+ case Type::ARR_FIXED:
+ case Type::ARR: {
+ sections.PushSection({indent + maybe_key + "[", Description("json array")});
+ for (const auto& i : m_inner) {
+ i.ToSections(sections, OuterType::ARR, current_indent + 2);
+ }
+ CHECK_NONFATAL(!m_inner.empty());
+ if (m_type == Type::ARR && m_inner.back().m_type != Type::ELISION) {
+ sections.PushSection({indent_next + "...", ""});
+ } else {
+ // Remove final comma, which would be invalid JSON
+ sections.m_sections.back().m_left.pop_back();
+ }
+ sections.PushSection({indent + "]" + maybe_separator, ""});
+ return;
+ }
+ case Type::OBJ_DYN:
+ case Type::OBJ: {
+ sections.PushSection({indent + maybe_key + "{", Description("json object")});
+ for (const auto& i : m_inner) {
+ i.ToSections(sections, OuterType::OBJ, current_indent + 2);
+ }
+ CHECK_NONFATAL(!m_inner.empty());
+ if (m_type == Type::OBJ_DYN && m_inner.back().m_type != Type::ELISION) {
+ // If the dictionary keys are dynamic, use three dots for continuation
+ sections.PushSection({indent_next + "...", ""});
+ } else {
+ // Remove final comma, which would be invalid JSON
+ sections.m_sections.back().m_left.pop_back();
+ }
+ sections.PushSection({indent + "}" + maybe_separator, ""});
+ return;
+ }
+
+ // no default case, so the compiler can warn about missing cases
+ }
+
+ CHECK_NONFATAL(false);
+}
+
std::string RPCArg::ToStringObj(const bool oneline) const
{
std::string res;
res += "\"";
- res += m_name;
+ res += GetFirstName();
if (oneline) {
res += "\":";
} else {
@@ -636,13 +741,13 @@ std::string RPCArg::ToString(const bool oneline) const
switch (m_type) {
case Type::STR_HEX:
case Type::STR: {
- return "\"" + m_name + "\"";
+ return "\"" + GetFirstName() + "\"";
}
case Type::NUM:
case Type::RANGE:
case Type::AMOUNT:
case Type::BOOL: {
- return m_name;
+ return GetFirstName();
}
case Type::OBJ:
case Type::OBJ_USER_KEYS: {
diff --git a/src/rpc/util.h b/src/rpc/util.h
index 065a992a88..53dce2c397 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -28,9 +28,16 @@
*/
extern const std::string UNIX_EPOCH_TIME;
+/**
+ * Example bech32 addresses for the RPCExamples help documentation. They are intentionally
+ * invalid to prevent accidental transactions by users.
+ */
+extern const std::string EXAMPLE_ADDRESS[2];
+
class FillableSigningProvider;
class CPubKey;
class CScript;
+struct Sections;
/** Wrapper for UniValue::VType, which includes typeAny:
* Used to denote don't care type. */
@@ -95,6 +102,16 @@ std::vector<CScript> EvalDescriptorStringOrObject(const UniValue& scanobject, Fl
/** Returns, given services flags, a list of humanly readable (known) network services */
UniValue GetServicesNames(ServiceFlags services);
+/**
+ * Serializing JSON objects depends on the outer type. Only arrays and
+ * dictionaries can be nested in json. The top-level outer type is "NONE".
+ */
+enum class OuterType {
+ ARR,
+ OBJ,
+ NONE, // Only set on first recursion
+};
+
struct RPCArg {
enum class Type {
OBJ,
@@ -125,7 +142,7 @@ struct RPCArg {
OMITTED,
};
using Fallback = boost::variant<Optional, /* default value for optional args */ std::string>;
- const std::string m_name; //!< The name of the arg (can be empty for inner args)
+ const std::string m_names; //!< The name of the arg (can be empty for inner args, can contain multiple aliases separated by | for named request arguments)
const Type m_type;
const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts
const Fallback m_fallback;
@@ -134,43 +151,49 @@ struct RPCArg {
const std::vector<std::string> m_type_str; //!< Should be empty unless it is supposed to override the auto-generated type strings. Vector length is either 0 or 2, m_type_str.at(0) will override the type of the value in a key-value pair, m_type_str.at(1) will override the type in the argument description.
RPCArg(
- const std::string& name,
- const Type& type,
- const Fallback& fallback,
- const std::string& description,
- const std::string& oneline_description = "",
- const std::vector<std::string>& type_str = {})
- : m_name{name},
- m_type{type},
- m_fallback{fallback},
- m_description{description},
- m_oneline_description{oneline_description},
- m_type_str{type_str}
+ const std::string name,
+ const Type type,
+ const Fallback fallback,
+ const std::string description,
+ const std::string oneline_description = "",
+ const std::vector<std::string> type_str = {})
+ : m_names{std::move(name)},
+ m_type{std::move(type)},
+ m_fallback{std::move(fallback)},
+ m_description{std::move(description)},
+ m_oneline_description{std::move(oneline_description)},
+ m_type_str{std::move(type_str)}
{
CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ);
}
RPCArg(
- const std::string& name,
- const Type& type,
- const Fallback& fallback,
- const std::string& description,
- const std::vector<RPCArg>& inner,
- const std::string& oneline_description = "",
- const std::vector<std::string>& type_str = {})
- : m_name{name},
- m_type{type},
- m_inner{inner},
- m_fallback{fallback},
- m_description{description},
- m_oneline_description{oneline_description},
- m_type_str{type_str}
+ const std::string name,
+ const Type type,
+ const Fallback fallback,
+ const std::string description,
+ const std::vector<RPCArg> inner,
+ const std::string oneline_description = "",
+ const std::vector<std::string> type_str = {})
+ : m_names{std::move(name)},
+ m_type{std::move(type)},
+ m_inner{std::move(inner)},
+ m_fallback{std::move(fallback)},
+ m_description{std::move(description)},
+ m_oneline_description{std::move(oneline_description)},
+ m_type_str{std::move(type_str)}
{
CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ);
}
bool IsOptional() const;
+ /** Return the first of all aliases */
+ std::string GetFirstName() const;
+
+ /** Return the name, throws when there are aliases */
+ std::string GetName() const;
+
/**
* Return the type string of the argument.
* Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description).
@@ -189,31 +212,90 @@ struct RPCArg {
};
struct RPCResult {
+ enum class Type {
+ OBJ,
+ ARR,
+ STR,
+ NUM,
+ BOOL,
+ NONE,
+ STR_AMOUNT, //!< Special string to represent a floating point amount
+ STR_HEX, //!< Special string with only hex chars
+ OBJ_DYN, //!< Special dictionary with keys that are not literals
+ ARR_FIXED, //!< Special array that has a fixed number of entries
+ NUM_TIME, //!< Special numeric to denote unix epoch time
+ ELISION, //!< Special type to denote elision (...)
+ };
+
+ const Type m_type;
+ const std::string m_key_name; //!< Only used for dicts
+ const std::vector<RPCResult> m_inner; //!< Only used for arrays or dicts
+ const bool m_optional;
+ const std::string m_description;
const std::string m_cond;
- const std::string m_result;
- explicit RPCResult(std::string result)
- : m_cond{}, m_result{std::move(result)}
+ RPCResult(
+ const std::string cond,
+ const Type type,
+ const std::string m_key_name,
+ const bool optional,
+ const std::string description,
+ const std::vector<RPCResult> inner = {})
+ : m_type{std::move(type)},
+ m_key_name{std::move(m_key_name)},
+ m_inner{std::move(inner)},
+ m_optional{optional},
+ m_description{std::move(description)},
+ m_cond{std::move(cond)}
{
- CHECK_NONFATAL(!m_result.empty());
+ CHECK_NONFATAL(!m_cond.empty());
+ const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN};
+ CHECK_NONFATAL(inner_needed != inner.empty());
}
- RPCResult(std::string cond, std::string result)
- : m_cond{std::move(cond)}, m_result{std::move(result)}
+ RPCResult(
+ const std::string cond,
+ const Type type,
+ const std::string m_key_name,
+ const std::string description,
+ const std::vector<RPCResult> inner = {})
+ : RPCResult{cond, type, m_key_name, false, description, inner} {}
+
+ RPCResult(
+ const Type type,
+ const std::string m_key_name,
+ const bool optional,
+ const std::string description,
+ const std::vector<RPCResult> inner = {})
+ : m_type{std::move(type)},
+ m_key_name{std::move(m_key_name)},
+ m_inner{std::move(inner)},
+ m_optional{optional},
+ m_description{std::move(description)},
+ m_cond{}
{
- CHECK_NONFATAL(!m_cond.empty());
- CHECK_NONFATAL(!m_result.empty());
+ const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN};
+ CHECK_NONFATAL(inner_needed != inner.empty());
}
+
+ RPCResult(
+ const Type type,
+ const std::string m_key_name,
+ const std::string description,
+ const std::vector<RPCResult> inner = {})
+ : RPCResult{type, m_key_name, false, description, inner} {}
+
+ /** Append the sections of the result. */
+ void ToSections(Sections& sections, OuterType outer_type = OuterType::NONE, const int current_indent = 0) const;
+ /** Return the type string of the result when it is in an object (dict). */
+ std::string ToStringObj() const;
+ /** Return the description string, including the result type. */
+ std::string ToDescriptionString() const;
};
struct RPCResults {
const std::vector<RPCResult> m_results;
- RPCResults()
- : m_results{}
- {
- }
-
RPCResults(RPCResult result)
: m_results{{result}}
{
diff --git a/src/scheduler.cpp b/src/scheduler.cpp
index 927a3f3820..c4bd47310b 100644
--- a/src/scheduler.cpp
+++ b/src/scheduler.cpp
@@ -1,37 +1,28 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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 <scheduler.h>
#include <random.h>
-#include <reverselock.h>
#include <assert.h>
#include <utility>
-CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false)
+CScheduler::CScheduler()
{
}
CScheduler::~CScheduler()
{
assert(nThreadsServicingQueue == 0);
+ if (stopWhenEmpty) assert(taskQueue.empty());
}
-#if BOOST_VERSION < 105000
-static boost::system_time toPosixTime(const boost::chrono::system_clock::time_point& t)
-{
- // Creating the posix_time using from_time_t loses sub-second precision. So rather than exporting the time_point to time_t,
- // start with a posix_time at the epoch (0) and add the milliseconds that have passed since then.
- return boost::posix_time::from_time_t(0) + boost::posix_time::milliseconds(boost::chrono::duration_cast<boost::chrono::milliseconds>(t.time_since_epoch()).count());
-}
-#endif
-
void CScheduler::serviceQueue()
{
- boost::unique_lock<boost::mutex> lock(newTaskMutex);
+ WAIT_LOCK(newTaskMutex, lock);
++nThreadsServicingQueue;
// newTaskMutex is locked throughout this loop EXCEPT
@@ -40,7 +31,7 @@ void CScheduler::serviceQueue()
while (!shouldStop()) {
try {
if (!shouldStop() && taskQueue.empty()) {
- reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ REVERSE_LOCK(lock);
}
while (!shouldStop() && taskQueue.empty()) {
// Wait until there is something to do.
@@ -50,21 +41,13 @@ void CScheduler::serviceQueue()
// Wait until either there is a new task, or until
// the time of the first item on the queue:
-// wait_until needs boost 1.50 or later; older versions have timed_wait:
-#if BOOST_VERSION < 105000
- while (!shouldStop() && !taskQueue.empty() &&
- newTaskScheduled.timed_wait(lock, toPosixTime(taskQueue.begin()->first))) {
- // Keep waiting until timeout
- }
-#else
- // Some boost versions have a conflicting overload of wait_until that returns void.
- // Explicitly use a template here to avoid hitting that overload.
while (!shouldStop() && !taskQueue.empty()) {
- boost::chrono::system_clock::time_point timeToWaitFor = taskQueue.begin()->first;
- if (newTaskScheduled.wait_until<>(lock, timeToWaitFor) == boost::cv_status::timeout)
+ std::chrono::system_clock::time_point timeToWaitFor = taskQueue.begin()->first;
+ if (newTaskScheduled.wait_until(lock, timeToWaitFor) == std::cv_status::timeout) {
break; // Exit loop after timeout, it means we reached the time of the event
+ }
}
-#endif
+
// If there are multiple threads, the queue can empty while we're waiting (another
// thread may service the task we were waiting on).
if (shouldStop() || taskQueue.empty())
@@ -76,7 +59,7 @@ void CScheduler::serviceQueue()
{
// Unlock before calling f, so it can reschedule itself or another task
// without deadlocking:
- reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ REVERSE_LOCK(lock);
f();
}
} catch (...) {
@@ -91,7 +74,7 @@ void CScheduler::serviceQueue()
void CScheduler::stop(bool drain)
{
{
- boost::unique_lock<boost::mutex> lock(newTaskMutex);
+ LOCK(newTaskMutex);
if (drain)
stopWhenEmpty = true;
else
@@ -100,35 +83,52 @@ void CScheduler::stop(bool drain)
newTaskScheduled.notify_all();
}
-void CScheduler::schedule(CScheduler::Function f, boost::chrono::system_clock::time_point t)
+void CScheduler::schedule(CScheduler::Function f, std::chrono::system_clock::time_point t)
{
{
- boost::unique_lock<boost::mutex> lock(newTaskMutex);
+ LOCK(newTaskMutex);
taskQueue.insert(std::make_pair(t, f));
}
newTaskScheduled.notify_one();
}
-void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaMilliSeconds)
+void CScheduler::MockForward(std::chrono::seconds delta_seconds)
{
- schedule(f, boost::chrono::system_clock::now() + boost::chrono::milliseconds(deltaMilliSeconds));
+ assert(delta_seconds.count() > 0 && delta_seconds < std::chrono::hours{1});
+
+ {
+ LOCK(newTaskMutex);
+
+ // use temp_queue to maintain updated schedule
+ std::multimap<std::chrono::system_clock::time_point, Function> temp_queue;
+
+ for (const auto& element : taskQueue) {
+ temp_queue.emplace_hint(temp_queue.cend(), element.first - delta_seconds, element.second);
+ }
+
+ // point taskQueue to temp_queue
+ taskQueue = std::move(temp_queue);
+ }
+
+ // notify that the taskQueue needs to be processed
+ newTaskScheduled.notify_one();
}
-static void Repeat(CScheduler* s, CScheduler::Function f, int64_t deltaMilliSeconds)
+static void Repeat(CScheduler& s, CScheduler::Function f, std::chrono::milliseconds delta)
{
f();
- s->scheduleFromNow(std::bind(&Repeat, s, f, deltaMilliSeconds), deltaMilliSeconds);
+ s.scheduleFromNow([=, &s] { Repeat(s, f, delta); }, delta);
}
-void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaMilliSeconds)
+void CScheduler::scheduleEvery(CScheduler::Function f, std::chrono::milliseconds delta)
{
- scheduleFromNow(std::bind(&Repeat, this, f, deltaMilliSeconds), deltaMilliSeconds);
+ scheduleFromNow([=] { Repeat(*this, f, delta); }, delta);
}
-size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first,
- boost::chrono::system_clock::time_point &last) const
+size_t CScheduler::getQueueInfo(std::chrono::system_clock::time_point &first,
+ std::chrono::system_clock::time_point &last) const
{
- boost::unique_lock<boost::mutex> lock(newTaskMutex);
+ LOCK(newTaskMutex);
size_t result = taskQueue.size();
if (!taskQueue.empty()) {
first = taskQueue.begin()->first;
@@ -138,7 +138,7 @@ size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first,
}
bool CScheduler::AreThreadsServicingQueue() const {
- boost::unique_lock<boost::mutex> lock(newTaskMutex);
+ LOCK(newTaskMutex);
return nThreadsServicingQueue;
}
@@ -152,7 +152,7 @@ void SingleThreadedSchedulerClient::MaybeScheduleProcessQueue() {
if (m_are_callbacks_running) return;
if (m_callbacks_pending.empty()) return;
}
- m_pscheduler->schedule(std::bind(&SingleThreadedSchedulerClient::ProcessQueue, this));
+ m_pscheduler->schedule(std::bind(&SingleThreadedSchedulerClient::ProcessQueue, this), std::chrono::system_clock::now());
}
void SingleThreadedSchedulerClient::ProcessQueue() {
diff --git a/src/scheduler.h b/src/scheduler.h
index 7080adf34c..1e64195484 100644
--- a/src/scheduler.h
+++ b/src/scheduler.h
@@ -7,11 +7,12 @@
//
// NOTE:
-// boost::thread / boost::chrono should be ported to std::thread / std::chrono
+// boost::thread should be ported to std::thread
// when we support C++11.
//
-#include <boost/chrono/chrono.hpp>
-#include <boost/thread.hpp>
+#include <condition_variable>
+#include <functional>
+#include <list>
#include <map>
#include <sync.h>
@@ -23,12 +24,12 @@
// Usage:
//
// CScheduler* s = new CScheduler();
-// s->scheduleFromNow(doSomething, 11); // Assuming a: void doSomething() { }
-// s->scheduleFromNow(std::bind(Class::func, this, argument), 3);
+// s->scheduleFromNow(doSomething, std::chrono::milliseconds{11}); // Assuming a: void doSomething() { }
+// s->scheduleFromNow([=] { this->func(argument); }, std::chrono::milliseconds{3});
// boost::thread* t = new boost::thread(std::bind(CScheduler::serviceQueue, s));
//
-// ... then at program shutdown, clean up the thread running serviceQueue:
-// t->interrupt();
+// ... then at program shutdown, make sure to call stop() to clean up the thread(s) running serviceQueue:
+// s->stop();
// t->join();
// delete t;
// delete s; // Must be done after thread is interrupted/joined.
@@ -43,17 +44,28 @@ public:
typedef std::function<void()> Function;
// Call func at/after time t
- void schedule(Function f, boost::chrono::system_clock::time_point t=boost::chrono::system_clock::now());
+ void schedule(Function f, std::chrono::system_clock::time_point t);
- // Convenience method: call f once deltaMilliSeconds from now
- void scheduleFromNow(Function f, int64_t deltaMilliSeconds);
+ /** Call f once after the delta has passed */
+ void scheduleFromNow(Function f, std::chrono::milliseconds delta)
+ {
+ schedule(std::move(f), std::chrono::system_clock::now() + delta);
+ }
- // Another convenience method: call f approximately
- // every deltaMilliSeconds forever, starting deltaMilliSeconds from now.
- // To be more precise: every time f is finished, it
- // is rescheduled to run deltaMilliSeconds later. If you
- // need more accurate scheduling, don't use this method.
- void scheduleEvery(Function f, int64_t deltaMilliSeconds);
+ /**
+ * Repeat f until the scheduler is stopped. First run is after delta has passed once.
+ *
+ * The timing is not exact: Every time f is finished, it is rescheduled to run again after delta. If you need more
+ * accurate scheduling, don't use this method.
+ */
+ void scheduleEvery(Function f, std::chrono::milliseconds delta);
+
+ /**
+ * Mock the scheduler to fast forward in time.
+ * Iterates through items on taskQueue and reschedules them
+ * to be delta_seconds sooner.
+ */
+ void MockForward(std::chrono::seconds delta_seconds);
// To keep things as simple as possible, there is no unschedule.
@@ -68,20 +80,20 @@ public:
// Returns number of tasks waiting to be serviced,
// and first and last task times
- size_t getQueueInfo(boost::chrono::system_clock::time_point &first,
- boost::chrono::system_clock::time_point &last) const;
+ size_t getQueueInfo(std::chrono::system_clock::time_point &first,
+ std::chrono::system_clock::time_point &last) const;
// Returns true if there are threads actively running in serviceQueue()
bool AreThreadsServicingQueue() const;
private:
- std::multimap<boost::chrono::system_clock::time_point, Function> taskQueue;
- boost::condition_variable newTaskScheduled;
- mutable boost::mutex newTaskMutex;
- int nThreadsServicingQueue;
- bool stopRequested;
- bool stopWhenEmpty;
- bool shouldStop() const { return stopRequested || (stopWhenEmpty && taskQueue.empty()); }
+ mutable Mutex newTaskMutex;
+ std::condition_variable newTaskScheduled;
+ std::multimap<std::chrono::system_clock::time_point, Function> taskQueue GUARDED_BY(newTaskMutex);
+ int nThreadsServicingQueue GUARDED_BY(newTaskMutex){0};
+ bool stopRequested GUARDED_BY(newTaskMutex){false};
+ bool stopWhenEmpty GUARDED_BY(newTaskMutex){false};
+ bool shouldStop() const EXCLUSIVE_LOCKS_REQUIRED(newTaskMutex) { return stopRequested || (stopWhenEmpty && taskQueue.empty()); }
};
/**
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 773d6a55c4..5279f40506 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
@@ -150,10 +150,22 @@ typedef std::vector<uint32_t> KeyPath;
/** Interface for public key objects in descriptors. */
struct PubkeyProvider
{
+protected:
+ //! Index of this key expression in the descriptor
+ //! E.g. If this PubkeyProvider is key1 in multi(2, key1, key2, key3), then m_expr_index = 0
+ uint32_t m_expr_index;
+
+public:
+ PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
+
virtual ~PubkeyProvider() = default;
- /** Derive a public key. If key==nullptr, only info is desired. */
- virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const = 0;
+ /** Derive a public key.
+ * read_cache is the cache to read keys from (if not nullptr)
+ * write_cache is the cache to write keys to (if not nullptr)
+ * Caches are not exclusive but this is not tested. Currently we use them exclusively
+ */
+ virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) = 0;
/** Whether this represent multiple public keys at different positions. */
virtual bool IsRange() const = 0;
@@ -182,10 +194,10 @@ class OriginPubkeyProvider final : public PubkeyProvider
}
public:
- OriginPubkeyProvider(KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : m_origin(std::move(info)), m_provider(std::move(provider)) {}
- bool GetPubKey(int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
+ OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)) {}
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
{
- if (!m_provider->GetPubKey(pos, arg, key, info)) return false;
+ if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache)) return false;
std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.fingerprint);
info.path.insert(info.path.begin(), m_origin.path.begin(), m_origin.path.end());
return true;
@@ -212,10 +224,10 @@ class ConstPubkeyProvider final : public PubkeyProvider
CPubKey m_pubkey;
public:
- ConstPubkeyProvider(const CPubKey& pubkey) : m_pubkey(pubkey) {}
- bool GetPubKey(int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
+ ConstPubkeyProvider(uint32_t exp_index, const CPubKey& pubkey) : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
{
- if (key) *key = m_pubkey;
+ key = m_pubkey;
info.path.clear();
CKeyID keyid = m_pubkey.GetID();
std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
@@ -246,22 +258,36 @@ enum class DeriveType {
/** An object representing a parsed extended public key in a descriptor. */
class BIP32PubkeyProvider final : public PubkeyProvider
{
- CExtPubKey m_extkey;
+ // Root xpub, path, and final derivation step type being used, if any
+ CExtPubKey m_root_extkey;
KeyPath m_path;
DeriveType m_derive;
+ // Cache of the parent of the final derived pubkeys.
+ // Primarily useful for situations when no read_cache is provided
+ CExtPubKey m_cached_xpub;
bool GetExtKey(const SigningProvider& arg, CExtKey& ret) const
{
CKey key;
- if (!arg.GetKey(m_extkey.pubkey.GetID(), key)) return false;
- ret.nDepth = m_extkey.nDepth;
- std::copy(m_extkey.vchFingerprint, m_extkey.vchFingerprint + sizeof(ret.vchFingerprint), ret.vchFingerprint);
- ret.nChild = m_extkey.nChild;
- ret.chaincode = m_extkey.chaincode;
+ if (!arg.GetKey(m_root_extkey.pubkey.GetID(), key)) return false;
+ ret.nDepth = m_root_extkey.nDepth;
+ std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint + sizeof(ret.vchFingerprint), ret.vchFingerprint);
+ ret.nChild = m_root_extkey.nChild;
+ ret.chaincode = m_root_extkey.chaincode;
ret.key = key;
return true;
}
+ // Derives the last xprv
+ bool GetDerivedExtKey(const SigningProvider& arg, CExtKey& xprv) const
+ {
+ if (!GetExtKey(arg, xprv)) return false;
+ for (auto entry : m_path) {
+ xprv.Derive(xprv, entry);
+ }
+ return true;
+ }
+
bool IsHardened() const
{
if (m_derive == DeriveType::HARDENED) return true;
@@ -272,37 +298,77 @@ class BIP32PubkeyProvider final : public PubkeyProvider
}
public:
- BIP32PubkeyProvider(const CExtPubKey& extkey, KeyPath path, DeriveType derive) : m_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
+ BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
bool IsRange() const override { return m_derive != DeriveType::NO; }
size_t GetSize() const override { return 33; }
- bool GetPubKey(int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key_out, KeyOriginInfo& final_info_out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
{
- if (key) {
- if (IsHardened()) {
- CKey priv_key;
- if (!GetPrivKey(pos, arg, priv_key)) return false;
- *key = priv_key.GetPubKey();
- } else {
- // TODO: optimize by caching
- CExtPubKey extkey = m_extkey;
- for (auto entry : m_path) {
- extkey.Derive(extkey, entry);
- }
- if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
- assert(m_derive != DeriveType::HARDENED);
- *key = extkey.pubkey;
+ // Info of parent of the to be derived pubkey
+ KeyOriginInfo parent_info;
+ CKeyID keyid = m_root_extkey.pubkey.GetID();
+ std::copy(keyid.begin(), keyid.begin() + sizeof(parent_info.fingerprint), parent_info.fingerprint);
+ parent_info.path = m_path;
+
+ // Info of the derived key itself which is copied out upon successful completion
+ KeyOriginInfo final_info_out_tmp = parent_info;
+ if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.path.push_back((uint32_t)pos);
+ if (m_derive == DeriveType::HARDENED) final_info_out_tmp.path.push_back(((uint32_t)pos) | 0x80000000L);
+
+ // Derive keys or fetch them from cache
+ CExtPubKey final_extkey = m_root_extkey;
+ CExtPubKey parent_extkey = m_root_extkey;
+ bool der = true;
+ if (read_cache) {
+ if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
+ if (m_derive == DeriveType::HARDENED) return false;
+ // Try to get the derivation parent
+ if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey)) return false;
+ final_extkey = parent_extkey;
+ if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
+ }
+ } else if (m_cached_xpub.pubkey.IsValid() && m_derive != DeriveType::HARDENED) {
+ parent_extkey = final_extkey = m_cached_xpub;
+ if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
+ } else if (IsHardened()) {
+ CExtKey xprv;
+ if (!GetDerivedExtKey(arg, xprv)) return false;
+ parent_extkey = xprv.Neuter();
+ if (m_derive == DeriveType::UNHARDENED) der = xprv.Derive(xprv, pos);
+ if (m_derive == DeriveType::HARDENED) der = xprv.Derive(xprv, pos | 0x80000000UL);
+ final_extkey = xprv.Neuter();
+ } else {
+ for (auto entry : m_path) {
+ der = parent_extkey.Derive(parent_extkey, entry);
+ assert(der);
}
+ final_extkey = parent_extkey;
+ if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
+ assert(m_derive != DeriveType::HARDENED);
}
- CKeyID keyid = m_extkey.pubkey.GetID();
- std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
- info.path = m_path;
- if (m_derive == DeriveType::UNHARDENED) info.path.push_back((uint32_t)pos);
- if (m_derive == DeriveType::HARDENED) info.path.push_back(((uint32_t)pos) | 0x80000000L);
+ assert(der);
+
+ final_info_out = final_info_out_tmp;
+ key_out = final_extkey.pubkey;
+
+ // We rely on the consumer to check that m_derive isn't HARDENED as above
+ // But we can't have already cached something in case we read something from the cache
+ // and parent_extkey isn't actually the parent.
+ if (!m_cached_xpub.pubkey.IsValid()) m_cached_xpub = parent_extkey;
+
+ if (write_cache) {
+ // Only cache parent if there is any unhardened derivation
+ if (m_derive != DeriveType::HARDENED) {
+ write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
+ } else if (final_info_out.path.size() > 0) {
+ write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
+ }
+ }
+
return true;
}
std::string ToString() const override
{
- std::string ret = EncodeExtPubKey(m_extkey) + FormatHDKeypath(m_path);
+ std::string ret = EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path);
if (IsRange()) {
ret += "/*";
if (m_derive == DeriveType::HARDENED) ret += '\'';
@@ -323,10 +389,7 @@ public:
bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
{
CExtKey extkey;
- if (!GetExtKey(arg, extkey)) return false;
- for (auto entry : m_path) {
- extkey.Derive(extkey, entry);
- }
+ if (!GetDerivedExtKey(arg, extkey)) return false;
if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
key = extkey.key;
@@ -339,14 +402,15 @@ class DescriptorImpl : public Descriptor
{
//! Public key arguments for this descriptor (size 1 for PK, PKH, WPKH; any size for Multisig).
const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
+ //! The string name of the descriptor function.
+ const std::string m_name;
+
+protected:
//! The sub-descriptor argument (nullptr for everything but SH and WSH).
//! In doc/descriptors.m this is referred to as SCRIPT expressions sh(SCRIPT)
//! and wsh(SCRIPT), and distinct from KEY expressions and ADDR expressions.
const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
- //! The string name of the descriptor function.
- const std::string m_name;
-protected:
//! Return a serialization of anything except pubkey and script arguments, to be prepended to those.
virtual std::string ToStringExtra() const { return ""; }
@@ -364,7 +428,7 @@ protected:
virtual std::vector<CScript> MakeScripts(const std::vector<CPubKey>& pubkeys, const CScript* script, FlatSigningProvider& out) const = 0;
public:
- DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl> script, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_subdescriptor_arg(std::move(script)), m_name(name) {}
+ DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl> script, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_name(name), m_subdescriptor_arg(std::move(script)) {}
bool IsSolvable() const override
{
@@ -424,7 +488,7 @@ public:
return ret;
}
- bool ExpandHelper(int pos, const SigningProvider& arg, Span<const unsigned char>* cache_read, std::vector<CScript>& output_scripts, FlatSigningProvider& out, std::vector<unsigned char>* cache_write) const
+ bool ExpandHelper(int pos, const SigningProvider& arg, const DescriptorCache* read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache) const
{
std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
entries.reserve(m_pubkey_args.size());
@@ -432,27 +496,12 @@ public:
// Construct temporary data in `entries` and `subscripts`, to avoid producing output in case of failure.
for (const auto& p : m_pubkey_args) {
entries.emplace_back();
- // If we have a cache, we don't need GetPubKey to compute the public key.
- // Pass in nullptr to signify only origin info is desired.
- if (!p->GetPubKey(pos, arg, cache_read ? nullptr : &entries.back().first, entries.back().second)) return false;
- if (cache_read) {
- // Cached expanded public key exists, use it.
- if (cache_read->size() == 0) return false;
- bool compressed = ((*cache_read)[0] == 0x02 || (*cache_read)[0] == 0x03) && cache_read->size() >= 33;
- bool uncompressed = ((*cache_read)[0] == 0x04) && cache_read->size() >= 65;
- if (!(compressed || uncompressed)) return false;
- CPubKey pubkey(cache_read->begin(), cache_read->begin() + (compressed ? 33 : 65));
- entries.back().first = pubkey;
- *cache_read = cache_read->subspan(compressed ? 33 : 65);
- }
- if (cache_write) {
- cache_write->insert(cache_write->end(), entries.back().first.begin(), entries.back().first.end());
- }
+ if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache)) return false;
}
std::vector<CScript> subscripts;
if (m_subdescriptor_arg) {
FlatSigningProvider subprovider;
- if (!m_subdescriptor_arg->ExpandHelper(pos, arg, cache_read, subscripts, subprovider, cache_write)) return false;
+ if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache, subscripts, subprovider, write_cache)) return false;
out = Merge(out, subprovider);
}
@@ -476,15 +525,14 @@ public:
return true;
}
- bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, std::vector<unsigned char>* cache = nullptr) const final
+ bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache = nullptr) const final
{
- return ExpandHelper(pos, provider, nullptr, output_scripts, out, cache);
+ return ExpandHelper(pos, provider, nullptr, output_scripts, out, write_cache);
}
- bool ExpandFromCache(int pos, const std::vector<unsigned char>& cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const final
+ bool ExpandFromCache(int pos, const DescriptorCache& read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const final
{
- Span<const unsigned char> span = MakeSpan(cache);
- return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &span, output_scripts, out, nullptr) && span.size() == 0;
+ return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &read_cache, output_scripts, out, nullptr);
}
void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const final
@@ -500,6 +548,8 @@ public:
out = Merge(out, subprovider);
}
}
+
+ Optional<OutputType> GetOutputType() const override { return nullopt; }
};
/** A parsed addr(A) descriptor. */
@@ -512,6 +562,20 @@ protected:
public:
AddressDescriptor(CTxDestination destination) : DescriptorImpl({}, {}, "addr"), m_destination(std::move(destination)) {}
bool IsSolvable() const final { return false; }
+
+ Optional<OutputType> GetOutputType() const override
+ {
+ switch (m_destination.which()) {
+ case 1 /* PKHash */:
+ case 2 /* ScriptHash */: return OutputType::LEGACY;
+ case 3 /* WitnessV0ScriptHash */:
+ case 4 /* WitnessV0KeyHash */:
+ case 5 /* WitnessUnknown */: return OutputType::BECH32;
+ case 0 /* CNoDestination */:
+ default: return nullopt;
+ }
+ }
+ bool IsSingleType() const final { return true; }
};
/** A parsed raw(H) descriptor. */
@@ -524,6 +588,22 @@ protected:
public:
RawDescriptor(CScript script) : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {}
bool IsSolvable() const final { return false; }
+
+ Optional<OutputType> GetOutputType() const override
+ {
+ CTxDestination dest;
+ ExtractDestination(m_script, dest);
+ switch (dest.which()) {
+ case 1 /* PKHash */:
+ case 2 /* ScriptHash */: return OutputType::LEGACY;
+ case 3 /* WitnessV0ScriptHash */:
+ case 4 /* WitnessV0KeyHash */:
+ case 5 /* WitnessUnknown */: return OutputType::BECH32;
+ case 0 /* CNoDestination */:
+ default: return nullopt;
+ }
+ }
+ bool IsSingleType() const final { return true; }
};
/** A parsed pk(P) descriptor. */
@@ -533,6 +613,7 @@ protected:
std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Vector(GetScriptForRawPubKey(keys[0])); }
public:
PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pk") {}
+ bool IsSingleType() const final { return true; }
};
/** A parsed pkh(P) descriptor. */
@@ -547,6 +628,8 @@ protected:
}
public:
PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pkh") {}
+ Optional<OutputType> GetOutputType() const override { return OutputType::LEGACY; }
+ bool IsSingleType() const final { return true; }
};
/** A parsed wpkh(P) descriptor. */
@@ -561,6 +644,8 @@ protected:
}
public:
WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "wpkh") {}
+ Optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
+ bool IsSingleType() const final { return true; }
};
/** A parsed combo(P) descriptor. */
@@ -584,6 +669,7 @@ protected:
}
public:
ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {}
+ bool IsSingleType() const final { return false; }
};
/** A parsed multi(...) or sortedmulti(...) descriptor */
@@ -603,6 +689,7 @@ protected:
}
public:
MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), {}, sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {}
+ bool IsSingleType() const final { return true; }
};
/** A parsed sh(...) descriptor. */
@@ -612,6 +699,14 @@ protected:
std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(ScriptHash(*script))); }
public:
SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {}
+
+ Optional<OutputType> GetOutputType() const override
+ {
+ assert(m_subdescriptor_arg);
+ if (m_subdescriptor_arg->GetOutputType() == OutputType::BECH32) return OutputType::P2SH_SEGWIT;
+ return OutputType::LEGACY;
+ }
+ bool IsSingleType() const final { return true; }
};
/** A parsed wsh(...) descriptor. */
@@ -621,6 +716,8 @@ protected:
std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(WitnessV0ScriptHash(*script))); }
public:
WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {}
+ Optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
+ bool IsSingleType() const final { return true; }
};
////////////////////////////////////////////////////////////////////////////
@@ -657,7 +754,7 @@ NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath&
}
/** Parse a public key that excludes origin information. */
-std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
+std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
{
using namespace spanparsing;
@@ -673,7 +770,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
CPubKey pubkey(data);
if (pubkey.IsFullyValid()) {
if (permit_uncompressed || pubkey.IsCompressed()) {
- return MakeUnique<ConstPubkeyProvider>(pubkey);
+ return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
} else {
error = "Uncompressed keys are not allowed";
return nullptr;
@@ -687,7 +784,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
if (permit_uncompressed || key.IsCompressed()) {
CPubKey pubkey = key.GetPubKey();
out.keys.emplace(pubkey.GetID(), key);
- return MakeUnique<ConstPubkeyProvider>(pubkey);
+ return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
} else {
error = "Uncompressed keys are not allowed";
return nullptr;
@@ -714,11 +811,11 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
extpubkey = extkey.Neuter();
out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key);
}
- return MakeUnique<BIP32PubkeyProvider>(extpubkey, std::move(path), type);
+ return MakeUnique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type);
}
/** Parse a public key including origin information (if enabled). */
-std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
+std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index, const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
{
using namespace spanparsing;
@@ -727,7 +824,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
error = "Multiple ']' characters found for a single pubkey";
return nullptr;
}
- if (origin_split.size() == 1) return ParsePubkeyInner(origin_split[0], permit_uncompressed, out, error);
+ if (origin_split.size() == 1) return ParsePubkeyInner(key_exp_index, origin_split[0], permit_uncompressed, out, error);
if (origin_split[0].size() < 1 || origin_split[0][0] != '[') {
error = strprintf("Key origin start '[ character expected but not found, got '%c' instead", origin_split[0][0]);
return nullptr;
@@ -748,30 +845,30 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
assert(fpr_bytes.size() == 4);
std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
if (!ParseKeyPath(slash_split, info.path, error)) return nullptr;
- auto provider = ParsePubkeyInner(origin_split[1], permit_uncompressed, out, error);
+ auto provider = ParsePubkeyInner(key_exp_index, origin_split[1], permit_uncompressed, out, error);
if (!provider) return nullptr;
- return MakeUnique<OriginPubkeyProvider>(std::move(info), std::move(provider));
+ return MakeUnique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider));
}
/** Parse a script in a particular context. */
-std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
+std::unique_ptr<DescriptorImpl> ParseScript(uint32_t key_exp_index, Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
{
using namespace spanparsing;
auto expr = Expr(sp);
bool sorted_multi = false;
if (Func("pk", expr)) {
- auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out, error);
+ auto pubkey = ParsePubkey(key_exp_index, expr, ctx != ParseScriptContext::P2WSH, out, error);
if (!pubkey) return nullptr;
return MakeUnique<PKDescriptor>(std::move(pubkey));
}
if (Func("pkh", expr)) {
- auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out, error);
+ auto pubkey = ParsePubkey(key_exp_index, expr, ctx != ParseScriptContext::P2WSH, out, error);
if (!pubkey) return nullptr;
return MakeUnique<PKHDescriptor>(std::move(pubkey));
}
if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
- auto pubkey = ParsePubkey(expr, true, out, error);
+ auto pubkey = ParsePubkey(key_exp_index, expr, true, out, error);
if (!pubkey) return nullptr;
return MakeUnique<ComboDescriptor>(std::move(pubkey));
} else if (ctx != ParseScriptContext::TOP && Func("combo", expr)) {
@@ -793,10 +890,11 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
return nullptr;
}
auto arg = Expr(expr);
- auto pk = ParsePubkey(arg, ctx != ParseScriptContext::P2WSH, out, error);
+ auto pk = ParsePubkey(key_exp_index, arg, ctx != ParseScriptContext::P2WSH, out, error);
if (!pk) return nullptr;
script_size += pk->GetSize() + 1;
providers.emplace_back(std::move(pk));
+ key_exp_index++;
}
if (providers.size() < 1 || providers.size() > 16) {
error = strprintf("Cannot have %u keys in multisig; must have between 1 and 16 keys, inclusive", providers.size());
@@ -823,7 +921,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
return MakeUnique<MultisigDescriptor>(thres, std::move(providers), sorted_multi);
}
if (ctx != ParseScriptContext::P2WSH && Func("wpkh", expr)) {
- auto pubkey = ParsePubkey(expr, false, out, error);
+ auto pubkey = ParsePubkey(key_exp_index, expr, false, out, error);
if (!pubkey) return nullptr;
return MakeUnique<WPKHDescriptor>(std::move(pubkey));
} else if (ctx == ParseScriptContext::P2WSH && Func("wpkh", expr)) {
@@ -831,7 +929,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
return nullptr;
}
if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
- auto desc = ParseScript(expr, ParseScriptContext::P2SH, out, error);
+ auto desc = ParseScript(key_exp_index, expr, ParseScriptContext::P2SH, out, error);
if (!desc || expr.size()) return nullptr;
return MakeUnique<SHDescriptor>(std::move(desc));
} else if (ctx != ParseScriptContext::TOP && Func("sh", expr)) {
@@ -839,7 +937,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
return nullptr;
}
if (ctx != ParseScriptContext::P2WSH && Func("wsh", expr)) {
- auto desc = ParseScript(expr, ParseScriptContext::P2WSH, out, error);
+ auto desc = ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH, out, error);
if (!desc || expr.size()) return nullptr;
return MakeUnique<WSHDescriptor>(std::move(desc));
} else if (ctx == ParseScriptContext::P2WSH && Func("wsh", expr)) {
@@ -876,10 +974,10 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
{
- std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(pubkey);
+ std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(0, pubkey);
KeyOriginInfo info;
if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
- return MakeUnique<OriginPubkeyProvider>(std::move(info), std::move(key_provider));
+ return MakeUnique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
}
return key_provider;
}
@@ -991,7 +1089,7 @@ std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProv
{
Span<const char> sp(descriptor.data(), descriptor.size());
if (!CheckChecksum(sp, require_checksum, error)) return nullptr;
- auto ret = ParseScript(sp, ParseScriptContext::TOP, out, error);
+ auto ret = ParseScript(0, sp, ParseScriptContext::TOP, out, error);
if (sp.size() == 0 && ret) return std::unique_ptr<Descriptor>(std::move(ret));
return nullptr;
}
@@ -1009,3 +1107,42 @@ std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const Signing
{
return InferScript(script, ParseScriptContext::TOP, provider);
}
+
+void DescriptorCache::CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub)
+{
+ m_parent_xpubs[key_exp_pos] = xpub;
+}
+
+void DescriptorCache::CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey& xpub)
+{
+ auto& xpubs = m_derived_xpubs[key_exp_pos];
+ xpubs[der_index] = xpub;
+}
+
+bool DescriptorCache::GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const
+{
+ const auto& it = m_parent_xpubs.find(key_exp_pos);
+ if (it == m_parent_xpubs.end()) return false;
+ xpub = it->second;
+ return true;
+}
+
+bool DescriptorCache::GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey& xpub) const
+{
+ const auto& key_exp_it = m_derived_xpubs.find(key_exp_pos);
+ if (key_exp_it == m_derived_xpubs.end()) return false;
+ const auto& der_it = key_exp_it->second.find(der_index);
+ if (der_it == key_exp_it->second.end()) return false;
+ xpub = der_it->second;
+ return true;
+}
+
+const ExtPubKeyMap DescriptorCache::GetCachedParentExtPubKeys() const
+{
+ return m_parent_xpubs;
+}
+
+const std::unordered_map<uint32_t, ExtPubKeyMap> DescriptorCache::GetCachedDerivedExtPubKeys() const
+{
+ return m_derived_xpubs;
+}
diff --git a/src/script/descriptor.h b/src/script/descriptor.h
index a5a41d78dd..17b43e7c81 100644
--- a/src/script/descriptor.h
+++ b/src/script/descriptor.h
@@ -1,16 +1,61 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
#ifndef BITCOIN_SCRIPT_DESCRIPTOR_H
#define BITCOIN_SCRIPT_DESCRIPTOR_H
+#include <optional.h>
+#include <outputtype.h>
#include <script/script.h>
#include <script/sign.h>
#include <script/signingprovider.h>
#include <vector>
+using ExtPubKeyMap = std::unordered_map<uint32_t, CExtPubKey>;
+
+/** Cache for single descriptor's derived extended pubkeys */
+class DescriptorCache {
+private:
+ /** Map key expression index -> map of (key derivation index -> xpub) */
+ std::unordered_map<uint32_t, ExtPubKeyMap> m_derived_xpubs;
+ /** Map key expression index -> parent xpub */
+ ExtPubKeyMap m_parent_xpubs;
+
+public:
+ /** Cache a parent xpub
+ *
+ * @param[in] key_exp_pos Position of the key expression within the descriptor
+ * @param[in] xpub The CExtPubKey to cache
+ */
+ void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub);
+ /** Retrieve a cached parent xpub
+ *
+ * @param[in] key_exp_pos Position of the key expression within the descriptor
+ * @param[in] xpub The CExtPubKey to get from cache
+ */
+ bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const;
+ /** Cache an xpub derived at an index
+ *
+ * @param[in] key_exp_pos Position of the key expression within the descriptor
+ * @param[in] der_index Derivation index of the xpub
+ * @param[in] xpub The CExtPubKey to cache
+ */
+ void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey& xpub);
+ /** Retrieve a cached xpub derived at an index
+ *
+ * @param[in] key_exp_pos Position of the key expression within the descriptor
+ * @param[in] der_index Derivation index of the xpub
+ * @param[in] xpub The CExtPubKey to get from cache
+ */
+ bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey& xpub) const;
+
+ /** Retrieve all cached parent xpubs */
+ const ExtPubKeyMap GetCachedParentExtPubKeys() const;
+ /** Retrieve all cached derived xpubs */
+ const std::unordered_map<uint32_t, ExtPubKeyMap> GetCachedDerivedExtPubKeys() const;
+};
/** \brief Interface for parsed descriptor objects.
*
@@ -42,6 +87,9 @@ struct Descriptor {
/** Convert the descriptor back to a string, undoing parsing. */
virtual std::string ToString() const = 0;
+ /** Whether this descriptor will return one scriptPubKey or multiple (aka is or is not combo) */
+ virtual bool IsSingleType() const = 0;
+
/** Convert the descriptor to a private string. This fails if the provided provider does not have the relevant private keys. */
virtual bool ToPrivateString(const SigningProvider& provider, std::string& out) const = 0;
@@ -51,18 +99,18 @@ struct Descriptor {
* @param[in] provider The provider to query for private keys in case of hardened derivation.
* @param[out] output_scripts The expanded scriptPubKeys.
* @param[out] out Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`).
- * @param[out] cache Cache data necessary to evaluate the descriptor at this point without access to private keys.
+ * @param[out] write_cache Cache data necessary to evaluate the descriptor at this point without access to private keys.
*/
- virtual bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, std::vector<unsigned char>* cache = nullptr) const = 0;
+ virtual bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache = nullptr) const = 0;
/** Expand a descriptor at a specified position using cached expansion data.
*
* @param[in] pos The position at which to expand the descriptor. If IsRange() is false, this is ignored.
- * @param[in] cache Cached expansion data.
+ * @param[in] read_cache Cached expansion data.
* @param[out] output_scripts The expanded scriptPubKeys.
* @param[out] out Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`).
*/
- virtual bool ExpandFromCache(int pos, const std::vector<unsigned char>& cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0;
+ virtual bool ExpandFromCache(int pos, const DescriptorCache& read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0;
/** Expand the private key for a descriptor at a specified position, if possible.
*
@@ -71,6 +119,9 @@ struct Descriptor {
* @param[out] out Any private keys available for the specified `pos`.
*/
virtual void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const = 0;
+
+ /** @return The OutputType of the scriptPubKey(s) produced by this descriptor. Or nullopt if indeterminate (multiple or none) */
+ virtual Optional<OutputType> GetOutputType() const = 0;
};
/** Parse a `descriptor` string. Included private keys are put in `out`.
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index d0865d2793..23d5b72a5c 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -278,6 +278,99 @@ int FindAndDelete(CScript& script, const CScript& b)
return nFound;
}
+namespace {
+/** A data type to abstract out the condition stack during script execution.
+ *
+ * Conceptually it acts like a vector of booleans, one for each level of nested
+ * IF/THEN/ELSE, indicating whether we're in the active or inactive branch of
+ * each.
+ *
+ * The elements on the stack cannot be observed individually; we only need to
+ * expose whether the stack is empty and whether or not any false values are
+ * present at all. To implement OP_ELSE, a toggle_top modifier is added, which
+ * flips the last value without returning it.
+ *
+ * This uses an optimized implementation that does not materialize the
+ * actual stack. Instead, it just stores the size of the would-be stack,
+ * and the position of the first false value in it.
+ */
+class ConditionStack {
+private:
+ //! A constant for m_first_false_pos to indicate there are no falses.
+ static constexpr uint32_t NO_FALSE = std::numeric_limits<uint32_t>::max();
+
+ //! The size of the implied stack.
+ uint32_t m_stack_size = 0;
+ //! The position of the first false value on the implied stack, or NO_FALSE if all true.
+ uint32_t m_first_false_pos = NO_FALSE;
+
+public:
+ bool empty() { return m_stack_size == 0; }
+ bool all_true() { return m_first_false_pos == NO_FALSE; }
+ void push_back(bool f)
+ {
+ if (m_first_false_pos == NO_FALSE && !f) {
+ // The stack consists of all true values, and a false is added.
+ // The first false value will appear at the current size.
+ m_first_false_pos = m_stack_size;
+ }
+ ++m_stack_size;
+ }
+ void pop_back()
+ {
+ assert(m_stack_size > 0);
+ --m_stack_size;
+ if (m_first_false_pos == m_stack_size) {
+ // When popping off the first false value, everything becomes true.
+ m_first_false_pos = NO_FALSE;
+ }
+ }
+ void toggle_top()
+ {
+ assert(m_stack_size > 0);
+ if (m_first_false_pos == NO_FALSE) {
+ // The current stack is all true values; the first false will be the top.
+ m_first_false_pos = m_stack_size - 1;
+ } else if (m_first_false_pos == m_stack_size - 1) {
+ // The top is the first false value; toggling it will make everything true.
+ m_first_false_pos = NO_FALSE;
+ } else {
+ // There is a false value, but not on top. No action is needed as toggling
+ // anything but the first false value is unobservable.
+ }
+ }
+};
+}
+
+/** Helper for OP_CHECKSIG and OP_CHECKSIGVERIFY
+ *
+ * A return value of false means the script fails entirely. When true is returned, the
+ * fSuccess variable indicates whether the signature check itself succeeded.
+ */
+static bool EvalChecksig(const valtype& vchSig, const valtype& vchPubKey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& fSuccess)
+{
+ // Subset of script starting at the most recent codeseparator
+ CScript scriptCode(pbegincodehash, pend);
+
+ // Drop the signature in pre-segwit scripts but not segwit scripts
+ if (sigversion == SigVersion::BASE) {
+ int found = FindAndDelete(scriptCode, CScript() << vchSig);
+ if (found > 0 && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))
+ return set_error(serror, SCRIPT_ERR_SIG_FINDANDDELETE);
+ }
+
+ if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
+ //serror is set
+ return false;
+ }
+ fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
+
+ if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size())
+ return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
+
+ return true;
+}
+
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
{
static const CScriptNum bnZero(0);
@@ -293,7 +386,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
CScript::const_iterator pbegincodehash = script.begin();
opcodetype opcode;
valtype vchPushValue;
- std::vector<bool> vfExec;
+ ConditionStack vfExec;
std::vector<valtype> altstack;
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
if (script.size() > MAX_SCRIPT_SIZE)
@@ -305,7 +398,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
{
while (pc < pend)
{
- bool fExec = !count(vfExec.begin(), vfExec.end(), false);
+ bool fExec = vfExec.all_true();
//
// Read instruction
@@ -494,7 +587,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
{
if (vfExec.empty())
return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
- vfExec.back() = !vfExec.back();
+ vfExec.toggle_top();
}
break;
@@ -921,25 +1014,8 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
valtype& vchSig = stacktop(-2);
valtype& vchPubKey = stacktop(-1);
- // Subset of script starting at the most recent codeseparator
- CScript scriptCode(pbegincodehash, pend);
-
- // Drop the signature in pre-segwit scripts but not segwit scripts
- if (sigversion == SigVersion::BASE) {
- int found = FindAndDelete(scriptCode, CScript() << vchSig);
- if (found > 0 && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))
- return set_error(serror, SCRIPT_ERR_SIG_FINDANDDELETE);
- }
-
- if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
- //serror is set
- return false;
- }
- bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
-
- if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size())
- return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
-
+ bool fSuccess = true;
+ if (!EvalChecksig(vchSig, vchPubKey, pbegincodehash, pend, flags, checker, sigversion, serror, fSuccess)) return false;
popstack(stack);
popstack(stack);
stack.push_back(fSuccess ? vchTrue : vchFalse);
@@ -1215,18 +1291,29 @@ uint256 GetOutputsHash(const T& txTo)
} // namespace
template <class T>
-PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
+void PrecomputedTransactionData::Init(const T& txTo)
{
+ assert(!m_ready);
+
// Cache is calculated only for transactions with witness
if (txTo.HasWitness()) {
hashPrevouts = GetPrevoutHash(txTo);
hashSequence = GetSequenceHash(txTo);
hashOutputs = GetOutputsHash(txTo);
- ready = true;
}
+
+ m_ready = true;
+}
+
+template <class T>
+PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
+{
+ Init(txTo);
}
// explicit instantiation
+template void PrecomputedTransactionData::Init(const CTransaction& txTo);
+template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo);
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
@@ -1239,7 +1326,7 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
uint256 hashPrevouts;
uint256 hashSequence;
uint256 hashOutputs;
- const bool cacheready = cache && cache->ready;
+ const bool cacheready = cache && cache->m_ready;
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
hashPrevouts = cacheready ? cache->hashPrevouts : GetPrevoutHash(txTo);
@@ -1414,57 +1501,61 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
template class GenericTransactionSignatureChecker<CTransaction>;
template class GenericTransactionSignatureChecker<CMutableTransaction>;
+static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CScript& scriptPubKey, unsigned int flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptError* serror)
+{
+ std::vector<valtype> stack{stack_span.begin(), stack_span.end()};
+
+ // Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
+ for (const valtype& elem : stack) {
+ if (elem.size() > MAX_SCRIPT_ELEMENT_SIZE) return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
+ }
+
+ // Run the script interpreter.
+ if (!EvalScript(stack, scriptPubKey, flags, checker, sigversion, serror)) return false;
+
+ // Scripts inside witness implicitly require cleanstack behaviour
+ if (stack.size() != 1) return set_error(serror, SCRIPT_ERR_CLEANSTACK);
+ if (!CastToBool(stack.back())) return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ return true;
+}
+
static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
- std::vector<std::vector<unsigned char> > stack;
CScript scriptPubKey;
+ Span<const valtype> stack = MakeSpan(witness.stack);
if (witversion == 0) {
if (program.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
// Version 0 segregated witness program: SHA256(CScript) inside the program, CScript + inputs in witness
- if (witness.stack.size() == 0) {
+ if (stack.size() == 0) {
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY);
}
- scriptPubKey = CScript(witness.stack.back().begin(), witness.stack.back().end());
- stack = std::vector<std::vector<unsigned char> >(witness.stack.begin(), witness.stack.end() - 1);
+ const valtype& script_bytes = SpanPopBack(stack);
+ scriptPubKey = CScript(script_bytes.begin(), script_bytes.end());
uint256 hashScriptPubKey;
CSHA256().Write(&scriptPubKey[0], scriptPubKey.size()).Finalize(hashScriptPubKey.begin());
if (memcmp(hashScriptPubKey.begin(), program.data(), 32)) {
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
}
+ return ExecuteWitnessScript(stack, scriptPubKey, flags, SigVersion::WITNESS_V0, checker, serror);
} else if (program.size() == WITNESS_V0_KEYHASH_SIZE) {
// Special case for pay-to-pubkeyhash; signature + pubkey in witness
- if (witness.stack.size() != 2) {
+ if (stack.size() != 2) {
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); // 2 items in witness
}
scriptPubKey << OP_DUP << OP_HASH160 << program << OP_EQUALVERIFY << OP_CHECKSIG;
- stack = witness.stack;
+ return ExecuteWitnessScript(stack, scriptPubKey, flags, SigVersion::WITNESS_V0, checker, serror);
} else {
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH);
}
- } else if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
- return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
} else {
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
+ }
// Higher version witness scripts return true for future softfork compatibility
- return set_success(serror);
- }
-
- // Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
- for (unsigned int i = 0; i < stack.size(); i++) {
- if (stack.at(i).size() > MAX_SCRIPT_ELEMENT_SIZE)
- return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
- }
-
- if (!EvalScript(stack, scriptPubKey, flags, checker, SigVersion::WITNESS_V0, serror)) {
- return false;
+ return true;
}
-
- // Scripts inside witness implicitly require cleanstack behaviour
- if (stack.size() != 1)
- return set_error(serror, SCRIPT_ERR_CLEANSTACK);
- if (!CastToBool(stack.back()))
- return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
- return true;
+ // There is intentionally no return statement here, to be able to use "control reaches end of non-void function" warnings to detect gaps in the logic above.
}
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 2b104a608c..71f2436369 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -121,7 +121,12 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
struct PrecomputedTransactionData
{
uint256 hashPrevouts, hashSequence, hashOutputs;
- bool ready = false;
+ bool m_ready = false;
+
+ PrecomputedTransactionData() = default;
+
+ template <class T>
+ void Init(const T& tx);
template <class T>
explicit PrecomputedTransactionData(const T& tx);
diff --git a/src/script/script.h b/src/script/script.h
index 7aaa10b60b..773ffbb985 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -329,7 +329,7 @@ public:
std::vector<unsigned char> result;
const bool neg = value < 0;
- uint64_t absvalue = neg ? -value : value;
+ uint64_t absvalue = neg ? ~static_cast<uint64_t>(value) + 1 : static_cast<uint64_t>(value);
while(absvalue)
{
@@ -419,28 +419,15 @@ public:
READWRITEAS(CScriptBase, *this);
}
- CScript& operator+=(const CScript& b)
- {
- reserve(size() + b.size());
- insert(end(), b.begin(), b.end());
- return *this;
- }
-
- friend CScript operator+(const CScript& a, const CScript& b)
- {
- CScript ret = a;
- ret += b;
- return ret;
- }
-
- CScript(int64_t b) { operator<<(b); }
-
+ explicit CScript(int64_t b) { operator<<(b); }
explicit CScript(opcodetype b) { operator<<(b); }
explicit CScript(const CScriptNum& b) { operator<<(b); }
// delete non-existent constructor to defend against future introduction
// e.g. via prevector
explicit CScript(const std::vector<unsigned char>& b) = delete;
+ /** Delete non-existent operator to defend against future introduction */
+ CScript& operator<<(const CScript& b) = delete;
CScript& operator<<(int64_t b) { return push_int64(b); }
@@ -487,15 +474,6 @@ public:
return *this;
}
- CScript& operator<<(const CScript& b)
- {
- // I'm not sure if this should push the script or concatenate scripts.
- // If there's ever a use for pushing a script onto a script, delete this member fn
- assert(!"Warning: Pushing a CScript onto a CScript with << is probably not intended, use + to concatenate!");
- return *this;
- }
-
-
bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const
{
return GetScriptOp(pc, end(), opcodeRet, &vchRet);
@@ -506,7 +484,6 @@ public:
return GetScriptOp(pc, end(), opcodeRet, nullptr);
}
-
/** Encode/decode small integers: */
static int DecodeOP_N(opcodetype opcode)
{
diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp
index 9d7deffc78..57e8fee539 100644
--- a/src/script/script_error.cpp
+++ b/src/script/script_error.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -58,7 +58,7 @@ const char* ScriptErrorString(const ScriptError serror)
case SCRIPT_ERR_MINIMALDATA:
return "Data push larger than necessary";
case SCRIPT_ERR_SIG_PUSHONLY:
- return "Only non-push operators allowed in signatures";
+ return "Only push operators allowed in signatures";
case SCRIPT_ERR_SIG_HIGH_S:
return "Non-canonical signature: S value is unnecessarily high";
case SCRIPT_ERR_SIG_NULLDUMMY:
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 58eae3ce96..1e00afcf89 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -465,3 +465,54 @@ bool IsSegWitOutput(const SigningProvider& provider, const CScript& script)
}
return false;
}
+
+bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, int nHashType, std::map<int, std::string>& input_errors)
+{
+ bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
+
+ // Use CTransaction for the constant parts of the
+ // transaction to avoid rehashing.
+ const CTransaction txConst(mtx);
+ // Sign what we can:
+ for (unsigned int i = 0; i < mtx.vin.size(); i++) {
+ CTxIn& txin = mtx.vin[i];
+ auto coin = coins.find(txin.prevout);
+ if (coin == coins.end() || coin->second.IsSpent()) {
+ input_errors[i] = "Input not found or already spent";
+ continue;
+ }
+ const CScript& prevPubKey = coin->second.out.scriptPubKey;
+ const CAmount& amount = coin->second.out.nValue;
+
+ SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
+ // Only sign SIGHASH_SINGLE if there's a corresponding output:
+ if (!fHashSingle || (i < mtx.vout.size())) {
+ ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
+ }
+
+ UpdateInput(txin, sigdata);
+
+ // amount must be specified for valid segwit signature
+ if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) {
+ input_errors[i] = "Missing amount";
+ continue;
+ }
+
+ ScriptError serror = SCRIPT_ERR_OK;
+ if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
+ if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
+ // Unable to sign input and verification failed (possible attempt to partially sign).
+ input_errors[i] = "Unable to sign input, invalid stack size (possibly missing key)";
+ } else if (serror == SCRIPT_ERR_SIG_NULLFAIL) {
+ // Verification failed (possibly due to insufficient signatures).
+ input_errors[i] = "CHECK(MULTI)SIG failing with non-zero signature (possibly need more signatures)";
+ } else {
+ input_errors[i] = ScriptErrorString(serror);
+ }
+ } else {
+ // If this input succeeds, make sure there is no error set for it
+ input_errors.erase(i);
+ }
+ }
+ return input_errors.empty();
+}
diff --git a/src/script/sign.h b/src/script/sign.h
index 033c9ba19e..b77d26c0d7 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -1,11 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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_SCRIPT_SIGN_H
#define BITCOIN_SCRIPT_SIGN_H
+#include <coins.h>
#include <hash.h>
#include <pubkey.h>
#include <script/interpreter.h>
@@ -168,4 +169,7 @@ bool IsSolvable(const SigningProvider& provider, const CScript& script);
/** Check whether a scriptPubKey is known to be segwit. */
bool IsSegWitOutput(const SigningProvider& provider, const CScript& script);
+/** Sign the CMutableTransaction */
+bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* provider, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors);
+
#endif // BITCOIN_SCRIPT_SIGN_H
diff --git a/src/script/signingprovider.h b/src/script/signingprovider.h
index 6ad20480a7..76f31d2f6f 100644
--- a/src/script/signingprovider.h
+++ b/src/script/signingprovider.h
@@ -66,7 +66,53 @@ protected:
using KeyMap = std::map<CKeyID, CKey>;
using ScriptMap = std::map<CScriptID, CScript>;
+ /**
+ * Map of key id to unencrypted private keys known by the signing provider.
+ * Map may be empty if the provider has another source of keys, like an
+ * encrypted store.
+ */
KeyMap mapKeys GUARDED_BY(cs_KeyStore);
+
+ /**
+ * Map of script id to scripts known by the signing provider.
+ *
+ * This map originally just held P2SH redeemScripts, and was used by wallet
+ * code to look up script ids referenced in "OP_HASH160 <script id>
+ * OP_EQUAL" P2SH outputs. Later in 605e8473a7d it was extended to hold
+ * P2WSH witnessScripts as well, and used to look up nested scripts
+ * referenced in "OP_0 <script hash>" P2WSH outputs. Later in commits
+ * f4691ab3a9d and 248f3a76a82, it was extended once again to hold segwit
+ * "OP_0 <key or script hash>" scriptPubKeys, in order to give the wallet a
+ * way to distinguish between segwit outputs that it generated addresses for
+ * and wanted to receive payments from, and segwit outputs that it never
+ * generated addresses for, but it could spend just because of having keys.
+ * (Before segwit activation it was also important to not treat segwit
+ * outputs to arbitrary wallet keys as payments, because these could be
+ * spent by anyone without even needing to sign with the keys.)
+ *
+ * Some of the scripts stored in mapScripts are memory-only and
+ * intentionally not saved to disk. Specifically, scripts added by
+ * ImplicitlyLearnRelatedKeyScripts(pubkey) calls are not written to disk so
+ * future wallet code can have flexibility to be more selective about what
+ * transaction outputs it recognizes as payments, instead of having to treat
+ * all outputs spending to keys it knows as payments. By contrast,
+ * mapScripts entries added by AddCScript(script),
+ * LearnRelatedScripts(pubkey, type), and LearnAllRelatedScripts(pubkey)
+ * calls are saved because they are all intentionally used to receive
+ * payments.
+ *
+ * The FillableSigningProvider::mapScripts script map should not be confused
+ * with LegacyScriptPubKeyMan::setWatchOnly script set. The two collections
+ * can hold the same scripts, but they serve different purposes. The
+ * setWatchOnly script set is intended to expand the set of outputs the
+ * wallet considers payments. Every output with a script it contains is
+ * considered to belong to the wallet, regardless of whether the script is
+ * solvable or signable. By contrast, the scripts in mapScripts are only
+ * used for solving, and to restrict which outputs are considered payments
+ * by the wallet. An output with a script in mapScripts, unlike
+ * setWatchOnly, is not automatically considered to belong to the wallet if
+ * it can't be solved and signed for.
+ */
ScriptMap mapScripts GUARDED_BY(cs_KeyStore);
void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
diff --git a/src/serialize.h b/src/serialize.h
index 7fa669ebdb..fe53eeed31 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -9,6 +9,7 @@
#include <compat/endian.h>
#include <algorithm>
+#include <cstring>
#include <ios>
#include <limits>
#include <map>
@@ -25,6 +26,9 @@
static const unsigned int MAX_SIZE = 0x02000000;
+/** Maximum amount of memory (in bytes) to allocate at once when deserializing vectors. */
+static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
+
/**
* Dummy data type to identify deserializing constructors.
*
@@ -136,27 +140,31 @@ template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
}
inline uint64_t ser_double_to_uint64(double x)
{
- union { double x; uint64_t y; } tmp;
- tmp.x = x;
- return tmp.y;
+ uint64_t tmp;
+ std::memcpy(&tmp, &x, sizeof(x));
+ static_assert(sizeof(tmp) == sizeof(x), "double and uint64_t assumed to have the same size");
+ return tmp;
}
inline uint32_t ser_float_to_uint32(float x)
{
- union { float x; uint32_t y; } tmp;
- tmp.x = x;
- return tmp.y;
+ uint32_t tmp;
+ std::memcpy(&tmp, &x, sizeof(x));
+ static_assert(sizeof(tmp) == sizeof(x), "float and uint32_t assumed to have the same size");
+ return tmp;
}
inline double ser_uint64_to_double(uint64_t y)
{
- union { double x; uint64_t y; } tmp;
- tmp.y = y;
- return tmp.x;
+ double tmp;
+ std::memcpy(&tmp, &y, sizeof(y));
+ static_assert(sizeof(tmp) == sizeof(y), "double and uint64_t assumed to have the same size");
+ return tmp;
}
inline float ser_uint32_to_float(uint32_t y)
{
- union { float x; uint32_t y; } tmp;
- tmp.y = y;
- return tmp.x;
+ float tmp;
+ std::memcpy(&tmp, &y, sizeof(y));
+ static_assert(sizeof(tmp) == sizeof(y), "float and uint32_t assumed to have the same size");
+ return tmp;
}
@@ -490,12 +498,13 @@ public:
template<typename Formatter, typename T>
static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }
-#define VARINT(obj, ...) Using<VarIntFormatter<__VA_ARGS__>>(obj)
-#define COMPACTSIZE(obj) CCompactSize(REF(obj))
+#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
+#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
+#define COMPACTSIZE(obj) Using<CompactSizeFormatter>(obj)
#define LIMITED_STRING(obj,n) LimitedString< n >(REF(obj))
/** Serialization wrapper class for integers in VarInt format. */
-template<VarIntMode Mode=VarIntMode::DEFAULT>
+template<VarIntMode Mode>
struct VarIntFormatter
{
template<typename Stream, typename I> void Ser(Stream &s, I v)
@@ -509,6 +518,28 @@ struct VarIntFormatter
}
};
+template<int Bytes>
+struct CustomUintFormatter
+{
+ static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range");
+ static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
+
+ template <typename Stream, typename I> void Ser(Stream& s, I v)
+ {
+ if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
+ uint64_t raw = htole64(v);
+ s.write((const char*)&raw, Bytes);
+ }
+
+ template <typename Stream, typename I> void Unser(Stream& s, I& v)
+ {
+ static_assert(std::numeric_limits<I>::max() >= MAX && std::numeric_limits<I>::min() <= 0, "CustomUintFormatter type too small");
+ uint64_t raw = 0;
+ s.read((char*)&raw, Bytes);
+ v = le64toh(raw);
+ }
+};
+
/** Serialization wrapper class for big-endian integers.
*
* Use this wrapper around integer types that are stored in memory in native
@@ -543,21 +574,26 @@ public:
}
};
-class CCompactSize
+/** Formatter for integers in CompactSize format. */
+struct CompactSizeFormatter
{
-protected:
- uint64_t &n;
-public:
- explicit CCompactSize(uint64_t& nIn) : n(nIn) { }
-
- template<typename Stream>
- void Serialize(Stream &s) const {
- WriteCompactSize<Stream>(s, n);
+ template<typename Stream, typename I>
+ void Unser(Stream& s, I& v)
+ {
+ uint64_t n = ReadCompactSize<Stream>(s);
+ if (n < std::numeric_limits<I>::min() || n > std::numeric_limits<I>::max()) {
+ throw std::ios_base::failure("CompactSize exceeds limit of type");
+ }
+ v = n;
}
- template<typename Stream>
- void Unserialize(Stream& s) {
- n = ReadCompactSize<Stream>(s);
+ template<typename Stream, typename I>
+ void Ser(Stream& s, I v)
+ {
+ static_assert(std::is_unsigned<I>::value, "CompactSize only supported for unsigned integers");
+ static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max(), "CompactSize only supports 64-bit integers and below");
+
+ WriteCompactSize<Stream>(s, v);
}
};
@@ -593,6 +629,54 @@ public:
template<typename I>
BigEndian<I> WrapBigEndian(I& n) { return BigEndian<I>(n); }
+/** Formatter to serialize/deserialize vector elements using another formatter
+ *
+ * Example:
+ * struct X {
+ * std::vector<uint64_t> v;
+ * SERIALIZE_METHODS(X, obj) { READWRITE(Using<VectorFormatter<VarInt>>(obj.v)); }
+ * };
+ * will define a struct that contains a vector of uint64_t, which is serialized
+ * as a vector of VarInt-encoded integers.
+ *
+ * V is not required to be an std::vector type. It works for any class that
+ * exposes a value_type, size, reserve, emplace_back, back, and const iterators.
+ */
+template<class Formatter>
+struct VectorFormatter
+{
+ template<typename Stream, typename V>
+ void Ser(Stream& s, const V& v)
+ {
+ Formatter formatter;
+ WriteCompactSize(s, v.size());
+ for (const typename V::value_type& elem : v) {
+ formatter.Ser(s, elem);
+ }
+ }
+
+ template<typename Stream, typename V>
+ void Unser(Stream& s, V& v)
+ {
+ Formatter formatter;
+ v.clear();
+ size_t size = ReadCompactSize(s);
+ size_t allocated = 0;
+ while (allocated < size) {
+ // For DoS prevention, do not blindly allocate as much as the stream claims to contain.
+ // Instead, allocate in 5MiB batches, so that an attacker actually needs to provide
+ // X MiB of data to make us allocate X+5 Mib.
+ static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE, "Vector element size too large");
+ allocated = std::min(size, allocated + MAX_VECTOR_ALLOCATE / sizeof(typename V::value_type));
+ v.reserve(allocated);
+ while (v.size() < allocated) {
+ v.emplace_back();
+ formatter.Unser(s, v.back());
+ }
+ }
+ };
+};
+
/**
* Forward declarations
*/
@@ -673,6 +757,20 @@ inline void Unserialize(Stream& is, T&& a)
a.Unserialize(is);
}
+/** Default formatter. Serializes objects as themselves.
+ *
+ * The vector/prevector serialization code passes this to VectorFormatter
+ * to enable reusing that logic. It shouldn't be needed elsewhere.
+ */
+struct DefaultFormatter
+{
+ template<typename Stream, typename T>
+ static void Ser(Stream& s, const T& t) { Serialize(s, t); }
+
+ template<typename Stream, typename T>
+ static void Unser(Stream& s, T& t) { Unserialize(s, t); }
+};
+
@@ -713,9 +811,7 @@ void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&)
template<typename Stream, unsigned int N, typename T, typename V>
void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&)
{
- WriteCompactSize(os, v.size());
- for (typename prevector<N, T>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
- ::Serialize(os, (*vi));
+ Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));
}
template<typename Stream, unsigned int N, typename T>
@@ -744,19 +840,7 @@ void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)
template<typename Stream, unsigned int N, typename T, typename V>
void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&)
{
- v.clear();
- unsigned int nSize = ReadCompactSize(is);
- unsigned int i = 0;
- unsigned int nMid = 0;
- while (nMid < nSize)
- {
- nMid += 5000000 / sizeof(T);
- if (nMid > nSize)
- nMid = nSize;
- v.resize_uninitialized(nMid);
- for (; i < nMid; ++i)
- Unserialize(is, v[i]);
- }
+ Unserialize(is, Using<VectorFormatter<DefaultFormatter>>(v));
}
template<typename Stream, unsigned int N, typename T>
@@ -793,9 +877,7 @@ void Serialize_impl(Stream& os, const std::vector<T, A>& v, const bool&)
template<typename Stream, typename T, typename A, typename V>
void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&)
{
- WriteCompactSize(os, v.size());
- for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
- ::Serialize(os, (*vi));
+ Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));
}
template<typename Stream, typename T, typename A>
@@ -824,19 +906,7 @@ void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&)
template<typename Stream, typename T, typename A, typename V>
void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&)
{
- v.clear();
- unsigned int nSize = ReadCompactSize(is);
- unsigned int i = 0;
- unsigned int nMid = 0;
- while (nMid < nSize)
- {
- nMid += 5000000 / sizeof(T);
- if (nMid > nSize)
- nMid = nSize;
- v.resize(nMid);
- for (; i < nMid; i++)
- Unserialize(is, v[i]);
- }
+ Unserialize(is, Using<VectorFormatter<DefaultFormatter>>(v));
}
template<typename Stream, typename T, typename A>
diff --git a/src/span.h b/src/span.h
index 77de059fa6..73b37e35f3 100644
--- a/src/span.h
+++ b/src/span.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// 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.
@@ -8,6 +8,7 @@
#include <type_traits>
#include <cstddef>
#include <algorithm>
+#include <assert.h>
/** A Span is an object that can refer to a contiguous sequence of objects.
*
@@ -24,9 +25,28 @@ public:
constexpr Span(C* data, std::ptrdiff_t size) noexcept : m_data(data), m_size(size) {}
constexpr Span(C* data, C* end) noexcept : m_data(data), m_size(end - data) {}
+ /** Implicit conversion of spans between compatible types.
+ *
+ * Specifically, if a pointer to an array of type O can be implicitly converted to a pointer to an array of type
+ * C, then permit implicit conversion of Span<O> to Span<C>. This matches the behavior of the corresponding
+ * C++20 std::span constructor.
+ *
+ * For example this means that a Span<T> can be converted into a Span<const T>.
+ */
+ template <typename O, typename std::enable_if<std::is_convertible<O (*)[], C (*)[]>::value, int>::type = 0>
+ constexpr Span(const Span<O>& other) noexcept : m_data(other.m_data), m_size(other.m_size) {}
+
+ /** Default copy constructor. */
+ constexpr Span(const Span&) noexcept = default;
+
+ /** Default assignment operator. */
+ Span& operator=(const Span& other) noexcept = default;
+
constexpr C* data() const noexcept { return m_data; }
constexpr C* begin() const noexcept { return m_data; }
constexpr C* end() const noexcept { return m_data + m_size; }
+ constexpr C& front() const noexcept { return m_data[0]; }
+ constexpr C& back() const noexcept { return m_data[m_size - 1]; }
constexpr std::ptrdiff_t size() const noexcept { return m_size; }
constexpr C& operator[](std::ptrdiff_t pos) const noexcept { return m_data[pos]; }
@@ -41,6 +61,8 @@ public:
friend constexpr bool operator<=(const Span& a, const Span& b) noexcept { return !(b < a); }
friend constexpr bool operator>(const Span& a, const Span& b) noexcept { return (b < a); }
friend constexpr bool operator>=(const Span& a, const Span& b) noexcept { return !(a < b); }
+
+ template <typename O> friend class Span;
};
/** Create a span to a container exposing data() and size().
@@ -57,4 +79,15 @@ constexpr Span<A> MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
template<typename V>
constexpr Span<typename std::remove_pointer<decltype(std::declval<V>().data())>::type> MakeSpan(V& v) { return Span<typename std::remove_pointer<decltype(std::declval<V>().data())>::type>(v.data(), v.size()); }
+/** Pop the last element off a span, and return a reference to that element. */
+template <typename T>
+T& SpanPopBack(Span<T>& span)
+{
+ size_t size = span.size();
+ assert(size > 0);
+ T& back = span[size - 1];
+ span = Span<T>(span.data(), size - 1);
+ return back;
+}
+
#endif
diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
index 6980b6c0da..9b14637b95 100644
--- a/src/support/lockedpool.cpp
+++ b/src/support/lockedpool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -253,6 +253,9 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
}
if (addr) {
*lockingSuccess = mlock(addr, len) == 0;
+#ifdef MADV_DONTDUMP
+ madvise(addr, len, MADV_DONTDUMP);
+#endif
}
return addr;
}
diff --git a/src/sync.cpp b/src/sync.cpp
index 924e7b5bb0..b86c57e498 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -13,9 +13,9 @@
#include <util/strencodings.h>
#include <util/threadnames.h>
-
#include <map>
#include <set>
+#include <system_error>
#ifdef DEBUG_LOCKCONTENTION
#if !defined(HAVE_THREAD_LOCAL)
@@ -57,7 +57,12 @@ struct CLockLocation {
{
return strprintf(
"%s %s:%s%s (in thread %s)",
- mutexName, sourceFile, itostr(sourceLine), (fTry ? " (TRY)" : ""), m_thread_name);
+ mutexName, sourceFile, sourceLine, (fTry ? " (TRY)" : ""), m_thread_name);
+ }
+
+ std::string Name() const
+ {
+ return mutexName;
}
private:
@@ -155,6 +160,18 @@ void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs
push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry, util::ThreadGetInternalName()));
}
+void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line)
+{
+ if (!g_lockstack.empty()) {
+ const auto& lastlock = g_lockstack.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));
+}
+
void LeaveCritical()
{
pop_lock();
diff --git a/src/sync.h b/src/sync.h
index 0cdbb59c70..0c6f0ef0a7 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -10,9 +10,9 @@
#include <util/macros.h>
#include <condition_variable>
-#include <thread>
#include <mutex>
-
+#include <string>
+#include <thread>
////////////////////////////////////////////////
// //
@@ -50,6 +50,7 @@ LEAVE_CRITICAL_SECTION(mutex); // no RAII
#ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
+void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
std::string LocksHeld();
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) ASSERT_EXCLUSIVE_LOCK(cs);
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
@@ -64,6 +65,7 @@ extern bool g_debug_lockorder_abort;
#else
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {}
+void static inline CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) ASSERT_EXCLUSIVE_LOCK(cs) {}
void static inline AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {}
void static inline DeleteLock(void* cs) {}
@@ -171,8 +173,45 @@ public:
{
return Base::owns_lock();
}
+
+protected:
+ // needed for reverse_lock
+ UniqueLock() { }
+
+public:
+ /**
+ * An RAII-style reverse lock. Unlocks on construction and locks on destruction.
+ */
+ class reverse_lock {
+ public:
+ explicit reverse_lock(UniqueLock& _lock, const char* _guardname, const char* _file, int _line) : lock(_lock), file(_file), line(_line) {
+ CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line);
+ lock.unlock();
+ LeaveCritical();
+ lock.swap(templock);
+ }
+
+ ~reverse_lock() {
+ templock.swap(lock);
+ EnterCritical(lockname.c_str(), file.c_str(), line, (void*)lock.mutex());
+ lock.lock();
+ }
+
+ private:
+ reverse_lock(reverse_lock const&);
+ reverse_lock& operator=(reverse_lock const&);
+
+ UniqueLock& lock;
+ UniqueLock templock;
+ std::string lockname;
+ const std::string file;
+ const int line;
+ };
+ friend class reverse_lock;
};
+#define REVERSE_LOCK(g) typename std::decay<decltype(g)>::type::reverse_lock PASTE2(revlock, __COUNTER__)(g, #g, __FILE__, __LINE__)
+
template<typename MutexArg>
using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>;
diff --git a/src/test/README.md b/src/test/README.md
index 731720f654..57cda26d7c 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -17,26 +17,31 @@ and tests weren't explicitly disabled.
After configuring, they can be run with `make check`.
-To run the bitcoind tests manually, launch `src/test/test_bitcoin`. To recompile
+To run the unit tests manually, launch `src/test/test_bitcoin`. To recompile
after a test file was modified, run `make` and then run the test again. If you
modify a non-test file, use `make -C src/test` to recompile only what's needed
-to run the bitcoind tests.
+to run the unit tests.
-To add more bitcoind tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
+To add more unit tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
.cpp files in the `test/` directory or add new .cpp files that
implement new `BOOST_AUTO_TEST_SUITE` sections.
-To run the bitcoin-qt tests manually, launch `src/qt/test/test_bitcoin-qt`
+To run the GUI unit tests manually, launch `src/qt/test/test_bitcoin-qt`
-To add more bitcoin-qt tests, add them to the `src/qt/test/` directory and
+To add more GUI unit tests, add them to the `src/qt/test/` directory and
the `src/qt/test/test_main.cpp` file.
### Running individual tests
-test_bitcoin has some built-in command-line arguments; for
-example, to run just the getarg_tests verbosely:
+`test_bitcoin` has some built-in command-line arguments; for
+example, to run just the `getarg_tests` verbosely:
- test_bitcoin --log_level=all --run_test=getarg_tests
+ test_bitcoin --log_level=all --run_test=getarg_tests -- DEBUG_LOG_OUT
+
+`log_level` controls the verbosity of the test framework, which logs when a
+test case is entered, for example. The `DEBUG_LOG_OUT` after the two dashes
+redirects the debug log, which would normally go to a file in the test datadir
+(`BasicTestingSetup::m_path_root`), to the standard terminal output.
... or to run just the doubledash test:
@@ -56,11 +61,15 @@ see `uint256_tests.cpp`.
### Logging and debugging in unit tests
+`make check` will write to a log file `foo_tests.cpp.log` and display this file
+on failure. For running individual tests verbosely, refer to the section
+[above](#running-individual-tests).
+
To write to logs from unit tests you need to use specific message methods
provided by Boost. The simplest is `BOOST_TEST_MESSAGE`.
-For debugging you can launch the test_bitcoin executable with `gdb`or `lldb` and
-start debugging, just like you would with bitcoind:
+For debugging you can launch the `test_bitcoin` executable with `gdb`or `lldb` and
+start debugging, just like you would with any other program:
```bash
gdb src/test/test_bitcoin
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 07cebeb35a..bc6b38c682 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -1,17 +1,19 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <addrman.h>
+#include <test/data/asmap.raw.h>
#include <test/util/setup_common.h>
-#include <string>
-#include <boost/test/unit_test.hpp>
#include <util/asmap.h>
-#include <test/data/asmap.raw.h>
-
+#include <util/string.h>
#include <hash.h>
#include <netbase.h>
#include <random.h>
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+
class CAddrManTest : public CAddrMan
{
private:
@@ -266,7 +268,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
BOOST_CHECK_EQUAL(addrman.size(), 0U);
for (unsigned int i = 1; i < 18; i++) {
- CService addr = ResolveService("250.1.1." + std::to_string(i));
+ CService addr = ResolveService("250.1.1." + ToString(i));
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
//Test: No collision in new table yet.
@@ -292,7 +294,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
BOOST_CHECK_EQUAL(addrman.size(), 0U);
for (unsigned int i = 1; i < 80; i++) {
- CService addr = ResolveService("250.1.1." + std::to_string(i));
+ CService addr = ResolveService("250.1.1." + ToString(i));
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(CAddress(addr, NODE_NONE));
@@ -425,7 +427,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
for (unsigned int i = 1; i < (8 * 256); i++) {
int octet1 = i % 256;
int octet2 = i >> 8 % 256;
- std::string strAddr = std::to_string(octet1) + "." + std::to_string(octet2) + ".1.23";
+ std::string strAddr = ToString(octet1) + "." + ToString(octet2) + ".1.23";
CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
// Ensure that for all addrs in addrman, isTerrible == false.
@@ -477,8 +479,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
std::set<int> buckets;
for (int i = 0; i < 255; i++) {
CAddrInfo infoi = CAddrInfo(
- CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE),
- ResolveIP("250.1.1." + std::to_string(i)));
+ CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
+ ResolveIP("250.1.1." + ToString(i)));
int bucket = infoi.GetTriedBucket(nKey1, asmap);
buckets.insert(bucket);
}
@@ -489,8 +491,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
buckets.clear();
for (int j = 0; j < 255; j++) {
CAddrInfo infoj = CAddrInfo(
- CAddress(ResolveService("250." + std::to_string(j) + ".1.1"), NODE_NONE),
- ResolveIP("250." + std::to_string(j) + ".1.1"));
+ CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
+ ResolveIP("250." + ToString(j) + ".1.1"));
int bucket = infoj.GetTriedBucket(nKey1, asmap);
buckets.insert(bucket);
}
@@ -531,8 +533,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket_legacy)
std::set<int> buckets;
for (int i = 0; i < 255; i++) {
CAddrInfo infoi = CAddrInfo(
- CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE),
- ResolveIP("250.1.1." + std::to_string(i)));
+ CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
+ ResolveIP("250.1.1." + ToString(i)));
int bucket = infoi.GetNewBucket(nKey1, asmap);
buckets.insert(bucket);
}
@@ -544,7 +546,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket_legacy)
for (int j = 0; j < 4 * 255; j++) {
CAddrInfo infoj = CAddrInfo(CAddress(
ResolveService(
- std::to_string(250 + (j / 255)) + "." + std::to_string(j % 256) + ".1.1"), NODE_NONE),
+ ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
ResolveIP("251.4.1.1"));
int bucket = infoj.GetNewBucket(nKey1, asmap);
buckets.insert(bucket);
@@ -557,7 +559,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket_legacy)
for (int p = 0; p < 255; p++) {
CAddrInfo infoj = CAddrInfo(
CAddress(ResolveService("250.1.1.1"), NODE_NONE),
- ResolveIP("250." + std::to_string(p) + ".1.1"));
+ ResolveIP("250." + ToString(p) + ".1.1"));
int bucket = infoj.GetNewBucket(nKey1, asmap);
buckets.insert(bucket);
}
@@ -610,8 +612,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
std::set<int> buckets;
for (int j = 0; j < 255; j++) {
CAddrInfo infoj = CAddrInfo(
- CAddress(ResolveService("101." + std::to_string(j) + ".1.1"), NODE_NONE),
- ResolveIP("101." + std::to_string(j) + ".1.1"));
+ CAddress(ResolveService("101." + ToString(j) + ".1.1"), NODE_NONE),
+ ResolveIP("101." + ToString(j) + ".1.1"));
int bucket = infoj.GetTriedBucket(nKey1, asmap);
buckets.insert(bucket);
}
@@ -622,8 +624,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
buckets.clear();
for (int j = 0; j < 255; j++) {
CAddrInfo infoj = CAddrInfo(
- CAddress(ResolveService("250." + std::to_string(j) + ".1.1"), NODE_NONE),
- ResolveIP("250." + std::to_string(j) + ".1.1"));
+ CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
+ ResolveIP("250." + ToString(j) + ".1.1"));
int bucket = infoj.GetTriedBucket(nKey1, asmap);
buckets.insert(bucket);
}
@@ -664,8 +666,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
std::set<int> buckets;
for (int i = 0; i < 255; i++) {
CAddrInfo infoi = CAddrInfo(
- CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE),
- ResolveIP("250.1.1." + std::to_string(i)));
+ CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
+ ResolveIP("250.1.1." + ToString(i)));
int bucket = infoi.GetNewBucket(nKey1, asmap);
buckets.insert(bucket);
}
@@ -677,7 +679,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
for (int j = 0; j < 4 * 255; j++) {
CAddrInfo infoj = CAddrInfo(CAddress(
ResolveService(
- std::to_string(250 + (j / 255)) + "." + std::to_string(j % 256) + ".1.1"), NODE_NONE),
+ ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
ResolveIP("251.4.1.1"));
int bucket = infoj.GetNewBucket(nKey1, asmap);
buckets.insert(bucket);
@@ -690,7 +692,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
for (int p = 0; p < 255; p++) {
CAddrInfo infoj = CAddrInfo(
CAddress(ResolveService("250.1.1.1"), NODE_NONE),
- ResolveIP("101." + std::to_string(p) + ".1.1"));
+ ResolveIP("101." + ToString(p) + ".1.1"));
int bucket = infoj.GetNewBucket(nKey1, asmap);
buckets.insert(bucket);
}
@@ -702,7 +704,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
for (int p = 0; p < 255; p++) {
CAddrInfo infoj = CAddrInfo(
CAddress(ResolveService("250.1.1.1"), NODE_NONE),
- ResolveIP("250." + std::to_string(p) + ".1.1"));
+ ResolveIP("250." + ToString(p) + ".1.1"));
int bucket = infoj.GetNewBucket(nKey1, asmap);
buckets.insert(bucket);
}
@@ -791,7 +793,7 @@ BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
// Add twenty two addresses.
CNetAddr source = ResolveIP("252.2.2.2");
for (unsigned int i = 1; i < 23; i++) {
- CService addr = ResolveService("250.1.1."+std::to_string(i));
+ CService addr = ResolveService("250.1.1."+ToString(i));
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
@@ -802,7 +804,7 @@ BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
// Ensure Good handles duplicates well.
for (unsigned int i = 1; i < 23; i++) {
- CService addr = ResolveService("250.1.1."+std::to_string(i));
+ CService addr = ResolveService("250.1.1."+ToString(i));
addrman.Good(addr);
BOOST_CHECK(addrman.size() == 22);
@@ -818,7 +820,7 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
// Add twenty two addresses.
CNetAddr source = ResolveIP("252.2.2.2");
for (unsigned int i = 1; i < 23; i++) {
- CService addr = ResolveService("250.1.1."+std::to_string(i));
+ CService addr = ResolveService("250.1.1."+ToString(i));
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
@@ -841,7 +843,7 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
// Lets create two collisions.
for (unsigned int i = 24; i < 33; i++) {
- CService addr = ResolveService("250.1.1."+std::to_string(i));
+ CService addr = ResolveService("250.1.1."+ToString(i));
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
@@ -879,7 +881,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
// Add twenty two addresses.
CNetAddr source = ResolveIP("252.2.2.2");
for (unsigned int i = 1; i < 23; i++) {
- CService addr = ResolveService("250.1.1."+std::to_string(i));
+ CService addr = ResolveService("250.1.1."+ToString(i));
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp
index 3723a48903..a135c93786 100644
--- a/src/test/arith_uint256_tests.cpp
+++ b/src/test/arith_uint256_tests.cpp
@@ -1,17 +1,19 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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 <arith_uint256.h>
+#include <test/util/setup_common.h>
+#include <uint256.h>
+
#include <boost/test/unit_test.hpp>
-#include <stdint.h>
-#include <sstream>
+
+#include <cmath>
#include <iomanip>
#include <limits>
-#include <cmath>
-#include <uint256.h>
-#include <arith_uint256.h>
+#include <sstream>
+#include <stdint.h>
#include <string>
-#include <test/util/setup_common.h>
BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup)
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
index 690368b177..eedab30576 100644
--- a/src/test/base32_tests.cpp
+++ b/src/test/base32_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <util/strencodings.h>
#include <test/util/setup_common.h>
+#include <util/strencodings.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index 94df4d1955..5927eab6cf 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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 <util/strencodings.h>
#include <test/util/setup_common.h>
+#include <util/strencodings.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 53df032252..32329eb510 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2019 The Bitcoin Core developers
+// Copyright (c) 2013-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.
@@ -8,8 +8,8 @@
#include <key.h>
#include <key_io.h>
#include <streams.h>
-#include <util/strencodings.h>
#include <test/util/setup_common.h>
+#include <util/strencodings.h>
#include <string>
#include <vector>
diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp
index 3b4c480f72..c8e8cdeeb3 100644
--- a/src/test/blockchain_tests.cpp
+++ b/src/test/blockchain_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -9,6 +9,7 @@
#include <chain.h>
#include <rpc/blockchain.h>
#include <test/util/setup_common.h>
+#include <util/string.h>
/* Equality between doubles is imprecise. Comparison should be done
* with a small threshold of tolerance, rather than exact equality.
@@ -30,8 +31,8 @@ static CBlockIndex* CreateBlockIndexWithNbits(uint32_t nbits)
static void RejectDifficultyMismatch(double difficulty, double expected_difficulty) {
BOOST_CHECK_MESSAGE(
DoubleEquals(difficulty, expected_difficulty, 0.00001),
- "Difficulty was " + std::to_string(difficulty)
- + " but was expected to be " + std::to_string(expected_difficulty));
+ "Difficulty was " + ToString(difficulty)
+ + " but was expected to be " + ToString(expected_difficulty));
}
/* Given a BlockIndex with the provided nbits,
diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp
index 79e18cd2c0..ff01f730a3 100644
--- a/src/test/blockfilter_index_tests.cpp
+++ b/src/test/blockfilter_index_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -138,7 +138,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
int64_t time_start = GetTimeMillis();
while (!filter_index.BlockUntilSyncedToCurrentChain()) {
BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
- MilliSleep(100);
+ UninterruptibleSleep(std::chrono::milliseconds{100});
}
// Check that filter index has all blocks that were in the chain before it started.
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 4a7ad9b38b..a75d9fc9ec 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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.
@@ -12,10 +12,10 @@
#include <random.h>
#include <serialize.h>
#include <streams.h>
+#include <test/util/setup_common.h>
#include <uint256.h>
-#include <util/system.h>
#include <util/strencodings.h>
-#include <test/util/setup_common.h>
+#include <util/system.h>
#include <vector>
@@ -27,6 +27,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
{
CBloomFilter filter(3, 0.01, 0, BLOOM_UPDATE_ALL);
+ BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter should be empty!");
filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!");
// One bit different in first byte
@@ -50,8 +51,6 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!");
- filter.clear();
- BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter should be empty!");
}
BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp
index d5e2344a8b..c89cb5488d 100644
--- a/src/test/bswap_tests.cpp
+++ b/src/test/bswap_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -11,16 +11,16 @@ BOOST_FIXTURE_TEST_SUITE(bswap_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(bswap_tests)
{
- // Sibling in bitcoin/src/qt/test/compattests.cpp
- uint16_t u1 = 0x1234;
- uint32_t u2 = 0x56789abc;
- uint64_t u3 = 0xdef0123456789abc;
- uint16_t e1 = 0x3412;
- uint32_t e2 = 0xbc9a7856;
- uint64_t e3 = 0xbc9a78563412f0de;
- BOOST_CHECK(bswap_16(u1) == e1);
- BOOST_CHECK(bswap_32(u2) == e2);
- BOOST_CHECK(bswap_64(u3) == e3);
+ // Sibling in bitcoin/src/qt/test/compattests.cpp
+ uint16_t u1 = 0x1234;
+ uint32_t u2 = 0x56789abc;
+ uint64_t u3 = 0xdef0123456789abc;
+ uint16_t e1 = 0x3412;
+ uint32_t e2 = 0xbc9a7856;
+ uint64_t e3 = 0xbc9a78563412f0de;
+ BOOST_CHECK(bswap_16(u1) == e1);
+ BOOST_CHECK(bswap_32(u2) == e2);
+ BOOST_CHECK(bswap_64(u3) == e3);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
index 482fe3772c..0565982215 100644
--- a/src/test/checkqueue_tests.cpp
+++ b/src/test/checkqueue_tests.cpp
@@ -1,23 +1,23 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <checkqueue.h>
+#include <test/util/setup_common.h>
#include <util/memory.h>
#include <util/system.h>
#include <util/time.h>
-#include <test/util/setup_common.h>
-#include <checkqueue.h>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
+
#include <atomic>
-#include <thread>
-#include <vector>
-#include <mutex>
#include <condition_variable>
-
+#include <mutex>
+#include <thread>
#include <unordered_set>
#include <utility>
+#include <vector>
BOOST_FIXTURE_TEST_SUITE(checkqueue_tests, TestingSetup)
@@ -393,7 +393,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks)
CCheckQueueControl<FakeCheck> control(queue.get());
// While sleeping, no other thread should execute to this point
auto observed = ++nThreads;
- MilliSleep(10);
+ UninterruptibleSleep(std::chrono::milliseconds{10});
fails += observed != nThreads;
});
}
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index 436c1bffa0..60196c36a5 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -8,6 +8,7 @@
#include <script/standard.h>
#include <streams.h>
#include <test/util/setup_common.h>
+#include <txdb.h>
#include <uint256.h>
#include <undo.h>
#include <util/strencodings.h>
@@ -109,7 +110,12 @@ static const unsigned int NUM_SIMULATION_ITERATIONS = 40000;
//
// During the process, booleans are kept to make sure that the randomized
// operation hits all branches.
-BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
+//
+// If fake_best_block is true, assign a random uint256 to mock the recording
+// of best block on flush. This is necessary when using CCoinsViewDB as the base,
+// otherwise we'll hit an assertion in BatchWrite.
+//
+void SimulationTest(CCoinsView* base, bool fake_best_block)
{
// Various coverage trackers.
bool removed_all_caches = false;
@@ -126,9 +132,8 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
std::map<COutPoint, Coin> result;
// The cache stack.
- CCoinsViewTest base; // A CCoinsViewTest at the bottom.
std::vector<CCoinsViewCacheTest*> stack; // A stack of CCoinsViewCaches on top.
- stack.push_back(new CCoinsViewCacheTest(&base)); // Start with one cache.
+ stack.push_back(new CCoinsViewCacheTest(base)); // Start with one cache.
// Use a limited set of random transaction ids, so we do test overwriting entries.
std::vector<uint256> txids;
@@ -211,6 +216,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
// Every 100 iterations, flush an intermediate cache
if (stack.size() > 1 && InsecureRandBool() == 0) {
unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
+ if (fake_best_block) stack[flushIndex]->SetBestBlock(InsecureRand256());
BOOST_CHECK(stack[flushIndex]->Flush());
}
}
@@ -218,13 +224,14 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
// Every 100 iterations, change the cache stack.
if (stack.size() > 0 && InsecureRandBool() == 0) {
//Remove the top cache
+ if (fake_best_block) stack.back()->SetBestBlock(InsecureRand256());
BOOST_CHECK(stack.back()->Flush());
delete stack.back();
stack.pop_back();
}
if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) {
//Add a new cache
- CCoinsView* tip = &base;
+ CCoinsView* tip = base;
if (stack.size() > 0) {
tip = stack.back();
} else {
@@ -256,6 +263,16 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
BOOST_CHECK(uncached_an_entry);
}
+// Run the above simulation for multiple base types.
+BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
+{
+ CCoinsViewTest base;
+ SimulationTest(&base, false);
+
+ CCoinsViewDB db_base{"test", /*nCacheSize*/ 1 << 23, /*fMemory*/ true, /*fWipe*/ false};
+ SimulationTest(&db_base, true);
+}
+
// Store of all necessary tx and undo data for next test
typedef std::map<COutPoint, std::tuple<CTransaction,CTxUndo,Coin>> UtxoData;
UtxoData utxoData;
@@ -532,7 +549,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
}
const static COutPoint OUTPOINT;
-const static CAmount PRUNED = -1;
+const static CAmount SPENT = -1;
const static CAmount ABSENT = -2;
const static CAmount FAIL = -3;
const static CAmount VALUE1 = 100;
@@ -551,7 +568,7 @@ static void SetCoinsValue(CAmount value, Coin& coin)
assert(value != ABSENT);
coin.Clear();
assert(coin.IsSpent());
- if (value != PRUNED) {
+ if (value != SPENT) {
coin.out.nValue = value;
coin.nHeight = 1;
assert(!coin.IsSpent());
@@ -581,7 +598,7 @@ void GetCoinsMapEntry(const CCoinsMap& map, CAmount& value, char& flags)
flags = NO_ENTRY;
} else {
if (it->second.coin.IsSpent()) {
- value = PRUNED;
+ value = SPENT;
} else {
value = it->second.coin.out.nValue;
}
@@ -634,28 +651,28 @@ BOOST_AUTO_TEST_CASE(ccoins_access)
* Value Value Value Flags Flags
*/
CheckAccessCoin(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
- CheckAccessCoin(ABSENT, PRUNED, PRUNED, 0 , 0 );
- CheckAccessCoin(ABSENT, PRUNED, PRUNED, FRESH , FRESH );
- CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY );
- CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
+ CheckAccessCoin(ABSENT, SPENT , SPENT , 0 , 0 );
+ CheckAccessCoin(ABSENT, SPENT , SPENT , FRESH , FRESH );
+ CheckAccessCoin(ABSENT, SPENT , SPENT , DIRTY , DIRTY );
+ CheckAccessCoin(ABSENT, SPENT , SPENT , DIRTY|FRESH, DIRTY|FRESH);
CheckAccessCoin(ABSENT, VALUE2, VALUE2, 0 , 0 );
CheckAccessCoin(ABSENT, VALUE2, VALUE2, FRESH , FRESH );
CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY , DIRTY );
CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
- CheckAccessCoin(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
- CheckAccessCoin(PRUNED, PRUNED, PRUNED, 0 , 0 );
- CheckAccessCoin(PRUNED, PRUNED, PRUNED, FRESH , FRESH );
- CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
- CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
- CheckAccessCoin(PRUNED, VALUE2, VALUE2, 0 , 0 );
- CheckAccessCoin(PRUNED, VALUE2, VALUE2, FRESH , FRESH );
- CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY );
- CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
+ CheckAccessCoin(SPENT , ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
+ CheckAccessCoin(SPENT , SPENT , SPENT , 0 , 0 );
+ CheckAccessCoin(SPENT , SPENT , SPENT , FRESH , FRESH );
+ CheckAccessCoin(SPENT , SPENT , SPENT , DIRTY , DIRTY );
+ CheckAccessCoin(SPENT , SPENT , SPENT , DIRTY|FRESH, DIRTY|FRESH);
+ CheckAccessCoin(SPENT , VALUE2, VALUE2, 0 , 0 );
+ CheckAccessCoin(SPENT , VALUE2, VALUE2, FRESH , FRESH );
+ CheckAccessCoin(SPENT , VALUE2, VALUE2, DIRTY , DIRTY );
+ CheckAccessCoin(SPENT , VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
CheckAccessCoin(VALUE1, ABSENT, VALUE1, NO_ENTRY , 0 );
- CheckAccessCoin(VALUE1, PRUNED, PRUNED, 0 , 0 );
- CheckAccessCoin(VALUE1, PRUNED, PRUNED, FRESH , FRESH );
- CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY );
- CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
+ CheckAccessCoin(VALUE1, SPENT , SPENT , 0 , 0 );
+ CheckAccessCoin(VALUE1, SPENT , SPENT , FRESH , FRESH );
+ CheckAccessCoin(VALUE1, SPENT , SPENT , DIRTY , DIRTY );
+ CheckAccessCoin(VALUE1, SPENT , SPENT , DIRTY|FRESH, DIRTY|FRESH);
CheckAccessCoin(VALUE1, VALUE2, VALUE2, 0 , 0 );
CheckAccessCoin(VALUE1, VALUE2, VALUE2, FRESH , FRESH );
CheckAccessCoin(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY );
@@ -685,31 +702,31 @@ BOOST_AUTO_TEST_CASE(ccoins_spend)
* Value Value Value Flags Flags
*/
CheckSpendCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
- CheckSpendCoins(ABSENT, PRUNED, PRUNED, 0 , DIRTY );
- CheckSpendCoins(ABSENT, PRUNED, ABSENT, FRESH , NO_ENTRY );
- CheckSpendCoins(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY );
- CheckSpendCoins(ABSENT, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
- CheckSpendCoins(ABSENT, VALUE2, PRUNED, 0 , DIRTY );
+ CheckSpendCoins(ABSENT, SPENT , SPENT , 0 , DIRTY );
+ CheckSpendCoins(ABSENT, SPENT , ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(ABSENT, SPENT , SPENT , DIRTY , DIRTY );
+ CheckSpendCoins(ABSENT, SPENT , ABSENT, DIRTY|FRESH, NO_ENTRY );
+ CheckSpendCoins(ABSENT, VALUE2, SPENT , 0 , DIRTY );
CheckSpendCoins(ABSENT, VALUE2, ABSENT, FRESH , NO_ENTRY );
- CheckSpendCoins(ABSENT, VALUE2, PRUNED, DIRTY , DIRTY );
+ CheckSpendCoins(ABSENT, VALUE2, SPENT , DIRTY , DIRTY );
CheckSpendCoins(ABSENT, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
- CheckSpendCoins(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
- CheckSpendCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY );
- CheckSpendCoins(PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY );
- CheckSpendCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
- CheckSpendCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
- CheckSpendCoins(PRUNED, VALUE2, PRUNED, 0 , DIRTY );
- CheckSpendCoins(PRUNED, VALUE2, ABSENT, FRESH , NO_ENTRY );
- CheckSpendCoins(PRUNED, VALUE2, PRUNED, DIRTY , DIRTY );
- CheckSpendCoins(PRUNED, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
- CheckSpendCoins(VALUE1, ABSENT, PRUNED, NO_ENTRY , DIRTY );
- CheckSpendCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY );
- CheckSpendCoins(VALUE1, PRUNED, ABSENT, FRESH , NO_ENTRY );
- CheckSpendCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY );
- CheckSpendCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
- CheckSpendCoins(VALUE1, VALUE2, PRUNED, 0 , DIRTY );
+ CheckSpendCoins(SPENT , ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
+ CheckSpendCoins(SPENT , SPENT , SPENT , 0 , DIRTY );
+ CheckSpendCoins(SPENT , SPENT , ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(SPENT , SPENT , SPENT , DIRTY , DIRTY );
+ CheckSpendCoins(SPENT , SPENT , ABSENT, DIRTY|FRESH, NO_ENTRY );
+ CheckSpendCoins(SPENT , VALUE2, SPENT , 0 , DIRTY );
+ CheckSpendCoins(SPENT , VALUE2, ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(SPENT , VALUE2, SPENT , DIRTY , DIRTY );
+ CheckSpendCoins(SPENT , VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
+ CheckSpendCoins(VALUE1, ABSENT, SPENT , NO_ENTRY , DIRTY );
+ CheckSpendCoins(VALUE1, SPENT , SPENT , 0 , DIRTY );
+ CheckSpendCoins(VALUE1, SPENT , ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(VALUE1, SPENT , SPENT , DIRTY , DIRTY );
+ CheckSpendCoins(VALUE1, SPENT , ABSENT, DIRTY|FRESH, NO_ENTRY );
+ CheckSpendCoins(VALUE1, VALUE2, SPENT , 0 , DIRTY );
CheckSpendCoins(VALUE1, VALUE2, ABSENT, FRESH , NO_ENTRY );
- CheckSpendCoins(VALUE1, VALUE2, PRUNED, DIRTY , DIRTY );
+ CheckSpendCoins(VALUE1, VALUE2, SPENT , DIRTY , DIRTY );
CheckSpendCoins(VALUE1, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
}
@@ -742,7 +759,7 @@ static void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount mo
template <typename... Args>
static void CheckAddCoin(Args&&... args)
{
- for (const CAmount base_value : {ABSENT, PRUNED, VALUE1})
+ for (const CAmount base_value : {ABSENT, SPENT, VALUE1})
CheckAddCoinBase(base_value, std::forward<Args>(args)...);
}
@@ -751,21 +768,21 @@ BOOST_AUTO_TEST_CASE(ccoins_add)
/* Check AddCoin behavior, requesting a new coin from a cache view,
* writing a modification to the coin, and then checking the resulting
* entry in the cache after the modification. Verify behavior with the
- * with the AddCoin potential_overwrite argument set to false, and to true.
+ * AddCoin possible_overwrite argument set to false, and to true.
*
- * Cache Write Result Cache Result potential_overwrite
+ * Cache Write Result Cache Result possible_overwrite
* Value Value Value Flags Flags
*/
CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH, false);
CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY , true );
- CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY|FRESH, false);
- CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY , true );
- CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, false);
- CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
- CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , false);
- CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , true );
- CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false);
- CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
+ CheckAddCoin(SPENT , VALUE3, VALUE3, 0 , DIRTY|FRESH, false);
+ CheckAddCoin(SPENT , VALUE3, VALUE3, 0 , DIRTY , true );
+ CheckAddCoin(SPENT , VALUE3, VALUE3, FRESH , DIRTY|FRESH, false);
+ CheckAddCoin(SPENT , VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
+ CheckAddCoin(SPENT , VALUE3, VALUE3, DIRTY , DIRTY , false);
+ CheckAddCoin(SPENT , VALUE3, VALUE3, DIRTY , DIRTY , true );
+ CheckAddCoin(SPENT , VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false);
+ CheckAddCoin(SPENT , VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
CheckAddCoin(VALUE2, VALUE3, FAIL , 0 , NO_ENTRY , false);
CheckAddCoin(VALUE2, VALUE3, VALUE3, 0 , DIRTY , true );
CheckAddCoin(VALUE2, VALUE3, FAIL , FRESH , NO_ENTRY , false);
@@ -805,42 +822,42 @@ BOOST_AUTO_TEST_CASE(ccoins_write)
* Value Value Value Flags Flags Flags
*/
CheckWriteCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY , NO_ENTRY );
- CheckWriteCoins(ABSENT, PRUNED, PRUNED, NO_ENTRY , DIRTY , DIRTY );
- CheckWriteCoins(ABSENT, PRUNED, ABSENT, NO_ENTRY , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(ABSENT, SPENT , SPENT , NO_ENTRY , DIRTY , DIRTY );
+ CheckWriteCoins(ABSENT, SPENT , ABSENT, NO_ENTRY , DIRTY|FRESH, NO_ENTRY );
CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY , DIRTY );
CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY|FRESH, DIRTY|FRESH);
- CheckWriteCoins(PRUNED, ABSENT, PRUNED, 0 , NO_ENTRY , 0 );
- CheckWriteCoins(PRUNED, ABSENT, PRUNED, FRESH , NO_ENTRY , FRESH );
- CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY , NO_ENTRY , DIRTY );
- CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
- CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY , DIRTY );
- CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY|FRESH, DIRTY );
- CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY );
- CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY|FRESH, NO_ENTRY );
- CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY );
- CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY|FRESH, DIRTY );
- CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
- CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
- CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY , DIRTY );
- CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY|FRESH, DIRTY );
- CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
- CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY|FRESH, DIRTY|FRESH);
- CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY );
- CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY|FRESH, DIRTY );
- CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH);
- CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH, DIRTY|FRESH);
+ CheckWriteCoins(SPENT , ABSENT, SPENT , 0 , NO_ENTRY , 0 );
+ CheckWriteCoins(SPENT , ABSENT, SPENT , FRESH , NO_ENTRY , FRESH );
+ CheckWriteCoins(SPENT , ABSENT, SPENT , DIRTY , NO_ENTRY , DIRTY );
+ CheckWriteCoins(SPENT , ABSENT, SPENT , DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
+ CheckWriteCoins(SPENT , SPENT , SPENT , 0 , DIRTY , DIRTY );
+ CheckWriteCoins(SPENT , SPENT , SPENT , 0 , DIRTY|FRESH, DIRTY );
+ CheckWriteCoins(SPENT , SPENT , ABSENT, FRESH , DIRTY , NO_ENTRY );
+ CheckWriteCoins(SPENT , SPENT , ABSENT, FRESH , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(SPENT , SPENT , SPENT , DIRTY , DIRTY , DIRTY );
+ CheckWriteCoins(SPENT , SPENT , SPENT , DIRTY , DIRTY|FRESH, DIRTY );
+ CheckWriteCoins(SPENT , SPENT , ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
+ CheckWriteCoins(SPENT , SPENT , ABSENT, DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(SPENT , VALUE2, VALUE2, 0 , DIRTY , DIRTY );
+ CheckWriteCoins(SPENT , VALUE2, VALUE2, 0 , DIRTY|FRESH, DIRTY );
+ CheckWriteCoins(SPENT , VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
+ CheckWriteCoins(SPENT , VALUE2, VALUE2, FRESH , DIRTY|FRESH, DIRTY|FRESH);
+ CheckWriteCoins(SPENT , VALUE2, VALUE2, DIRTY , DIRTY , DIRTY );
+ CheckWriteCoins(SPENT , VALUE2, VALUE2, DIRTY , DIRTY|FRESH, DIRTY );
+ CheckWriteCoins(SPENT , VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH);
+ CheckWriteCoins(SPENT , VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH, DIRTY|FRESH);
CheckWriteCoins(VALUE1, ABSENT, VALUE1, 0 , NO_ENTRY , 0 );
CheckWriteCoins(VALUE1, ABSENT, VALUE1, FRESH , NO_ENTRY , FRESH );
CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY , NO_ENTRY , DIRTY );
CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
- CheckWriteCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY , DIRTY );
- CheckWriteCoins(VALUE1, PRUNED, FAIL , 0 , DIRTY|FRESH, NO_ENTRY );
- CheckWriteCoins(VALUE1, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY );
- CheckWriteCoins(VALUE1, PRUNED, FAIL , FRESH , DIRTY|FRESH, NO_ENTRY );
- CheckWriteCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY );
- CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY );
- CheckWriteCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
- CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, SPENT , SPENT , 0 , DIRTY , DIRTY );
+ CheckWriteCoins(VALUE1, SPENT , FAIL , 0 , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, SPENT , ABSENT, FRESH , DIRTY , NO_ENTRY );
+ CheckWriteCoins(VALUE1, SPENT , FAIL , FRESH , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, SPENT , SPENT , DIRTY , DIRTY , DIRTY );
+ CheckWriteCoins(VALUE1, SPENT , FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, SPENT , ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
+ CheckWriteCoins(VALUE1, SPENT , FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
CheckWriteCoins(VALUE1, VALUE2, VALUE2, 0 , DIRTY , DIRTY );
CheckWriteCoins(VALUE1, VALUE2, FAIL , 0 , DIRTY|FRESH, NO_ENTRY );
CheckWriteCoins(VALUE1, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
@@ -854,8 +871,8 @@ BOOST_AUTO_TEST_CASE(ccoins_write)
// they would be too repetitive (the parent cache is never updated in these
// cases). The loop below covers these cases and makes sure the parent cache
// is always left unchanged.
- for (const CAmount parent_value : {ABSENT, PRUNED, VALUE1})
- for (const CAmount child_value : {ABSENT, PRUNED, VALUE2})
+ for (const CAmount parent_value : {ABSENT, SPENT, VALUE1})
+ for (const CAmount child_value : {ABSENT, SPENT, VALUE2})
for (const char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS)
for (const char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS)
CheckWriteCoins(parent_value, child_value, parent_value, parent_flags, child_flags, parent_flags);
diff --git a/src/test/compilerbug_tests.cpp b/src/test/compilerbug_tests.cpp
index 1a6fcda009..b68bc279e1 100644
--- a/src/test/compilerbug_tests.cpp
+++ b/src/test/compilerbug_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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/setup_common.h>
#include <boost/test/unit_test.hpp>
+#include <test/util/setup_common.h>
BOOST_FIXTURE_TEST_SUITE(compilerbug_tests, BasicTestingSetup)
diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp
index 22eae91cf0..df1a119d79 100644
--- a/src/test/compress_tests.cpp
+++ b/src/test/compress_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <compressor.h>
-#include <test/util/setup_common.h>
#include <script/standard.h>
+#include <test/util/setup_common.h>
#include <stdint.h>
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 2deb0c5bfc..f64251fe32 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -1,21 +1,21 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-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 <crypto/aes.h>
#include <crypto/chacha20.h>
#include <crypto/chacha_poly_aead.h>
-#include <crypto/poly1305.h>
#include <crypto/hkdf_sha256_32.h>
#include <crypto/hmac_sha256.h>
#include <crypto/hmac_sha512.h>
+#include <crypto/poly1305.h>
#include <crypto/ripemd160.h>
#include <crypto/sha1.h>
#include <crypto/sha256.h>
#include <crypto/sha512.h>
#include <random.h>
-#include <util/strencodings.h>
#include <test/util/setup_common.h>
+#include <util/strencodings.h>
#include <vector>
diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp
index 6be24c0845..3a951d28ae 100644
--- a/src/test/cuckoocache_tests.cpp
+++ b/src/test/cuckoocache_tests.cpp
@@ -1,13 +1,13 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <boost/test/unit_test.hpp>
#include <cuckoocache.h>
+#include <deque>
+#include <random.h>
#include <script/sigcache.h>
#include <test/util/setup_common.h>
-#include <random.h>
#include <thread>
-#include <deque>
/** Test Suite for CuckooCache
*
diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json
index 3241f32f56..c01ef307b7 100644
--- a/src/test/data/script_tests.json
+++ b/src/test/data/script_tests.json
@@ -121,9 +121,9 @@
["8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
["2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
["2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
-["549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
-["549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"],
-["9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x05ffffffff7f", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x06000000008000", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x08ffffffffffffff7f", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"],
["-1", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
["-127", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
["-128", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"],
@@ -133,9 +133,9 @@
["-8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
["-2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
["-2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
-["-549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
-["-549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"],
-["-9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x05ffffffffff", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x06000000008080", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x08ffffffffffffffff", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"],
["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL", "P2SH,STRICTENC", "OK"],
["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "P2SH,STRICTENC", "OK", "SIZE does not consume argument"],
@@ -360,9 +360,9 @@
["8388608", "0x04 0x00008000 EQUAL", "P2SH,STRICTENC", "OK"],
["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC", "OK"],
-["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
-["549755813888", "0x06 0x000000008000 EQUAL", "P2SH,STRICTENC", "OK"],
-["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["0x05ffffffff7f", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["0x06000000008000", "0x06 0x000000008000 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x08ffffffffffffff7f", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "OK", "Numbers are little-endian with the MSB being a sign bit"],
["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC", "OK"],
["-128", "0x02 0x8080 EQUAL", "P2SH,STRICTENC", "OK"],
@@ -373,9 +373,9 @@
["-2147483647", "0x04 0xFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
["-2147483648", "0x05 0x0000008080 EQUAL", "P2SH,STRICTENC", "OK"],
["-4294967295", "0x05 0xFFFFFFFF80 EQUAL", "P2SH,STRICTENC", "OK"],
-["-549755813887", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
-["-549755813888", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC", "OK"],
-["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["0x05ffffffffff", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["0x06000000008080", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x08ffffffffffffffff", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
["2147483647", "1ADD 2147483648 EQUAL", "P2SH,STRICTENC", "OK", "We can do math on 4-byte integers, and compare 5-byte ones"],
["2147483647", "1ADD 1", "P2SH,STRICTENC", "OK"],
@@ -2521,7 +2521,7 @@
["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"],
["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"],
["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
-["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
+["0x050000000001", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
"CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"],
["MINIMALIF tests"],
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index d22175d660..3b1db449b2 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -174,7 +174,7 @@
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
["Argument 2^32 with nLockTime=2^32-1"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967296 CHECKLOCKTIMEVERIFY 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x050000000001 CHECKLOCKTIMEVERIFY 1"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
["Same, but with nLockTime=2^31-1"],
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 4a1c77166d..11634c90f0 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -292,11 +292,11 @@
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument 3<<31 with various nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x050000008001 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x050000008001 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x050000008001 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["5 byte non-minimally-encoded operandss are valid"],
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index b647c0f70b..c378546e8b 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <dbwrapper.h>
-#include <uint256.h>
#include <test/util/setup_common.h>
+#include <uint256.h>
#include <util/memory.h>
#include <memory>
@@ -399,15 +399,15 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering)
BOOST_AUTO_TEST_CASE(unicodepath)
{
- // Attempt to create a database with a utf8 character in the path.
+ // Attempt to create a database with a UTF8 character in the path.
// On Windows this test will fail if the directory is created using
- // the ANSI CreateDirectoryA call and the code page isn't UTF8.
- // It will succeed if the created with CreateDirectoryW.
+ // the ANSI CreateDirectoryA call and the code page isn't UTF8.
+ // It will succeed if created with CreateDirectoryW.
fs::path ph = GetDataDir() / "test_runner_₿_🏃_20191128_104644";
CDBWrapper dbw(ph, (1 << 20));
fs::path lockPath = ph / "LOCK";
- BOOST_CHECK(boost::filesystem::exists(lockPath));
+ BOOST_CHECK(fs::exists(lockPath));
}
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index 2c2b3035e3..6314c1a42f 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -13,6 +13,7 @@
#include <script/standard.h>
#include <serialize.h>
#include <util/memory.h>
+#include <util/string.h>
#include <util/system.h>
#include <util/time.h>
#include <validation.h>
@@ -51,7 +52,6 @@ struct COrphanTx {
NodeId fromPeer;
int64_t nTimeExpire;
};
-extern RecursiveMutex g_cs_orphans;
extern std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans);
static CService ip(uint32_t i)
@@ -78,7 +78,7 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, *m_node.scheduler, *m_node.mempool);
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -148,7 +148,7 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidat
BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
{
auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, *m_node.scheduler, *m_node.mempool);
const Consensus::Params& consensusParams = Params().GetConsensus();
constexpr int max_outbound_full_relay = 8;
@@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
{
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), *m_node.scheduler, *m_node.mempool);
banman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -276,7 +276,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
{
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), *m_node.scheduler, *m_node.mempool);
banman->ClearBanned();
gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number
@@ -313,7 +313,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
}
BOOST_CHECK(banman->IsBanned(addr1));
- gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD));
+ gArgs.ForceSetArg("-banscore", ToString(DEFAULT_BANSCORE_THRESHOLD));
bool dummy;
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
@@ -323,7 +323,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
{
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), *m_node.scheduler, *m_node.mempool);
banman->ClearBanned();
int64_t nStartTime = GetTime();
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index bcce8854e3..121b80ab2d 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -1,16 +1,18 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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 <vector>
-#include <string>
+#include <script/descriptor.h>
#include <script/sign.h>
#include <script/standard.h>
#include <test/util/setup_common.h>
-#include <boost/test/unit_test.hpp>
-#include <script/descriptor.h>
#include <util/strencodings.h>
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+#include <vector>
+
namespace {
void CheckUnparsable(const std::string& prv, const std::string& pub, const std::string& expected_error)
@@ -29,6 +31,7 @@ constexpr int RANGE = 1; // Expected to be ranged descriptor
constexpr int HARDENED = 2; // Derivation needs access to private keys
constexpr int UNSOLVABLE = 4; // This descriptor is not expected to be solvable
constexpr int SIGNABLE = 8; // We can sign with this descriptor (this is not true when actual BIP32 derivation is used, as that's not integrated in our signing code)
+constexpr int DERIVE_HARDENED = 16; // The final derivation is hardened, i.e. ends with *' or *h
/** Compare two descriptors. If only one of them has a checksum, the checksum is ignored. */
bool EqualDescriptor(std::string a, std::string b)
@@ -62,7 +65,7 @@ std::string UseHInsteadOfApostrophe(const std::string& desc)
const std::set<std::vector<uint32_t>> ONLY_EMPTY{{}};
-void DoCheck(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY,
+void DoCheck(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const Optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY,
bool replace_apostrophe_with_h_in_prv=false, bool replace_apostrophe_with_h_in_pub=false)
{
FlatSigningProvider keys_priv, keys_pub;
@@ -86,6 +89,10 @@ void DoCheck(const std::string& prv, const std::string& pub, int flags, const st
BOOST_CHECK(parse_priv);
BOOST_CHECK(parse_pub);
+ // Check that the correct OutputType is inferred
+ BOOST_CHECK(parse_priv->GetOutputType() == type);
+ BOOST_CHECK(parse_pub->GetOutputType() == type);
+
// Check private keys are extracted from the private version but not the public one.
BOOST_CHECK(keys_priv.keys.size());
BOOST_CHECK(!keys_pub.keys.size());
@@ -131,19 +138,82 @@ void DoCheck(const std::string& prv, const std::string& pub, int flags, const st
// Evaluate the descriptor selected by `t` in poisition `i`.
FlatSigningProvider script_provider, script_provider_cached;
std::vector<CScript> spks, spks_cached;
- std::vector<unsigned char> cache;
- BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i, key_provider, spks, script_provider, &cache));
+ DescriptorCache desc_cache;
+ BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i, key_provider, spks, script_provider, &desc_cache));
// Compare the output with the expected result.
BOOST_CHECK_EQUAL(spks.size(), ref.size());
// Try to expand again using cached data, and compare.
- BOOST_CHECK(parse_pub->ExpandFromCache(i, cache, spks_cached, script_provider_cached));
+ BOOST_CHECK(parse_pub->ExpandFromCache(i, desc_cache, spks_cached, script_provider_cached));
BOOST_CHECK(spks == spks_cached);
BOOST_CHECK(script_provider.pubkeys == script_provider_cached.pubkeys);
BOOST_CHECK(script_provider.scripts == script_provider_cached.scripts);
BOOST_CHECK(script_provider.origins == script_provider_cached.origins);
+ // Check whether keys are in the cache
+ const auto& der_xpub_cache = desc_cache.GetCachedDerivedExtPubKeys();
+ const auto& parent_xpub_cache = desc_cache.GetCachedParentExtPubKeys();
+ if ((flags & RANGE) && !(flags & DERIVE_HARDENED)) {
+ // For ranged, unhardened derivation, None of the keys in origins should appear in the cache but the cache should have parent keys
+ // But we can derive one level from each of those parent keys and find them all
+ BOOST_CHECK(der_xpub_cache.empty());
+ BOOST_CHECK(parent_xpub_cache.size() > 0);
+ std::set<CPubKey> pubkeys;
+ for (const auto& xpub_pair : parent_xpub_cache) {
+ const CExtPubKey& xpub = xpub_pair.second;
+ CExtPubKey der;
+ xpub.Derive(der, i);
+ pubkeys.insert(der.pubkey);
+ }
+ for (const auto& origin_pair : script_provider_cached.origins) {
+ const CPubKey& pk = origin_pair.second.first;
+ BOOST_CHECK(pubkeys.count(pk) > 0);
+ }
+ } else if (pub1.find("xpub") != std::string::npos) {
+ // For ranged, hardened derivation, or not ranged, but has an xpub, all of the keys should appear in the cache
+ BOOST_CHECK(der_xpub_cache.size() + parent_xpub_cache.size() == script_provider_cached.origins.size());
+ // Get all of the derived pubkeys
+ std::set<CPubKey> pubkeys;
+ for (const auto& xpub_map_pair : der_xpub_cache) {
+ for (const auto& xpub_pair : xpub_map_pair.second) {
+ const CExtPubKey& xpub = xpub_pair.second;
+ pubkeys.insert(xpub.pubkey);
+ }
+ }
+ // Derive one level from all of the parents
+ for (const auto& xpub_pair : parent_xpub_cache) {
+ const CExtPubKey& xpub = xpub_pair.second;
+ pubkeys.insert(xpub.pubkey);
+ CExtPubKey der;
+ xpub.Derive(der, i);
+ pubkeys.insert(der.pubkey);
+ }
+ for (const auto& origin_pair : script_provider_cached.origins) {
+ const CPubKey& pk = origin_pair.second.first;
+ BOOST_CHECK(pubkeys.count(pk) > 0);
+ }
+ } else {
+ // No xpub, nothing should be cached
+ BOOST_CHECK(der_xpub_cache.empty());
+ BOOST_CHECK(parent_xpub_cache.empty());
+ }
+
+ // Make sure we can expand using cached xpubs for unhardened derivation
+ if (!(flags & DERIVE_HARDENED)) {
+ // Evaluate the descriptor at i + 1
+ FlatSigningProvider script_provider1, script_provider_cached1;
+ std::vector<CScript> spks1, spk1_from_cache;
+ BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i + 1, key_provider, spks1, script_provider1, nullptr));
+
+ // Try again but use the cache from expanding i. That cache won't have the pubkeys for i + 1, but will have the parent xpub for derivation.
+ BOOST_CHECK(parse_pub->ExpandFromCache(i + 1, desc_cache, spk1_from_cache, script_provider_cached1));
+ BOOST_CHECK(spks1 == spk1_from_cache);
+ BOOST_CHECK(script_provider1.pubkeys == script_provider_cached1.pubkeys);
+ BOOST_CHECK(script_provider1.scripts == script_provider_cached1.scripts);
+ BOOST_CHECK(script_provider1.origins == script_provider_cached1.origins);
+ }
+
// For each of the produced scripts, verify solvability, and when possible, try to sign a transaction spending it.
for (size_t n = 0; n < spks.size(); ++n) {
BOOST_CHECK_EQUAL(ref[n], HexStr(spks[n].begin(), spks[n].end()));
@@ -181,29 +251,29 @@ void DoCheck(const std::string& prv, const std::string& pub, int flags, const st
BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv);
}
-void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
+void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const Optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
{
bool found_apostrophes_in_prv = false;
bool found_apostrophes_in_pub = false;
// Do not replace apostrophes with 'h' in prv and pub
- DoCheck(prv, pub, flags, scripts, paths);
+ DoCheck(prv, pub, flags, scripts, type, paths);
// Replace apostrophes with 'h' in prv but not in pub, if apostrophes are found in prv
if (prv.find('\'') != std::string::npos) {
found_apostrophes_in_prv = true;
- DoCheck(prv, pub, flags, scripts, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */false);
+ DoCheck(prv, pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */false);
}
// Replace apostrophes with 'h' in pub but not in prv, if apostrophes are found in pub
if (pub.find('\'') != std::string::npos) {
found_apostrophes_in_pub = true;
- DoCheck(prv, pub, flags, scripts, paths, /* replace_apostrophe_with_h_in_prv = */false, /*replace_apostrophe_with_h_in_pub = */true);
+ DoCheck(prv, pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */false, /*replace_apostrophe_with_h_in_pub = */true);
}
// Replace apostrophes with 'h' both in prv and in pub, if apostrophes are found in both
if (found_apostrophes_in_prv && found_apostrophes_in_pub) {
- DoCheck(prv, pub, flags, scripts, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */true);
+ DoCheck(prv, pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */true);
}
}
@@ -214,50 +284,50 @@ BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(descriptor_test)
{
// Basic single-key compressed
- Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
- Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}});
- Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, {{1,0x80000002UL,3,0x80000004UL}});
- Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}});
- Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
+ Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, nullopt);
+ Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}, nullopt);
+ Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, OutputType::LEGACY, {{1,0x80000002UL,3,0x80000004UL}});
+ Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}}, OutputType::BECH32);
+ Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, OutputType::P2SH_SEGWIT);
CheckUnparsable("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY2))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5))", "Pubkey '03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5' is invalid"); // Invalid pubkey
CheckUnparsable("pkh(deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh(deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "Key origin start '[ character expected but not found, got 'd' instead"); // Missing start bracket in key origin
CheckUnparsable("pkh([deadbeef]/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef]/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "Multiple ']' characters found for a single pubkey"); // Multiple end brackets in key origin
// Basic single-key uncompressed
- Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}});
- Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}});
- Check("pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}});
+ Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, nullopt);
+ Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}, nullopt);
+ Check("pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, OutputType::LEGACY);
CheckUnparsable("wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Uncompressed keys are not allowed"); // No uncompressed keys in witness
CheckUnparsable("wsh(pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "wsh(pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))", "Uncompressed keys are not allowed"); // No uncompressed keys in witness
CheckUnparsable("sh(wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "sh(wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))", "Uncompressed keys are not allowed"); // No uncompressed keys in witness
// Some unconventional single-key constructions
- Check("sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141857af51a5e516552b3086430fd8ce55f7c1a52487"}});
- Check("sh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141a31ad23bf49c247dd531a623c2ef57da3c400c587"}});
- Check("wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"00202e271faa2325c199d25d22e1ead982e45b64eeb4f31e73dbdf41bd4b5fec23fa"}});
- Check("wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"0020338e023079b91c58571b20e602d7805fb808c22473cbc391a41b1bd3a192e75b"}});
- Check("sh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a91472d0c5a3bfad8c3e7bd5303a72b94240e80b6f1787"}});
- Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}});
+ Check("sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141857af51a5e516552b3086430fd8ce55f7c1a52487"}}, OutputType::LEGACY);
+ Check("sh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141a31ad23bf49c247dd531a623c2ef57da3c400c587"}}, OutputType::LEGACY);
+ Check("wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"00202e271faa2325c199d25d22e1ead982e45b64eeb4f31e73dbdf41bd4b5fec23fa"}}, OutputType::BECH32);
+ Check("wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"0020338e023079b91c58571b20e602d7805fb808c22473cbc391a41b1bd3a192e75b"}}, OutputType::BECH32);
+ Check("sh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a91472d0c5a3bfad8c3e7bd5303a72b94240e80b6f1787"}}, OutputType::P2SH_SEGWIT);
+ Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}}, OutputType::P2SH_SEGWIT);
// Versions with BIP32 derivations
- Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}});
- Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, {{0}});
- Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, {{0xFFFFFFFFUL,0}});
- Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
- Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
- Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, {{0}, {1}});
+ Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}, nullopt);
+ Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, nullopt, {{0}});
+ Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{0xFFFFFFFFUL,0}});
+ Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, OutputType::BECH32, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
+ Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED | DERIVE_HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, OutputType::P2SH_SEGWIT, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
+ Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, nullopt, {{0}, {1}});
CheckUnparsable("combo([012345678]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([012345678]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "Fingerprint is not 4 bytes (9 characters instead of 8 characters)"); // Too long key fingerprint
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)", "Key path value 2147483648 is out of range"); // BIP 32 path element overflow
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/1aa)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1aa)", "Key path value '1aa' is not a valid uint32"); // Path is not valid uint
// Multisig constructions
- Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
- Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
- Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
- Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}});
- Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}});
- Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
- Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}});
+ Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt);
+ Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt);
+ Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt);
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
+ Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, nullopt, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}});
+ Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE | DERIVE_HARDENED, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, OutputType::BECH32, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
+ Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}}, OutputType::P2SH_SEGWIT);
CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))", "P2SH script is too large, 547 bytes is larger than 520 bytes"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
CheckUnparsable("wsh(multi(2,[aaaaaaaa][aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa][aaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Multiple ']' characters found for a single pubkey"); // Double key origin descriptor
CheckUnparsable("wsh(multi(2,[aaaagaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaagaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Fingerprint 'aaagaaaa' is not hex"); // Non hex fingerprint
@@ -280,8 +350,8 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
CheckUnparsable("wsh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "Cannot have wsh within wsh"); // Cannot embed P2WSH inside P2WSH
// Checksums
- Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}});
- Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#", "Expected 8 character checksum, not 0 characters"); // Empty checksum
CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfyq", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq", "Expected 8 character checksum, not 9 characters"); // Too long checksum
CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5", "Expected 8 character checksum, not 7 characters"); // Too short checksum
diff --git a/src/test/fuzz/addition_overflow.cpp b/src/test/fuzz/addition_overflow.cpp
new file mode 100644
index 0000000000..a455992b13
--- /dev/null
+++ b/src/test/fuzz/addition_overflow.cpp
@@ -0,0 +1,55 @@
+// 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/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#if defined(__has_builtin)
+#if __has_builtin(__builtin_add_overflow)
+#define HAVE_BUILTIN_ADD_OVERFLOW
+#endif
+#elif defined(__GNUC__) && (__GNUC__ >= 5)
+#define HAVE_BUILTIN_ADD_OVERFLOW
+#endif
+
+namespace {
+template <typename T>
+void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider)
+{
+ const T i = fuzzed_data_provider.ConsumeIntegral<T>();
+ const T j = fuzzed_data_provider.ConsumeIntegral<T>();
+ const bool is_addition_overflow_custom = AdditionOverflow(i, j);
+#if defined(HAVE_BUILTIN_ADD_OVERFLOW)
+ T result_builtin;
+ const bool is_addition_overflow_builtin = __builtin_add_overflow(i, j, &result_builtin);
+ assert(is_addition_overflow_custom == is_addition_overflow_builtin);
+ if (!is_addition_overflow_custom) {
+ assert(i + j == result_builtin);
+ }
+#else
+ if (!is_addition_overflow_custom) {
+ (void)(i + j);
+ }
+#endif
+}
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ TestAdditionOverflow<int64_t>(fuzzed_data_provider);
+ TestAdditionOverflow<uint64_t>(fuzzed_data_provider);
+ TestAdditionOverflow<int32_t>(fuzzed_data_provider);
+ TestAdditionOverflow<uint32_t>(fuzzed_data_provider);
+ TestAdditionOverflow<int16_t>(fuzzed_data_provider);
+ TestAdditionOverflow<uint16_t>(fuzzed_data_provider);
+ TestAdditionOverflow<char>(fuzzed_data_provider);
+ TestAdditionOverflow<unsigned char>(fuzzed_data_provider);
+ TestAdditionOverflow<signed char>(fuzzed_data_provider);
+}
diff --git a/src/test/fuzz/addrdb.cpp b/src/test/fuzz/addrdb.cpp
new file mode 100644
index 0000000000..f21ff3fac3
--- /dev/null
+++ b/src/test/fuzz/addrdb.cpp
@@ -0,0 +1,43 @@
+// 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 <optional.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ const CBanEntry ban_entry = [&] {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 3)) {
+ case 0:
+ return CBanEntry{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
+ break;
+ case 1:
+ return CBanEntry{fuzzed_data_provider.ConsumeIntegral<int64_t>(), fuzzed_data_provider.PickValueInArray<BanReason>({
+ BanReason::BanReasonUnknown,
+ BanReason::BanReasonNodeMisbehaving,
+ BanReason::BanReasonManuallyAdded,
+ })};
+ break;
+ case 2: {
+ const Optional<CBanEntry> ban_entry = ConsumeDeserializable<CBanEntry>(fuzzed_data_provider);
+ if (ban_entry) {
+ return *ban_entry;
+ }
+ break;
+ }
+ }
+ return CBanEntry{};
+ }();
+ assert(!ban_entry.banReasonToString().empty());
+}
diff --git a/src/test/fuzz/asmap.cpp b/src/test/fuzz/asmap.cpp
new file mode 100644
index 0000000000..7f3eef79a1
--- /dev/null
+++ b/src/test/fuzz/asmap.cpp
@@ -0,0 +1,28 @@
+// 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 <netaddress.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+
+#include <cstdint>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const Network network = fuzzed_data_provider.PickValueInArray({NET_IPV4, NET_IPV6});
+ if (fuzzed_data_provider.remaining_bytes() < 16) {
+ return;
+ }
+ CNetAddr net_addr;
+ net_addr.SetRaw(network, fuzzed_data_provider.ConsumeBytes<uint8_t>(16).data());
+ std::vector<bool> asmap;
+ for (const char cur_byte : fuzzed_data_provider.ConsumeRemainingBytes<char>()) {
+ for (int bit = 0; bit < 8; ++bit) {
+ asmap.push_back((cur_byte >> bit) & 1);
+ }
+ }
+ (void)net_addr.GetMappedAS(asmap);
+}
diff --git a/src/test/fuzz/base_encode_decode.cpp b/src/test/fuzz/base_encode_decode.cpp
index cb0fbdf76f..8d49f93c2f 100644
--- a/src/test/fuzz/base_encode_decode.cpp
+++ b/src/test/fuzz/base_encode_decode.cpp
@@ -1,12 +1,13 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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/fuzz/fuzz.h>
#include <base58.h>
-#include <util/string.h>
+#include <psbt.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <cassert>
#include <cstdint>
@@ -44,4 +45,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
assert(encoded_string == TrimString(encoded_string));
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
}
+
+ PartiallySignedTransaction psbt;
+ std::string error;
+ (void)DecodeBase64PSBT(psbt, random_encoded_string, error);
}
diff --git a/src/test/fuzz/block.cpp b/src/test/fuzz/block.cpp
index 431248de4a..f30fa03e0b 100644
--- a/src/test/fuzz/block.cpp
+++ b/src/test/fuzz/block.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -7,8 +7,8 @@
#include <consensus/validation.h>
#include <core_io.h>
#include <core_memusage.h>
-#include <pubkey.h>
#include <primitives/block.h>
+#include <pubkey.h>
#include <streams.h>
#include <test/fuzz/fuzz.h>
#include <validation.h>
@@ -19,7 +19,7 @@
void initialize()
{
- const static auto verify_handle = MakeUnique<ECCVerifyHandle>();
+ static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}
@@ -59,5 +59,11 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
(void)GetBlockWeight(block);
(void)GetWitnessCommitmentIndex(block);
- (void)RecursiveDynamicUsage(block);
+ const size_t raw_memory_size = RecursiveDynamicUsage(block);
+ const size_t raw_memory_size_as_shared_ptr = RecursiveDynamicUsage(std::make_shared<CBlock>(block));
+ assert(raw_memory_size_as_shared_ptr > raw_memory_size);
+ CBlock block_copy = block;
+ block_copy.SetNull();
+ const bool is_null = block_copy.IsNull();
+ assert(is_null);
}
diff --git a/src/test/fuzz/block_header.cpp b/src/test/fuzz/block_header.cpp
new file mode 100644
index 0000000000..92dcccc0e1
--- /dev/null
+++ b/src/test/fuzz/block_header.cpp
@@ -0,0 +1,41 @@
+// 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 <optional.h>
+#include <primitives/block.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <uint256.h>
+
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const Optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
+ if (!block_header) {
+ return;
+ }
+ {
+ const uint256 hash = block_header->GetHash();
+ static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
+ assert(hash != u256_max);
+ assert(block_header->GetBlockTime() == block_header->nTime);
+ assert(block_header->IsNull() == (block_header->nBits == 0));
+ }
+ {
+ CBlockHeader mut_block_header = *block_header;
+ mut_block_header.SetNull();
+ assert(mut_block_header.IsNull());
+ CBlock block{*block_header};
+ assert(block.GetBlockHeader().GetHash() == block_header->GetHash());
+ (void)block.ToString();
+ block.SetNull();
+ assert(block.GetBlockHeader().GetHash() == mut_block_header.GetHash());
+ }
+}
diff --git a/src/test/fuzz/blockfilter.cpp b/src/test/fuzz/blockfilter.cpp
new file mode 100644
index 0000000000..be9320dcbf
--- /dev/null
+++ b/src/test/fuzz/blockfilter.cpp
@@ -0,0 +1,44 @@
+// 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 <blockfilter.h>
+#include <optional.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const Optional<BlockFilter> block_filter = ConsumeDeserializable<BlockFilter>(fuzzed_data_provider);
+ if (!block_filter) {
+ return;
+ }
+ {
+ (void)block_filter->ComputeHeader(ConsumeUInt256(fuzzed_data_provider));
+ (void)block_filter->GetBlockHash();
+ (void)block_filter->GetEncodedFilter();
+ (void)block_filter->GetHash();
+ }
+ {
+ const BlockFilterType block_filter_type = block_filter->GetFilterType();
+ (void)BlockFilterTypeName(block_filter_type);
+ }
+ {
+ const GCSFilter gcs_filter = block_filter->GetFilter();
+ (void)gcs_filter.GetN();
+ (void)gcs_filter.GetParams();
+ (void)gcs_filter.GetEncoded();
+ (void)gcs_filter.Match(ConsumeRandomLengthByteVector(fuzzed_data_provider));
+ GCSFilter::ElementSet element_set;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ element_set.insert(ConsumeRandomLengthByteVector(fuzzed_data_provider));
+ gcs_filter.MatchAny(element_set);
+ }
+ }
+}
diff --git a/src/test/fuzz/bloom_filter.cpp b/src/test/fuzz/bloom_filter.cpp
new file mode 100644
index 0000000000..50036ce5bd
--- /dev/null
+++ b/src/test/fuzz/bloom_filter.cpp
@@ -0,0 +1,74 @@
+// 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 <bloom.h>
+#include <optional.h>
+#include <primitives/transaction.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <uint256.h>
+
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ CBloomFilter bloom_filter{
+ fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(1, 10000000),
+ 1.0 / fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(1, std::numeric_limits<unsigned int>::max()),
+ fuzzed_data_provider.ConsumeIntegral<unsigned int>(),
+ static_cast<unsigned char>(fuzzed_data_provider.PickValueInArray({BLOOM_UPDATE_NONE, BLOOM_UPDATE_ALL, BLOOM_UPDATE_P2PUBKEY_ONLY, BLOOM_UPDATE_MASK}))};
+ while (fuzzed_data_provider.remaining_bytes() > 0) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 4)) {
+ case 0: {
+ const std::vector<unsigned char> b = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ (void)bloom_filter.contains(b);
+ bloom_filter.insert(b);
+ const bool present = bloom_filter.contains(b);
+ assert(present);
+ break;
+ }
+ case 1: {
+ const Optional<COutPoint> out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
+ if (!out_point) {
+ break;
+ }
+ (void)bloom_filter.contains(*out_point);
+ bloom_filter.insert(*out_point);
+ const bool present = bloom_filter.contains(*out_point);
+ assert(present);
+ break;
+ }
+ case 2: {
+ const Optional<uint256> u256 = ConsumeDeserializable<uint256>(fuzzed_data_provider);
+ if (!u256) {
+ break;
+ }
+ (void)bloom_filter.contains(*u256);
+ bloom_filter.insert(*u256);
+ const bool present = bloom_filter.contains(*u256);
+ assert(present);
+ break;
+ }
+ case 3: {
+ const Optional<CMutableTransaction> mut_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ if (!mut_tx) {
+ break;
+ }
+ const CTransaction tx{*mut_tx};
+ (void)bloom_filter.IsRelevantAndUpdate(tx);
+ break;
+ }
+ case 4:
+ bloom_filter.UpdateEmptyFull();
+ break;
+ }
+ (void)bloom_filter.IsWithinSizeConstraints();
+ }
+}
diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp
new file mode 100644
index 0000000000..b322516cc7
--- /dev/null
+++ b/src/test/fuzz/chain.cpp
@@ -0,0 +1,65 @@
+// 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 <chain.h>
+#include <optional.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ Optional<CDiskBlockIndex> disk_block_index = ConsumeDeserializable<CDiskBlockIndex>(fuzzed_data_provider);
+ if (!disk_block_index) {
+ return;
+ }
+
+ const uint256 zero{};
+ disk_block_index->phashBlock = &zero;
+ (void)disk_block_index->GetBlockHash();
+ (void)disk_block_index->GetBlockPos();
+ (void)disk_block_index->GetBlockTime();
+ (void)disk_block_index->GetBlockTimeMax();
+ (void)disk_block_index->GetMedianTimePast();
+ (void)disk_block_index->GetUndoPos();
+ (void)disk_block_index->HaveTxsDownloaded();
+ (void)disk_block_index->IsValid();
+ (void)disk_block_index->ToString();
+
+ const CBlockHeader block_header = disk_block_index->GetBlockHeader();
+ (void)CDiskBlockIndex{*disk_block_index};
+ (void)disk_block_index->BuildSkip();
+
+ while (fuzzed_data_provider.ConsumeBool()) {
+ const BlockStatus block_status = fuzzed_data_provider.PickValueInArray({
+ BlockStatus::BLOCK_VALID_UNKNOWN,
+ BlockStatus::BLOCK_VALID_RESERVED,
+ BlockStatus::BLOCK_VALID_TREE,
+ BlockStatus::BLOCK_VALID_TRANSACTIONS,
+ BlockStatus::BLOCK_VALID_CHAIN,
+ BlockStatus::BLOCK_VALID_SCRIPTS,
+ BlockStatus::BLOCK_VALID_MASK,
+ BlockStatus::BLOCK_HAVE_DATA,
+ BlockStatus::BLOCK_HAVE_UNDO,
+ BlockStatus::BLOCK_HAVE_MASK,
+ BlockStatus::BLOCK_FAILED_VALID,
+ BlockStatus::BLOCK_FAILED_CHILD,
+ BlockStatus::BLOCK_FAILED_MASK,
+ BlockStatus::BLOCK_OPT_WITNESS,
+ });
+ if (block_status & ~BLOCK_VALID_MASK) {
+ continue;
+ }
+ (void)disk_block_index->RaiseValidity(block_status);
+ }
+
+ CBlockIndex block_index{block_header};
+ block_index.phashBlock = &zero;
+ (void)block_index.GetBlockHash();
+ (void)block_index.ToString();
+}
diff --git a/src/test/fuzz/checkqueue.cpp b/src/test/fuzz/checkqueue.cpp
new file mode 100644
index 0000000000..2ed097b827
--- /dev/null
+++ b/src/test/fuzz/checkqueue.cpp
@@ -0,0 +1,65 @@
+// 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 <checkqueue.h>
+#include <optional.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace {
+struct DumbCheck {
+ const bool result = false;
+
+ DumbCheck() = default;
+
+ explicit DumbCheck(const bool _result) : result(_result)
+ {
+ }
+
+ bool operator()() const
+ {
+ return result;
+ }
+
+ void swap(DumbCheck& x)
+ {
+ }
+};
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ const unsigned int batch_size = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 1024);
+ CCheckQueue<DumbCheck> check_queue_1{batch_size};
+ CCheckQueue<DumbCheck> check_queue_2{batch_size};
+ std::vector<DumbCheck> checks_1;
+ std::vector<DumbCheck> checks_2;
+ const int size = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1024);
+ for (int i = 0; i < size; ++i) {
+ const bool result = fuzzed_data_provider.ConsumeBool();
+ checks_1.emplace_back(result);
+ checks_2.emplace_back(result);
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ check_queue_1.Add(checks_1);
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ (void)check_queue_1.Wait();
+ }
+
+ CCheckQueueControl<DumbCheck> check_queue_control{&check_queue_2};
+ if (fuzzed_data_provider.ConsumeBool()) {
+ check_queue_control.Add(checks_2);
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ (void)check_queue_control.Wait();
+ }
+}
diff --git a/src/test/fuzz/cuckoocache.cpp b/src/test/fuzz/cuckoocache.cpp
new file mode 100644
index 0000000000..f674efe1b1
--- /dev/null
+++ b/src/test/fuzz/cuckoocache.cpp
@@ -0,0 +1,49 @@
+// 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 <cuckoocache.h>
+#include <optional.h>
+#include <script/sigcache.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <test/util/setup_common.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace {
+FuzzedDataProvider* fuzzed_data_provider_ptr = nullptr;
+
+struct RandomHasher {
+ template <uint8_t>
+ uint32_t operator()(const bool& /* unused */) const
+ {
+ assert(fuzzed_data_provider_ptr != nullptr);
+ return fuzzed_data_provider_ptr->ConsumeIntegral<uint32_t>();
+ }
+};
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ fuzzed_data_provider_ptr = &fuzzed_data_provider;
+ CuckooCache::cache<bool, RandomHasher> cuckoo_cache{};
+ if (fuzzed_data_provider.ConsumeBool()) {
+ const size_t megabytes = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 16);
+ cuckoo_cache.setup_bytes(megabytes << 20);
+ } else {
+ cuckoo_cache.setup(fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, 4096));
+ }
+ while (fuzzed_data_provider.ConsumeBool()) {
+ if (fuzzed_data_provider.ConsumeBool()) {
+ cuckoo_cache.insert(fuzzed_data_provider.ConsumeBool());
+ } else {
+ cuckoo_cache.contains(fuzzed_data_provider.ConsumeBool(), fuzzed_data_provider.ConsumeBool());
+ }
+ }
+ fuzzed_data_provider_ptr = nullptr;
+}
diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp
index 47d5038c26..001758ffdb 100644
--- a/src/test/fuzz/descriptor_parse.cpp
+++ b/src/test/fuzz/descriptor_parse.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -10,7 +10,7 @@
void initialize()
{
- static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+ static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}
@@ -20,6 +20,11 @@ void test_one_input(const std::vector<uint8_t>& buffer)
FlatSigningProvider signing_provider;
std::string error;
for (const bool require_checksum : {true, false}) {
- Parse(descriptor, signing_provider, error, require_checksum);
+ const auto desc = Parse(descriptor, signing_provider, error, require_checksum);
+ if (desc) {
+ (void)desc->ToString();
+ (void)desc->IsRange();
+ (void)desc->IsSolvable();
+ }
}
}
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index f06f339b9d..54793c890f 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -13,6 +13,7 @@
#include <key.h>
#include <merkleblock.h>
#include <net.h>
+#include <node/utxo_snapshot.h>
#include <primitives/block.h>
#include <protocol.h>
#include <psbt.h>
@@ -34,7 +35,7 @@
void initialize()
{
// Fuzzers using pubkey must hold an ECCVerifyHandle.
- static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+ static const ECCVerifyHandle verify_handle;
}
namespace {
@@ -214,9 +215,24 @@ void test_one_input(const std::vector<uint8_t>& buffer)
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
BlockTransactionsRequest btr;
DeserializeFromFuzzingInput(buffer, btr);
+#elif SNAPSHOTMETADATA_DESERIALIZE
+ SnapshotMetadata snapshot_metadata;
+ DeserializeFromFuzzingInput(buffer, snapshot_metadata);
+#elif UINT160_DESERIALIZE
+ uint160 u160;
+ DeserializeFromFuzzingInput(buffer, u160);
+ AssertEqualAfterSerializeDeserialize(u160);
+#elif 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 7acdd76857..c556599db3 100644
--- a/src/test/fuzz/eval_script.cpp
+++ b/src/test/fuzz/eval_script.cpp
@@ -1,18 +1,18 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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 <pubkey.h>
#include <script/interpreter.h>
-#include <test/fuzz/fuzz.h>
#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
#include <util/memory.h>
#include <limits>
void initialize()
{
- static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+ static const ECCVerifyHandle verify_handle;
}
void test_one_input(const std::vector<uint8_t>& buffer)
diff --git a/src/test/fuzz/fee_rate.cpp b/src/test/fuzz/fee_rate.cpp
new file mode 100644
index 0000000000..f3d44d9f93
--- /dev/null
+++ b/src/test/fuzz/fee_rate.cpp
@@ -0,0 +1,40 @@
+// 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 <amount.h>
+#include <policy/feerate.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <limits>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const CAmount satoshis_per_k = ConsumeMoney(fuzzed_data_provider);
+ const CFeeRate fee_rate{satoshis_per_k};
+
+ (void)fee_rate.GetFeePerK();
+ const size_t bytes = fuzzed_data_provider.ConsumeIntegral<size_t>();
+ if (!MultiplicationOverflow(static_cast<int64_t>(bytes), satoshis_per_k) && bytes <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
+ (void)fee_rate.GetFee(bytes);
+ }
+ (void)fee_rate.ToString();
+
+ const CAmount another_satoshis_per_k = ConsumeMoney(fuzzed_data_provider);
+ CFeeRate larger_fee_rate{another_satoshis_per_k};
+ larger_fee_rate += fee_rate;
+ if (satoshis_per_k != 0 && another_satoshis_per_k != 0) {
+ assert(fee_rate < larger_fee_rate);
+ assert(!(fee_rate > larger_fee_rate));
+ assert(!(fee_rate == larger_fee_rate));
+ assert(fee_rate <= larger_fee_rate);
+ assert(!(fee_rate >= larger_fee_rate));
+ assert(fee_rate != larger_fee_rate);
+ }
+}
diff --git a/src/test/fuzz/fees.cpp b/src/test/fuzz/fees.cpp
new file mode 100644
index 0000000000..f29acace23
--- /dev/null
+++ b/src/test/fuzz/fees.cpp
@@ -0,0 +1,29 @@
+// 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 <amount.h>
+#include <optional.h>
+#include <policy/fees.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <util/fees.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const CFeeRate minimal_incremental_fee{ConsumeMoney(fuzzed_data_provider)};
+ FeeFilterRounder fee_filter_rounder{minimal_incremental_fee};
+ while (fuzzed_data_provider.ConsumeBool()) {
+ const CAmount current_minimum_fee = ConsumeMoney(fuzzed_data_provider);
+ const CAmount rounded_fee = fee_filter_rounder.round(current_minimum_fee);
+ assert(MoneyRange(rounded_fee));
+ }
+ const FeeReason fee_reason = fuzzed_data_provider.PickValueInArray({FeeReason::NONE, FeeReason::HALF_ESTIMATE, FeeReason::FULL_ESTIMATE, FeeReason::DOUBLE_ESTIMATE, FeeReason::CONSERVATIVE, FeeReason::MEMPOOL_MIN, FeeReason::PAYTXFEE, FeeReason::FALLBACK, FeeReason::REQUIRED});
+ (void)StringForFeeReason(fee_reason);
+}
diff --git a/src/test/fuzz/flatfile.cpp b/src/test/fuzz/flatfile.cpp
new file mode 100644
index 0000000000..a55de77df7
--- /dev/null
+++ b/src/test/fuzz/flatfile.cpp
@@ -0,0 +1,30 @@
+// 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 <flatfile.h>
+#include <optional.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ Optional<FlatFilePos> flat_file_pos = ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
+ if (!flat_file_pos) {
+ return;
+ }
+ Optional<FlatFilePos> another_flat_file_pos = ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
+ if (another_flat_file_pos) {
+ assert((*flat_file_pos == *another_flat_file_pos) != (*flat_file_pos != *another_flat_file_pos));
+ }
+ (void)flat_file_pos->ToString();
+ flat_file_pos->SetNull();
+ assert(flat_file_pos->IsNull());
+}
diff --git a/src/test/fuzz/float.cpp b/src/test/fuzz/float.cpp
new file mode 100644
index 0000000000..a24bae5b35
--- /dev/null
+++ b/src/test/fuzz/float.cpp
@@ -0,0 +1,42 @@
+// 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 <memusage.h>
+#include <serialize.h>
+#include <streams.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <version.h>
+
+#include <cassert>
+#include <cstdint>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ {
+ const double d = fuzzed_data_provider.ConsumeFloatingPoint<double>();
+ (void)memusage::DynamicUsage(d);
+ assert(ser_uint64_to_double(ser_double_to_uint64(d)) == d);
+
+ CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
+ stream << d;
+ double d_deserialized;
+ stream >> d_deserialized;
+ assert(d == d_deserialized);
+ }
+
+ {
+ const float f = fuzzed_data_provider.ConsumeFloatingPoint<float>();
+ (void)memusage::DynamicUsage(f);
+ assert(ser_uint32_to_float(ser_float_to_uint32(f)) == f);
+
+ CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
+ stream << f;
+ float f_deserialized;
+ stream >> f_deserialized;
+ assert(f == f_deserialized);
+ }
+}
diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp
index a085e36911..6e2188fe86 100644
--- a/src/test/fuzz/fuzz.cpp
+++ b/src/test/fuzz/fuzz.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
diff --git a/src/test/fuzz/golomb_rice.cpp b/src/test/fuzz/golomb_rice.cpp
new file mode 100644
index 0000000000..3e20416116
--- /dev/null
+++ b/src/test/fuzz/golomb_rice.cpp
@@ -0,0 +1,112 @@
+// 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 <blockfilter.h>
+#include <serialize.h>
+#include <streams.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/util.h>
+#include <util/bytevectorhash.h>
+#include <util/golombrice.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iosfwd>
+#include <unordered_set>
+#include <vector>
+
+namespace {
+uint64_t MapIntoRange(const uint64_t x, const uint64_t n)
+{
+ const uint64_t x_hi = x >> 32;
+ const uint64_t x_lo = x & 0xFFFFFFFF;
+ const uint64_t n_hi = n >> 32;
+ const uint64_t n_lo = n & 0xFFFFFFFF;
+ const uint64_t ac = x_hi * n_hi;
+ const uint64_t ad = x_hi * n_lo;
+ const uint64_t bc = x_lo * n_hi;
+ const uint64_t bd = x_lo * n_lo;
+ const uint64_t mid34 = (bd >> 32) + (bc & 0xFFFFFFFF) + (ad & 0xFFFFFFFF);
+ const uint64_t upper64 = ac + (bc >> 32) + (ad >> 32) + (mid34 >> 32);
+ return upper64;
+}
+
+uint64_t HashToRange(const std::vector<uint8_t>& element, const uint64_t f)
+{
+ const uint64_t hash = CSipHasher(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL)
+ .Write(element.data(), element.size())
+ .Finalize();
+ return MapIntoRange(hash, f);
+}
+
+std::vector<uint64_t> BuildHashedSet(const std::unordered_set<std::vector<uint8_t>, ByteVectorHash>& elements, const uint64_t f)
+{
+ std::vector<uint64_t> hashed_elements;
+ hashed_elements.reserve(elements.size());
+ for (const std::vector<uint8_t>& element : elements) {
+ hashed_elements.push_back(HashToRange(element, f));
+ }
+ std::sort(hashed_elements.begin(), hashed_elements.end());
+ return hashed_elements;
+}
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ std::vector<uint8_t> golomb_rice_data;
+ std::vector<uint64_t> encoded_deltas;
+ {
+ std::unordered_set<std::vector<uint8_t>, ByteVectorHash> elements;
+ const int n = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 512);
+ for (int i = 0; i < n; ++i) {
+ elements.insert(ConsumeRandomLengthByteVector(fuzzed_data_provider, 16));
+ }
+ CVectorWriter stream(SER_NETWORK, 0, golomb_rice_data, 0);
+ WriteCompactSize(stream, static_cast<uint32_t>(elements.size()));
+ BitStreamWriter<CVectorWriter> bitwriter(stream);
+ if (!elements.empty()) {
+ uint64_t last_value = 0;
+ for (const uint64_t value : BuildHashedSet(elements, static_cast<uint64_t>(elements.size()) * static_cast<uint64_t>(BASIC_FILTER_M))) {
+ const uint64_t delta = value - last_value;
+ encoded_deltas.push_back(delta);
+ GolombRiceEncode(bitwriter, BASIC_FILTER_P, delta);
+ last_value = value;
+ }
+ }
+ bitwriter.Flush();
+ }
+
+ std::vector<uint64_t> decoded_deltas;
+ {
+ VectorReader stream{SER_NETWORK, 0, golomb_rice_data, 0};
+ BitStreamReader<VectorReader> bitreader(stream);
+ const uint32_t n = static_cast<uint32_t>(ReadCompactSize(stream));
+ for (uint32_t i = 0; i < n; ++i) {
+ decoded_deltas.push_back(GolombRiceDecode(bitreader, BASIC_FILTER_P));
+ }
+ }
+
+ assert(encoded_deltas == decoded_deltas);
+
+ {
+ const std::vector<uint8_t> random_bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider, 1024);
+ VectorReader stream{SER_NETWORK, 0, random_bytes, 0};
+ uint32_t n;
+ try {
+ n = static_cast<uint32_t>(ReadCompactSize(stream));
+ } catch (const std::ios_base::failure&) {
+ return;
+ }
+ BitStreamReader<VectorReader> bitreader(stream);
+ for (uint32_t i = 0; i < std::min<uint32_t>(n, 1024); ++i) {
+ try {
+ (void)GolombRiceDecode(bitreader, BASIC_FILTER_P);
+ } catch (const std::ios_base::failure&) {
+ }
+ }
+ }
+}
diff --git a/src/test/fuzz/hex.cpp b/src/test/fuzz/hex.cpp
index 54693180be..5fed17c17c 100644
--- a/src/test/fuzz/hex.cpp
+++ b/src/test/fuzz/hex.cpp
@@ -1,9 +1,14 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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 <core_io.h>
+#include <primitives/block.h>
+#include <pubkey.h>
+#include <rpc/util.h>
#include <test/fuzz/fuzz.h>
-
+#include <uint256.h>
+#include <univalue.h>
#include <util/strencodings.h>
#include <cassert>
@@ -11,6 +16,10 @@
#include <string>
#include <vector>
+void initialize() {
+ static const ECCVerifyHandle verify_handle;
+}
+
void test_one_input(const std::vector<uint8_t>& buffer)
{
const std::string random_hex_string(buffer.begin(), buffer.end());
@@ -19,4 +28,16 @@ void test_one_input(const std::vector<uint8_t>& buffer)
if (IsHex(random_hex_string)) {
assert(ToLower(random_hex_string) == hex_data);
}
+ (void)IsHexNumber(random_hex_string);
+ uint256 result;
+ (void)ParseHashStr(random_hex_string, result);
+ (void)uint256S(random_hex_string);
+ try {
+ (void)HexToPubKey(random_hex_string);
+ } catch (const UniValue&) {
+ }
+ CBlockHeader block_header;
+ (void)DecodeHexBlockHeader(block_header, random_hex_string);
+ CBlock block;
+ (void)DecodeHexBlk(block, random_hex_string);
}
diff --git a/src/test/fuzz/http_request.cpp b/src/test/fuzz/http_request.cpp
new file mode 100644
index 0000000000..ebf89749e9
--- /dev/null
+++ b/src/test/fuzz/http_request.cpp
@@ -0,0 +1,73 @@
+// 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 <httpserver.h>
+#include <netaddress.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <event2/buffer.h>
+#include <event2/event.h>
+#include <event2/http.h>
+#include <event2/http_struct.h>
+
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+// workaround for libevent versions before 2.1.1,
+// when internal functions didn't have underscores at the end
+#if LIBEVENT_VERSION_NUMBER < 0x02010100
+extern "C" int evhttp_parse_firstline(struct evhttp_request*, struct evbuffer*);
+extern "C" int evhttp_parse_headers(struct evhttp_request*, struct evbuffer*);
+inline int evhttp_parse_firstline_(struct evhttp_request* r, struct evbuffer* b)
+{
+ return evhttp_parse_firstline(r, b);
+}
+inline int evhttp_parse_headers_(struct evhttp_request* r, struct evbuffer* b)
+{
+ return evhttp_parse_headers(r, b);
+}
+#else
+extern "C" int evhttp_parse_firstline_(struct evhttp_request*, struct evbuffer*);
+extern "C" int evhttp_parse_headers_(struct evhttp_request*, struct evbuffer*);
+#endif
+
+std::string RequestMethodString(HTTPRequest::RequestMethod m);
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ evhttp_request* evreq = evhttp_request_new(nullptr, nullptr);
+ assert(evreq != nullptr);
+ evreq->kind = EVHTTP_REQUEST;
+ evbuffer* evbuf = evbuffer_new();
+ assert(evbuf != nullptr);
+ const std::vector<uint8_t> http_buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, 4096);
+ evbuffer_add(evbuf, http_buffer.data(), http_buffer.size());
+ if (evhttp_parse_firstline_(evreq, evbuf) != 1 || evhttp_parse_headers_(evreq, evbuf) != 1) {
+ evbuffer_free(evbuf);
+ evhttp_request_free(evreq);
+ return;
+ }
+
+ HTTPRequest http_request{evreq, true};
+ const HTTPRequest::RequestMethod request_method = http_request.GetRequestMethod();
+ (void)RequestMethodString(request_method);
+ (void)http_request.GetURI();
+ (void)http_request.GetHeader("Host");
+ const std::string header = fuzzed_data_provider.ConsumeRandomLengthString(16);
+ (void)http_request.GetHeader(header);
+ (void)http_request.WriteHeader(header, fuzzed_data_provider.ConsumeRandomLengthString(16));
+ (void)http_request.GetHeader(header);
+ const std::string body = http_request.ReadBody();
+ assert(body.empty());
+ const CService service = http_request.GetPeer();
+ assert(service.ToString() == "[::]:0");
+
+ evbuffer_free(evbuf);
+ evhttp_request_free(evreq);
+}
diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp
index 723938bcdb..35d6804d4f 100644
--- a/src/test/fuzz/integer.cpp
+++ b/src/test/fuzz/integer.cpp
@@ -1,7 +1,8 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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 <amount.h>
#include <arith_uint256.h>
#include <compressor.h>
#include <consensus/merkle.h>
@@ -13,20 +14,30 @@
#include <netbase.h>
#include <policy/settings.h>
#include <pow.h>
+#include <protocol.h>
#include <pubkey.h>
#include <rpc/util.h>
#include <script/signingprovider.h>
#include <script/standard.h>
#include <serialize.h>
+#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
#include <uint256.h>
+#include <util/check.h>
+#include <util/moneystr.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <util/system.h>
#include <util/time.h>
+#include <version.h>
#include <cassert>
+#include <chrono>
+#include <ctime>
#include <limits>
+#include <set>
#include <vector>
void initialize()
@@ -53,10 +64,18 @@ void test_one_input(const std::vector<uint8_t>& buffer)
// We cannot assume a specific value of std::is_signed<char>::value:
// ConsumeIntegral<char>() instead of casting from {u,}int8_t.
const char ch = fuzzed_data_provider.ConsumeIntegral<char>();
+ const bool b = fuzzed_data_provider.ConsumeBool();
const Consensus::Params& consensus_params = Params().GetConsensus();
(void)CheckProofOfWork(u256, u32, consensus_params);
- (void)CompressAmount(u64);
+ if (u64 <= MAX_MONEY) {
+ const uint64_t compressed_money_amount = CompressAmount(u64);
+ assert(u64 == DecompressAmount(compressed_money_amount));
+ static const uint64_t compressed_money_amount_max = CompressAmount(MAX_MONEY - 1);
+ assert(compressed_money_amount <= compressed_money_amount_max);
+ } else {
+ (void)CompressAmount(u64);
+ }
static const uint256 u256_min(uint256S("0000000000000000000000000000000000000000000000000000000000000000"));
static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
const std::vector<uint256> v256{u256, u256_min, u256_max};
@@ -65,16 +84,27 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)DecompressAmount(u64);
(void)FormatISO8601Date(i64);
(void)FormatISO8601DateTime(i64);
+ // FormatMoney(i) not defined when i == std::numeric_limits<int64_t>::min()
+ if (i64 != std::numeric_limits<int64_t>::min()) {
+ int64_t parsed_money;
+ if (ParseMoney(FormatMoney(i64), parsed_money)) {
+ assert(parsed_money == i64);
+ }
+ }
(void)GetSizeOfCompactSize(u64);
(void)GetSpecialScriptSize(u32);
- // (void)GetVirtualTransactionSize(i64, i64); // function defined only for a subset of int64_t inputs
- // (void)GetVirtualTransactionSize(i64, i64, u32); // function defined only for a subset of int64_t/uint32_t inputs
+ if (!MultiplicationOverflow(i64, static_cast<int64_t>(::nBytesPerSigOp)) && !AdditionOverflow(i64 * ::nBytesPerSigOp, static_cast<int64_t>(4))) {
+ (void)GetVirtualTransactionSize(i64, i64);
+ }
+ if (!MultiplicationOverflow(i64, static_cast<int64_t>(u32)) && !AdditionOverflow(i64, static_cast<int64_t>(4)) && !AdditionOverflow(i64 * u32, static_cast<int64_t>(4))) {
+ (void)GetVirtualTransactionSize(i64, i64, u32);
+ }
(void)HexDigit(ch);
- (void)i64tostr(i64);
+ (void)MoneyRange(i64);
+ (void)ToString(i64);
(void)IsDigit(ch);
(void)IsSpace(ch);
(void)IsSwitchChar(ch);
- (void)itostr(i32);
(void)memusage::DynamicUsage(ch);
(void)memusage::DynamicUsage(i16);
(void)memusage::DynamicUsage(i32);
@@ -86,6 +116,12 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)memusage::DynamicUsage(u8);
const unsigned char uch = static_cast<unsigned char>(u8);
(void)memusage::DynamicUsage(uch);
+ {
+ const std::set<int64_t> i64s{i64, static_cast<int64_t>(u64)};
+ const size_t dynamic_usage = memusage::DynamicUsage(i64s);
+ const size_t incremental_dynamic_usage = memusage::IncrementalDynamicUsage(i64s);
+ assert(dynamic_usage == incremental_dynamic_usage * i64s.size());
+ }
(void)MillisToTimeval(i64);
const double d = ser_uint64_to_double(u64);
assert(ser_double_to_uint64(d) == u64);
@@ -95,6 +131,24 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)SipHashUint256(u64, u64, u256);
(void)SipHashUint256Extra(u64, u64, u256, u32);
(void)ToLower(ch);
+ (void)ToUpper(ch);
+ // ValueFromAmount(i) not defined when i == std::numeric_limits<int64_t>::min()
+ if (i64 != std::numeric_limits<int64_t>::min()) {
+ int64_t parsed_money;
+ if (ParseMoney(ValueFromAmount(i64).getValStr(), parsed_money)) {
+ assert(parsed_money == i64);
+ }
+ }
+ if (i32 >= 0 && i32 <= 16) {
+ assert(i32 == CScript::DecodeOP_N(CScript::EncodeOP_N(i32)));
+ }
+
+ const std::chrono::seconds seconds{i64};
+ assert(count_seconds(seconds) == i64);
+
+ const CScriptNum script_num{i64};
+ (void)script_num.getint();
+ (void)script_num.getvch();
const arith_uint256 au256 = UintToArith256(u256);
assert(ArithToUint256(au256) == u256);
@@ -124,4 +178,118 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)GetScriptForDestination(destination);
(void)IsValidDestination(destination);
}
+
+ {
+ CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
+
+ uint256 deserialized_u256;
+ stream << u256;
+ stream >> deserialized_u256;
+ assert(u256 == deserialized_u256 && stream.empty());
+
+ uint160 deserialized_u160;
+ stream << u160;
+ stream >> deserialized_u160;
+ assert(u160 == deserialized_u160 && stream.empty());
+
+ uint64_t deserialized_u64;
+ stream << u64;
+ stream >> deserialized_u64;
+ assert(u64 == deserialized_u64 && stream.empty());
+
+ int64_t deserialized_i64;
+ stream << i64;
+ stream >> deserialized_i64;
+ assert(i64 == deserialized_i64 && stream.empty());
+
+ uint32_t deserialized_u32;
+ stream << u32;
+ stream >> deserialized_u32;
+ assert(u32 == deserialized_u32 && stream.empty());
+
+ int32_t deserialized_i32;
+ stream << i32;
+ stream >> deserialized_i32;
+ assert(i32 == deserialized_i32 && stream.empty());
+
+ uint16_t deserialized_u16;
+ stream << u16;
+ stream >> deserialized_u16;
+ assert(u16 == deserialized_u16 && stream.empty());
+
+ int16_t deserialized_i16;
+ stream << i16;
+ stream >> deserialized_i16;
+ assert(i16 == deserialized_i16 && stream.empty());
+
+ uint8_t deserialized_u8;
+ stream << u8;
+ stream >> deserialized_u8;
+ assert(u8 == deserialized_u8 && stream.empty());
+
+ int8_t deserialized_i8;
+ stream << i8;
+ stream >> deserialized_i8;
+ assert(i8 == deserialized_i8 && stream.empty());
+
+ char deserialized_ch;
+ stream << ch;
+ stream >> deserialized_ch;
+ assert(ch == deserialized_ch && stream.empty());
+
+ bool deserialized_b;
+ stream << b;
+ stream >> deserialized_b;
+ assert(b == deserialized_b && stream.empty());
+ }
+
+ {
+ const ServiceFlags service_flags = (ServiceFlags)u64;
+ (void)HasAllDesirableServiceFlags(service_flags);
+ (void)MayHaveUsefulAddressDB(service_flags);
+ }
+
+ {
+ CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
+
+ ser_writedata64(stream, u64);
+ const uint64_t deserialized_u64 = ser_readdata64(stream);
+ assert(u64 == deserialized_u64 && stream.empty());
+
+ ser_writedata32(stream, u32);
+ const uint32_t deserialized_u32 = ser_readdata32(stream);
+ assert(u32 == deserialized_u32 && stream.empty());
+
+ ser_writedata32be(stream, u32);
+ const uint32_t deserialized_u32be = ser_readdata32be(stream);
+ assert(u32 == deserialized_u32be && stream.empty());
+
+ ser_writedata16(stream, u16);
+ const uint16_t deserialized_u16 = ser_readdata16(stream);
+ assert(u16 == deserialized_u16 && stream.empty());
+
+ ser_writedata16be(stream, u16);
+ const uint16_t deserialized_u16be = ser_readdata16be(stream);
+ assert(u16 == deserialized_u16be && stream.empty());
+
+ ser_writedata8(stream, u8);
+ const uint8_t deserialized_u8 = ser_readdata8(stream);
+ assert(u8 == deserialized_u8 && stream.empty());
+ }
+
+ {
+ CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
+
+ WriteCompactSize(stream, u64);
+ try {
+ const uint64_t deserialized_u64 = ReadCompactSize(stream);
+ assert(u64 == deserialized_u64 && stream.empty());
+ } catch (const std::ios_base::failure&) {
+ }
+ }
+
+ try {
+ CHECK_NONFATAL(b);
+ } catch (const NonFatalCheckError&) {
+ }
}
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
new file mode 100644
index 0000000000..1919a5f881
--- /dev/null
+++ b/src/test/fuzz/key.cpp
@@ -0,0 +1,309 @@
+// 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 <key.h>
+#include <key_io.h>
+#include <outputtype.h>
+#include <policy/policy.h>
+#include <pubkey.h>
+#include <rpc/util.h>
+#include <script/keyorigin.h>
+#include <script/script.h>
+#include <script/sign.h>
+#include <script/signingprovider.h>
+#include <script/standard.h>
+#include <streams.h>
+#include <test/fuzz/fuzz.h>
+#include <util/memory.h>
+#include <util/strencodings.h>
+
+#include <cassert>
+#include <cstdint>
+#include <numeric>
+#include <string>
+#include <vector>
+
+void initialize()
+{
+ static const ECCVerifyHandle ecc_verify_handle;
+ ECC_Start();
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ const CKey key = [&] {
+ CKey k;
+ k.Set(buffer.begin(), buffer.end(), true);
+ return k;
+ }();
+ if (!key.IsValid()) {
+ return;
+ }
+
+ {
+ assert(key.begin() + key.size() == key.end());
+ assert(key.IsCompressed());
+ assert(key.size() == 32);
+ assert(DecodeSecret(EncodeSecret(key)) == key);
+ }
+
+ {
+ CKey invalid_key;
+ assert(!(invalid_key == key));
+ assert(!invalid_key.IsCompressed());
+ assert(!invalid_key.IsValid());
+ assert(invalid_key.size() == 0);
+ }
+
+ {
+ CKey uncompressed_key;
+ uncompressed_key.Set(buffer.begin(), buffer.end(), false);
+ assert(!(uncompressed_key == key));
+ assert(!uncompressed_key.IsCompressed());
+ assert(key.size() == 32);
+ assert(uncompressed_key.begin() + uncompressed_key.size() == uncompressed_key.end());
+ assert(uncompressed_key.IsValid());
+ }
+
+ {
+ CKey copied_key;
+ copied_key.Set(key.begin(), key.end(), key.IsCompressed());
+ assert(copied_key == key);
+ }
+
+ {
+ CKey negated_key = key;
+ negated_key.Negate();
+ assert(negated_key.IsValid());
+ assert(!(negated_key == key));
+
+ negated_key.Negate();
+ assert(negated_key == key);
+ }
+
+ const uint256 random_uint256 = Hash(buffer.begin(), buffer.end());
+
+ {
+ CKey child_key;
+ ChainCode child_chaincode;
+ const bool ok = key.Derive(child_key, child_chaincode, 0, random_uint256);
+ assert(ok);
+ assert(child_key.IsValid());
+ assert(!(child_key == key));
+ assert(child_chaincode != random_uint256);
+ }
+
+ const CPubKey pubkey = key.GetPubKey();
+
+ {
+ assert(pubkey.size() == 33);
+ assert(key.VerifyPubKey(pubkey));
+ assert(pubkey.GetHash() != random_uint256);
+ assert(pubkey.begin() + pubkey.size() == pubkey.end());
+ assert(pubkey.data() == pubkey.begin());
+ assert(pubkey.IsCompressed());
+ assert(pubkey.IsValid());
+ assert(pubkey.IsFullyValid());
+ assert(HexToPubKey(HexStr(pubkey.begin(), pubkey.end())) == pubkey);
+ assert(GetAllDestinationsForKey(pubkey).size() == 3);
+ }
+
+ {
+ CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
+ pubkey.Serialize(data_stream);
+
+ CPubKey pubkey_deserialized;
+ pubkey_deserialized.Unserialize(data_stream);
+ assert(pubkey_deserialized == pubkey);
+ }
+
+ {
+ const CScript tx_pubkey_script = GetScriptForRawPubKey(pubkey);
+ assert(!tx_pubkey_script.IsPayToScriptHash());
+ assert(!tx_pubkey_script.IsPayToWitnessScriptHash());
+ assert(!tx_pubkey_script.IsPushOnly());
+ assert(!tx_pubkey_script.IsUnspendable());
+ assert(tx_pubkey_script.HasValidOps());
+ assert(tx_pubkey_script.size() == 35);
+
+ const CScript tx_multisig_script = GetScriptForMultisig(1, {pubkey});
+ assert(!tx_multisig_script.IsPayToScriptHash());
+ assert(!tx_multisig_script.IsPayToWitnessScriptHash());
+ assert(!tx_multisig_script.IsPushOnly());
+ assert(!tx_multisig_script.IsUnspendable());
+ assert(tx_multisig_script.HasValidOps());
+ assert(tx_multisig_script.size() == 37);
+
+ FillableSigningProvider fillable_signing_provider;
+ assert(IsSolvable(fillable_signing_provider, tx_pubkey_script));
+ assert(IsSolvable(fillable_signing_provider, tx_multisig_script));
+ assert(!IsSegWitOutput(fillable_signing_provider, tx_pubkey_script));
+ assert(!IsSegWitOutput(fillable_signing_provider, tx_multisig_script));
+ assert(fillable_signing_provider.GetKeys().size() == 0);
+ assert(!fillable_signing_provider.HaveKey(pubkey.GetID()));
+
+ const bool ok_add_key = fillable_signing_provider.AddKey(key);
+ assert(ok_add_key);
+ assert(fillable_signing_provider.HaveKey(pubkey.GetID()));
+
+ FillableSigningProvider fillable_signing_provider_pub;
+ assert(!fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
+
+ const bool ok_add_key_pubkey = fillable_signing_provider_pub.AddKeyPubKey(key, pubkey);
+ assert(ok_add_key_pubkey);
+ assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
+
+ txnouttype which_type_tx_pubkey;
+ const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, which_type_tx_pubkey);
+ assert(is_standard_tx_pubkey);
+ assert(which_type_tx_pubkey == txnouttype::TX_PUBKEY);
+
+ txnouttype which_type_tx_multisig;
+ const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, which_type_tx_multisig);
+ assert(is_standard_tx_multisig);
+ assert(which_type_tx_multisig == txnouttype::TX_MULTISIG);
+
+ std::vector<std::vector<unsigned char>> v_solutions_ret_tx_pubkey;
+ const txnouttype outtype_tx_pubkey = Solver(tx_pubkey_script, v_solutions_ret_tx_pubkey);
+ assert(outtype_tx_pubkey == txnouttype::TX_PUBKEY);
+ assert(v_solutions_ret_tx_pubkey.size() == 1);
+ assert(v_solutions_ret_tx_pubkey[0].size() == 33);
+
+ std::vector<std::vector<unsigned char>> v_solutions_ret_tx_multisig;
+ const txnouttype outtype_tx_multisig = Solver(tx_multisig_script, v_solutions_ret_tx_multisig);
+ assert(outtype_tx_multisig == txnouttype::TX_MULTISIG);
+ assert(v_solutions_ret_tx_multisig.size() == 3);
+ assert(v_solutions_ret_tx_multisig[0].size() == 1);
+ assert(v_solutions_ret_tx_multisig[1].size() == 33);
+ assert(v_solutions_ret_tx_multisig[2].size() == 1);
+
+ OutputType output_type{};
+ const CTxDestination tx_destination = GetDestinationForKey(pubkey, output_type);
+ assert(output_type == OutputType::LEGACY);
+ assert(IsValidDestination(tx_destination));
+ assert(CTxDestination{PKHash{pubkey}} == tx_destination);
+
+ const CScript script_for_destination = GetScriptForDestination(tx_destination);
+ assert(script_for_destination.size() == 25);
+
+ const std::string destination_address = EncodeDestination(tx_destination);
+ assert(DecodeDestination(destination_address) == tx_destination);
+
+ const CPubKey pubkey_from_address_string = AddrToPubKey(fillable_signing_provider, destination_address);
+ assert(pubkey_from_address_string == pubkey);
+
+ CKeyID key_id = pubkey.GetID();
+ assert(!key_id.IsNull());
+ assert(key_id == CKeyID{key_id});
+ assert(key_id == GetKeyForDestination(fillable_signing_provider, tx_destination));
+
+ CPubKey pubkey_out;
+ const bool ok_get_pubkey = fillable_signing_provider.GetPubKey(key_id, pubkey_out);
+ assert(ok_get_pubkey);
+
+ CKey key_out;
+ const bool ok_get_key = fillable_signing_provider.GetKey(key_id, key_out);
+ assert(ok_get_key);
+ assert(fillable_signing_provider.GetKeys().size() == 1);
+ assert(fillable_signing_provider.HaveKey(key_id));
+
+ KeyOriginInfo key_origin_info;
+ const bool ok_get_key_origin = fillable_signing_provider.GetKeyOrigin(key_id, key_origin_info);
+ assert(!ok_get_key_origin);
+ }
+
+ {
+ const std::vector<unsigned char> vch_pubkey{pubkey.begin(), pubkey.end()};
+ assert(CPubKey::ValidSize(vch_pubkey));
+ assert(!CPubKey::ValidSize({pubkey.begin(), pubkey.begin() + pubkey.size() - 1}));
+
+ const CPubKey pubkey_ctor_1{vch_pubkey};
+ assert(pubkey == pubkey_ctor_1);
+
+ const CPubKey pubkey_ctor_2{vch_pubkey.begin(), vch_pubkey.end()};
+ assert(pubkey == pubkey_ctor_2);
+
+ CPubKey pubkey_set;
+ pubkey_set.Set(vch_pubkey.begin(), vch_pubkey.end());
+ assert(pubkey == pubkey_set);
+ }
+
+ {
+ const CPubKey invalid_pubkey{};
+ assert(!invalid_pubkey.IsValid());
+ assert(!invalid_pubkey.IsFullyValid());
+ assert(!(pubkey == invalid_pubkey));
+ assert(pubkey != invalid_pubkey);
+ assert(pubkey < invalid_pubkey);
+ }
+
+ {
+ // Cover CPubKey's operator[](unsigned int pos)
+ unsigned int sum = 0;
+ for (size_t i = 0; i < pubkey.size(); ++i) {
+ sum += pubkey[i];
+ }
+ assert(std::accumulate(pubkey.begin(), pubkey.end(), 0U) == sum);
+ }
+
+ {
+ CPubKey decompressed_pubkey = pubkey;
+ assert(decompressed_pubkey.IsCompressed());
+
+ const bool ok = decompressed_pubkey.Decompress();
+ assert(ok);
+ assert(!decompressed_pubkey.IsCompressed());
+ assert(decompressed_pubkey.size() == 65);
+ }
+
+ {
+ std::vector<unsigned char> vch_sig;
+ const bool ok = key.Sign(random_uint256, vch_sig, false);
+ assert(ok);
+ assert(pubkey.Verify(random_uint256, vch_sig));
+ assert(CPubKey::CheckLowS(vch_sig));
+
+ const std::vector<unsigned char> vch_invalid_sig{vch_sig.begin(), vch_sig.begin() + vch_sig.size() - 1};
+ assert(!pubkey.Verify(random_uint256, vch_invalid_sig));
+ assert(!CPubKey::CheckLowS(vch_invalid_sig));
+ }
+
+ {
+ std::vector<unsigned char> vch_compact_sig;
+ const bool ok_sign_compact = key.SignCompact(random_uint256, vch_compact_sig);
+ assert(ok_sign_compact);
+
+ CPubKey recover_pubkey;
+ const bool ok_recover_compact = recover_pubkey.RecoverCompact(random_uint256, vch_compact_sig);
+ assert(ok_recover_compact);
+ assert(recover_pubkey == pubkey);
+ }
+
+ {
+ CPubKey child_pubkey;
+ ChainCode child_chaincode;
+ const bool ok = pubkey.Derive(child_pubkey, child_chaincode, 0, random_uint256);
+ assert(ok);
+ assert(child_pubkey != pubkey);
+ assert(child_pubkey.IsCompressed());
+ assert(child_pubkey.IsFullyValid());
+ assert(child_pubkey.IsValid());
+ assert(child_pubkey.size() == 33);
+ assert(child_chaincode != random_uint256);
+ }
+
+ const CPrivKey priv_key = key.GetPrivKey();
+
+ {
+ for (const bool skip_check : {true, false}) {
+ CKey loaded_key;
+ const bool ok = loaded_key.Load(priv_key, pubkey, skip_check);
+ assert(ok);
+ assert(key == loaded_key);
+ }
+ }
+}
diff --git a/src/test/fuzz/key_io.cpp b/src/test/fuzz/key_io.cpp
new file mode 100644
index 0000000000..62aefb650d
--- /dev/null
+++ b/src/test/fuzz/key_io.cpp
@@ -0,0 +1,50 @@
+// 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 <key_io.h>
+#include <rpc/util.h>
+#include <script/signingprovider.h>
+#include <script/standard.h>
+#include <test/fuzz/fuzz.h>
+
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void initialize()
+{
+ static const ECCVerifyHandle verify_handle;
+ ECC_Start();
+ SelectParams(CBaseChainParams::MAIN);
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ const std::string random_string(buffer.begin(), buffer.end());
+
+ const CKey key = DecodeSecret(random_string);
+ if (key.IsValid()) {
+ assert(key == DecodeSecret(EncodeSecret(key)));
+ }
+
+ const CExtKey ext_key = DecodeExtKey(random_string);
+ if (ext_key.key.size() == 32) {
+ assert(ext_key == DecodeExtKey(EncodeExtKey(ext_key)));
+ }
+
+ const CExtPubKey ext_pub_key = DecodeExtPubKey(random_string);
+ if (ext_pub_key.pubkey.size() == CPubKey::COMPRESSED_SIZE) {
+ assert(ext_pub_key == DecodeExtPubKey(EncodeExtPubKey(ext_pub_key)));
+ }
+
+ const CTxDestination tx_destination = DecodeDestination(random_string);
+ (void)DescribeAddress(tx_destination);
+ (void)GetKeyForDestination(/* store */ {}, tx_destination);
+ (void)GetScriptForDestination(tx_destination);
+ (void)IsValidDestination(tx_destination);
+
+ (void)IsValidDestinationString(random_string);
+}
diff --git a/src/test/fuzz/kitchen_sink.cpp b/src/test/fuzz/kitchen_sink.cpp
new file mode 100644
index 0000000000..af6dc71322
--- /dev/null
+++ b/src/test/fuzz/kitchen_sink.cpp
@@ -0,0 +1,25 @@
+// 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 <rpc/util.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <util/error.h>
+
+#include <cstdint>
+#include <vector>
+
+// 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)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ const TransactionError transaction_error = fuzzed_data_provider.PickValueInArray<TransactionError>({TransactionError::OK, TransactionError::MISSING_INPUTS, TransactionError::ALREADY_IN_CHAIN, TransactionError::P2P_DISABLED, TransactionError::MEMPOOL_REJECTED, TransactionError::MEMPOOL_ERROR, TransactionError::INVALID_PSBT, TransactionError::PSBT_MISMATCH, TransactionError::SIGHASH_MISMATCH, TransactionError::MAX_FEE_EXCEEDED});
+ (void)JSONRPCTransactionError(transaction_error);
+ (void)RPCErrorFromTransactionError(transaction_error);
+ (void)TransactionErrorString(transaction_error);
+}
diff --git a/src/test/fuzz/locale.cpp b/src/test/fuzz/locale.cpp
new file mode 100644
index 0000000000..3597f51e51
--- /dev/null
+++ b/src/test/fuzz/locale.cpp
@@ -0,0 +1,96 @@
+// 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/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <tinyformat.h>
+#include <util/strencodings.h>
+#include <util/string.h>
+
+#include <cassert>
+#include <clocale>
+#include <cstdint>
+#include <locale>
+#include <string>
+#include <vector>
+
+namespace {
+const std::string locale_identifiers[] = {
+ "C", "C.UTF-8", "aa_DJ", "aa_DJ.ISO-8859-1", "aa_DJ.UTF-8", "aa_ER", "aa_ER.UTF-8", "aa_ET", "aa_ET.UTF-8", "af_ZA", "af_ZA.ISO-8859-1", "af_ZA.UTF-8", "agr_PE", "agr_PE.UTF-8", "ak_GH", "ak_GH.UTF-8", "am_ET", "am_ET.UTF-8", "an_ES", "an_ES.ISO-8859-15", "an_ES.UTF-8", "anp_IN", "anp_IN.UTF-8", "ar_AE", "ar_AE.ISO-8859-6", "ar_AE.UTF-8", "ar_BH", "ar_BH.ISO-8859-6", "ar_BH.UTF-8", "ar_DZ", "ar_DZ.ISO-8859-6", "ar_DZ.UTF-8", "ar_EG", "ar_EG.ISO-8859-6", "ar_EG.UTF-8", "ar_IN", "ar_IN.UTF-8", "ar_IQ", "ar_IQ.ISO-8859-6", "ar_IQ.UTF-8", "ar_JO", "ar_JO.ISO-8859-6", "ar_JO.UTF-8", "ar_KW", "ar_KW.ISO-8859-6", "ar_KW.UTF-8", "ar_LB", "ar_LB.ISO-8859-6", "ar_LB.UTF-8", "ar_LY", "ar_LY.ISO-8859-6", "ar_LY.UTF-8", "ar_MA", "ar_MA.ISO-8859-6", "ar_MA.UTF-8", "ar_OM", "ar_OM.ISO-8859-6", "ar_OM.UTF-8", "ar_QA", "ar_QA.ISO-8859-6", "ar_QA.UTF-8", "ar_SA", "ar_SA.ISO-8859-6", "ar_SA.UTF-8", "ar_SD", "ar_SD.ISO-8859-6", "ar_SD.UTF-8", "ar_SS", "ar_SS.UTF-8", "ar_SY", "ar_SY.ISO-8859-6", "ar_SY.UTF-8", "ar_TN", "ar_TN.ISO-8859-6", "ar_TN.UTF-8", "ar_YE", "ar_YE.ISO-8859-6", "ar_YE.UTF-8", "as_IN", "as_IN.UTF-8", "ast_ES", "ast_ES.ISO-8859-15", "ast_ES.UTF-8", "ayc_PE", "ayc_PE.UTF-8", "az_AZ", "az_AZ.UTF-8", "az_IR", "az_IR.UTF-8", "be_BY", "be_BY.CP1251", "be_BY.UTF-8", "bem_ZM", "bem_ZM.UTF-8", "ber_DZ", "ber_DZ.UTF-8", "ber_MA", "ber_MA.UTF-8", "bg_BG", "bg_BG.CP1251", "bg_BG.UTF-8", "bho_IN", "bho_IN.UTF-8", "bho_NP", "bho_NP.UTF-8", "bi_VU", "bi_VU.UTF-8", "bn_BD", "bn_BD.UTF-8", "bn_IN", "bn_IN.UTF-8", "bo_CN", "bo_CN.UTF-8", "bo_IN", "bo_IN.UTF-8", "br_FR", "br_FR.ISO-8859-1", "br_FR.UTF-8", "brx_IN", "brx_IN.UTF-8", "bs_BA", "bs_BA.ISO-8859-2", "bs_BA.UTF-8", "byn_ER", "byn_ER.UTF-8", "ca_AD", "ca_AD.ISO-8859-15", "ca_AD.UTF-8", "ca_ES", "ca_ES.ISO-8859-1", "ca_ES.UTF-8", "ca_FR", "ca_FR.ISO-8859-15", "ca_FR.UTF-8", "ca_IT", "ca_IT.ISO-8859-15", "ca_IT.UTF-8", "ce_RU", "ce_RU.UTF-8", "chr_US", "chr_US.UTF-8", "ckb_IQ", "ckb_IQ.UTF-8", "cmn_TW", "cmn_TW.UTF-8", "crh_UA", "crh_UA.UTF-8", "csb_PL", "csb_PL.UTF-8", "cs_CZ", "cs_CZ.ISO-8859-2", "cs_CZ.UTF-8", "cv_RU", "cv_RU.UTF-8", "cy_GB", "cy_GB.ISO-8859-14", "cy_GB.UTF-8", "da_DK", "da_DK.ISO-8859-1", "da_DK.UTF-8", "de_AT", "de_AT.ISO-8859-1", "de_AT.UTF-8", "de_BE", "de_BE.ISO-8859-1", "de_BE.UTF-8", "de_CH", "de_CH.ISO-8859-1", "de_CH.UTF-8", "de_DE", "de_DE.ISO-8859-1", "de_DE.UTF-8", "de_IT", "de_IT.ISO-8859-1", "de_IT.UTF-8", "de_LU", "de_LU.ISO-8859-1", "de_LU.UTF-8", "doi_IN", "doi_IN.UTF-8", "dv_MV", "dv_MV.UTF-8", "dz_BT", "dz_BT.UTF-8", "el_CY", "el_CY.ISO-8859-7", "el_CY.UTF-8", "el_GR", "el_GR.ISO-8859-7", "el_GR.UTF-8", "en_AG", "en_AG.UTF-8", "en_AU", "en_AU.ISO-8859-1", "en_AU.UTF-8", "en_BW", "en_BW.ISO-8859-1", "en_BW.UTF-8", "en_CA", "en_CA.ISO-8859-1", "en_CA.UTF-8", "en_DK", "en_DK.ISO-8859-1", "en_DK.ISO-8859-15", "en_DK.UTF-8", "en_GB", "en_GB.ISO-8859-1", "en_GB.ISO-8859-15", "en_GB.UTF-8", "en_HK", "en_HK.ISO-8859-1", "en_HK.UTF-8", "en_IE", "en_IE.ISO-8859-1", "en_IE.UTF-8", "en_IL", "en_IL.UTF-8", "en_IN", "en_IN.UTF-8", "en_NG", "en_NG.UTF-8", "en_NZ", "en_NZ.ISO-8859-1", "en_NZ.UTF-8", "en_PH", "en_PH.ISO-8859-1", "en_PH.UTF-8", "en_SG", "en_SG.ISO-8859-1", "en_SG.UTF-8", "en_US", "en_US.ISO-8859-1", "en_US.ISO-8859-15", "en_US.UTF-8", "en_ZA", "en_ZA.ISO-8859-1", "en_ZA.UTF-8", "en_ZM", "en_ZM.UTF-8", "en_ZW", "en_ZW.ISO-8859-1", "en_ZW.UTF-8", "es_AR", "es_AR.ISO-8859-1", "es_AR.UTF-8", "es_BO", "es_BO.ISO-8859-1", "es_BO.UTF-8", "es_CL", "es_CL.ISO-8859-1", "es_CL.UTF-8", "es_CO", "es_CO.ISO-8859-1", "es_CO.UTF-8", "es_CR", "es_CR.ISO-8859-1", "es_CR.UTF-8", "es_CU", "es_CU.UTF-8", "es_DO", "es_DO.ISO-8859-1", "es_DO.UTF-8", "es_EC", "es_EC.ISO-8859-1", "es_EC.UTF-8", "es_ES", "es_ES.ISO-8859-1", "es_ES.UTF-8", "es_GT", "es_GT.ISO-8859-1", "es_GT.UTF-8", "es_HN", "es_HN.ISO-8859-1", "es_HN.UTF-8", "es_MX", "es_MX.ISO-8859-1", "es_MX.UTF-8", "es_NI", "es_NI.ISO-8859-1", "es_NI.UTF-8", "es_PA", "es_PA.ISO-8859-1", "es_PA.UTF-8", "es_PE", "es_PE.ISO-8859-1", "es_PE.UTF-8", "es_PR", "es_PR.ISO-8859-1", "es_PR.UTF-8", "es_PY", "es_PY.ISO-8859-1", "es_PY.UTF-8", "es_SV", "es_SV.ISO-8859-1", "es_SV.UTF-8", "es_US", "es_US.ISO-8859-1", "es_US.UTF-8", "es_UY", "es_UY.ISO-8859-1", "es_UY.UTF-8", "es_VE", "es_VE.ISO-8859-1", "es_VE.UTF-8", "et_EE", "et_EE.ISO-8859-1", "et_EE.ISO-8859-15", "et_EE.UTF-8", "eu_ES", "eu_ES.ISO-8859-1", "eu_ES.UTF-8", "eu_FR", "eu_FR.ISO-8859-1", "eu_FR.UTF-8", "fa_IR", "fa_IR.UTF-8", "ff_SN", "ff_SN.UTF-8", "fi_FI", "fi_FI.ISO-8859-1", "fi_FI.UTF-8", "fil_PH", "fil_PH.UTF-8", "fo_FO", "fo_FO.ISO-8859-1", "fo_FO.UTF-8", "fr_BE", "fr_BE.ISO-8859-1", "fr_BE.UTF-8", "fr_CA", "fr_CA.ISO-8859-1", "fr_CA.UTF-8", "fr_CH", "fr_CH.ISO-8859-1", "fr_CH.UTF-8", "fr_FR", "fr_FR.ISO-8859-1", "fr_FR.UTF-8", "fr_LU", "fr_LU.ISO-8859-1", "fr_LU.UTF-8", "fur_IT", "fur_IT.UTF-8", "fy_DE", "fy_DE.UTF-8", "fy_NL", "fy_NL.UTF-8", "ga_IE", "ga_IE.ISO-8859-1", "ga_IE.UTF-8", "gd_GB", "gd_GB.ISO-8859-15", "gd_GB.UTF-8", "gez_ER", "gez_ER.UTF-8", "gez_ET", "gez_ET.UTF-8", "gl_ES", "gl_ES.ISO-8859-1", "gl_ES.UTF-8", "gu_IN", "gu_IN.UTF-8", "gv_GB", "gv_GB.ISO-8859-1", "gv_GB.UTF-8", "hak_TW", "hak_TW.UTF-8", "ha_NG", "ha_NG.UTF-8", "he_IL", "he_IL.ISO-8859-8", "he_IL.UTF-8", "hif_FJ", "hif_FJ.UTF-8", "hi_IN", "hi_IN.UTF-8", "hne_IN", "hne_IN.UTF-8", "hr_HR", "hr_HR.ISO-8859-2", "hr_HR.UTF-8", "hsb_DE", "hsb_DE.ISO-8859-2", "hsb_DE.UTF-8", "ht_HT", "ht_HT.UTF-8", "hu_HU", "hu_HU.ISO-8859-2", "hu_HU.UTF-8", "hy_AM", "hy_AM.ARMSCII-8", "hy_AM.UTF-8", "ia_FR", "ia_FR.UTF-8", "id_ID", "id_ID.ISO-8859-1", "id_ID.UTF-8", "ig_NG", "ig_NG.UTF-8", "ik_CA", "ik_CA.UTF-8", "is_IS", "is_IS.ISO-8859-1", "is_IS.UTF-8", "it_CH", "it_CH.ISO-8859-1", "it_CH.UTF-8", "it_IT", "it_IT.ISO-8859-1", "it_IT.UTF-8", "iu_CA", "iu_CA.UTF-8", "kab_DZ", "kab_DZ.UTF-8", "ka_GE", "ka_GE.GEORGIAN-PS", "ka_GE.UTF-8", "kk_KZ", "kk_KZ.PT154", "kk_KZ.RK1048", "kk_KZ.UTF-8", "kl_GL", "kl_GL.ISO-8859-1", "kl_GL.UTF-8", "km_KH", "km_KH.UTF-8", "kn_IN", "kn_IN.UTF-8", "kok_IN", "kok_IN.UTF-8", "ks_IN", "ks_IN.UTF-8", "ku_TR", "ku_TR.ISO-8859-9", "ku_TR.UTF-8", "kw_GB", "kw_GB.ISO-8859-1", "kw_GB.UTF-8", "ky_KG", "ky_KG.UTF-8", "lb_LU", "lb_LU.UTF-8", "lg_UG", "lg_UG.ISO-8859-10", "lg_UG.UTF-8", "li_BE", "li_BE.UTF-8", "lij_IT", "lij_IT.UTF-8", "li_NL", "li_NL.UTF-8", "ln_CD", "ln_CD.UTF-8", "lo_LA", "lo_LA.UTF-8", "lt_LT", "lt_LT.ISO-8859-13", "lt_LT.UTF-8", "lv_LV", "lv_LV.ISO-8859-13", "lv_LV.UTF-8", "lzh_TW", "lzh_TW.UTF-8", "mag_IN", "mag_IN.UTF-8", "mai_IN", "mai_IN.UTF-8", "mai_NP", "mai_NP.UTF-8", "mfe_MU", "mfe_MU.UTF-8", "mg_MG", "mg_MG.ISO-8859-15", "mg_MG.UTF-8", "mhr_RU", "mhr_RU.UTF-8", "mi_NZ", "mi_NZ.ISO-8859-13", "mi_NZ.UTF-8", "miq_NI", "miq_NI.UTF-8", "mjw_IN", "mjw_IN.UTF-8", "mk_MK", "mk_MK.ISO-8859-5", "mk_MK.UTF-8", "ml_IN", "ml_IN.UTF-8", "mni_IN", "mni_IN.UTF-8", "mn_MN", "mn_MN.UTF-8", "mr_IN", "mr_IN.UTF-8", "ms_MY", "ms_MY.ISO-8859-1", "ms_MY.UTF-8", "mt_MT", "mt_MT.ISO-8859-3", "mt_MT.UTF-8", "my_MM", "my_MM.UTF-8", "nan_TW", "nan_TW.UTF-8", "nb_NO", "nb_NO.ISO-8859-1", "nb_NO.UTF-8", "nds_DE", "nds_DE.UTF-8", "nds_NL", "nds_NL.UTF-8", "ne_NP", "ne_NP.UTF-8", "nhn_MX", "nhn_MX.UTF-8", "niu_NU", "niu_NU.UTF-8", "niu_NZ", "niu_NZ.UTF-8", "nl_AW", "nl_AW.UTF-8", "nl_BE", "nl_BE.ISO-8859-1", "nl_BE.UTF-8", "nl_NL", "nl_NL.ISO-8859-1", "nl_NL.UTF-8", "nn_NO", "nn_NO.ISO-8859-1", "nn_NO.UTF-8", "nr_ZA", "nr_ZA.UTF-8", "nso_ZA", "nso_ZA.UTF-8", "oc_FR", "oc_FR.ISO-8859-1", "oc_FR.UTF-8", "om_ET", "om_ET.UTF-8", "om_KE", "om_KE.ISO-8859-1", "om_KE.UTF-8", "or_IN", "or_IN.UTF-8", "os_RU", "os_RU.UTF-8", "pa_IN", "pa_IN.UTF-8", "pap_AW", "pap_AW.UTF-8", "pap_CW", "pap_CW.UTF-8", "pa_PK", "pa_PK.UTF-8", "pl_PL", "pl_PL.ISO-8859-2", "pl_PL.UTF-8", "ps_AF", "ps_AF.UTF-8", "pt_BR", "pt_BR.ISO-8859-1", "pt_BR.UTF-8", "pt_PT", "pt_PT.ISO-8859-1", "pt_PT.UTF-8", "quz_PE", "quz_PE.UTF-8", "raj_IN", "raj_IN.UTF-8", "ro_RO", "ro_RO.ISO-8859-2", "ro_RO.UTF-8", "ru_RU", "ru_RU.CP1251", "ru_RU.ISO-8859-5", "ru_RU.KOI8-R", "ru_RU.UTF-8", "ru_UA", "ru_UA.KOI8-U", "ru_UA.UTF-8", "rw_RW", "rw_RW.UTF-8", "sa_IN", "sa_IN.UTF-8", "sat_IN", "sat_IN.UTF-8", "sc_IT", "sc_IT.UTF-8", "sd_IN", "sd_IN.UTF-8", "sd_PK", "sd_PK.UTF-8", "se_NO", "se_NO.UTF-8", "sgs_LT", "sgs_LT.UTF-8", "shn_MM", "shn_MM.UTF-8", "shs_CA", "shs_CA.UTF-8", "sid_ET", "sid_ET.UTF-8", "si_LK", "si_LK.UTF-8", "sk_SK", "sk_SK.ISO-8859-2", "sk_SK.UTF-8", "sl_SI", "sl_SI.ISO-8859-2", "sl_SI.UTF-8", "sm_WS", "sm_WS.UTF-8", "so_DJ", "so_DJ.ISO-8859-1", "so_DJ.UTF-8", "so_ET", "so_ET.UTF-8", "so_KE", "so_KE.ISO-8859-1", "so_KE.UTF-8", "so_SO", "so_SO.ISO-8859-1", "so_SO.UTF-8", "sq_AL", "sq_AL.ISO-8859-1", "sq_AL.UTF-8", "sq_MK", "sq_MK.UTF-8", "sr_ME", "sr_ME.UTF-8", "sr_RS", "sr_RS.UTF-8", "ss_ZA", "ss_ZA.UTF-8", "st_ZA", "st_ZA.ISO-8859-1", "st_ZA.UTF-8", "sv_FI", "sv_FI.ISO-8859-1", "sv_FI.UTF-8", "sv_SE", "sv_SE.ISO-8859-1", "sv_SE.ISO-8859-15", "sv_SE.UTF-8", "sw_KE", "sw_KE.UTF-8", "sw_TZ", "sw_TZ.UTF-8", "szl_PL", "szl_PL.UTF-8", "ta_IN", "ta_IN.UTF-8", "ta_LK", "ta_LK.UTF-8", "te_IN", "te_IN.UTF-8", "tg_TJ", "tg_TJ.KOI8-T", "tg_TJ.UTF-8", "the_NP", "the_NP.UTF-8", "th_TH", "th_TH.TIS-620", "th_TH.UTF-8", "ti_ER", "ti_ER.UTF-8", "ti_ET", "ti_ET.UTF-8", "tig_ER", "tig_ER.UTF-8", "tk_TM", "tk_TM.UTF-8", "tl_PH", "tl_PH.ISO-8859-1", "tl_PH.UTF-8", "tn_ZA", "tn_ZA.UTF-8", "to_TO", "to_TO.UTF-8", "tpi_PG", "tpi_PG.UTF-8", "tr_CY", "tr_CY.ISO-8859-9", "tr_CY.UTF-8", "tr_TR", "tr_TR.ISO-8859-9", "tr_TR.UTF-8", "ts_ZA", "ts_ZA.UTF-8", "tt_RU", "tt_RU.UTF-8", "ug_CN", "ug_CN.UTF-8", "uk_UA", "uk_UA.KOI8-U", "uk_UA.UTF-8", "unm_US", "unm_US.UTF-8", "ur_IN", "ur_IN.UTF-8", "ur_PK", "ur_PK.UTF-8", "uz_UZ", "uz_UZ.ISO-8859-1", "uz_UZ.UTF-8", "ve_ZA", "ve_ZA.UTF-8", "vi_VN", "vi_VN.UTF-8", "wa_BE", "wa_BE.ISO-8859-1", "wa_BE.UTF-8", "wae_CH", "wae_CH.UTF-8", "wal_ET", "wal_ET.UTF-8", "wo_SN", "wo_SN.UTF-8", "xh_ZA", "xh_ZA.ISO-8859-1", "xh_ZA.UTF-8", "yi_US", "yi_US.CP1255", "yi_US.UTF-8", "yo_NG", "yo_NG.UTF-8", "yue_HK", "yue_HK.UTF-8", "yuw_PG", "yuw_PG.UTF-8", "zh_CN", "zh_CN.GB18030", "zh_CN.GB2312", "zh_CN.GBK", "zh_CN.UTF-8", "zh_HK", "zh_HK.BIG5-HKSCS", "zh_HK.UTF-8", "zh_SG", "zh_SG.GB2312", "zh_SG.GBK", "zh_SG.UTF-8", "zh_TW", "zh_TW.BIG5", "zh_TW.EUC-TW", "zh_TW.UTF-8", "zu_ZA", "zu_ZA.ISO-8859-1", "zu_ZA.UTF-8"};
+
+std::string ConsumeLocaleIdentifier(FuzzedDataProvider& fuzzed_data_provider)
+{
+ return fuzzed_data_provider.PickValueInArray<std::string>(locale_identifiers);
+}
+
+bool IsAvailableLocale(const std::string& locale_identifier)
+{
+ try {
+ (void)std::locale(locale_identifier);
+ } catch (const std::runtime_error&) {
+ return false;
+ }
+ return true;
+}
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const std::string locale_identifier = ConsumeLocaleIdentifier(fuzzed_data_provider);
+ if (!IsAvailableLocale(locale_identifier)) {
+ return;
+ }
+ const char* c_locale = std::setlocale(LC_ALL, "C");
+ assert(c_locale != nullptr);
+
+ const std::string random_string = fuzzed_data_provider.ConsumeRandomLengthString(5);
+ int32_t parseint32_out_without_locale;
+ const bool parseint32_without_locale = ParseInt32(random_string, &parseint32_out_without_locale);
+ int64_t parseint64_out_without_locale;
+ const bool parseint64_without_locale = ParseInt64(random_string, &parseint64_out_without_locale);
+ const int64_t atoi64_without_locale = atoi64(random_string);
+ const int atoi_without_locale = atoi(random_string);
+ const int64_t atoi64c_without_locale = atoi64(random_string.c_str());
+ const int64_t random_int64 = fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ const std::string tostring_without_locale = ToString(random_int64);
+ // The variable `random_int32` is no longer used, but the harness still needs to
+ // consume the same data that it did previously to not invalidate existing seeds.
+ const int32_t random_int32 = fuzzed_data_provider.ConsumeIntegral<int32_t>();
+ (void)random_int32;
+ const std::string strprintf_int_without_locale = strprintf("%d", random_int64);
+ const double random_double = fuzzed_data_provider.ConsumeFloatingPoint<double>();
+ const std::string strprintf_double_without_locale = strprintf("%f", random_double);
+
+ const char* new_locale = std::setlocale(LC_ALL, locale_identifier.c_str());
+ assert(new_locale != nullptr);
+
+ int32_t parseint32_out_with_locale;
+ const bool parseint32_with_locale = ParseInt32(random_string, &parseint32_out_with_locale);
+ assert(parseint32_without_locale == parseint32_with_locale);
+ if (parseint32_without_locale) {
+ assert(parseint32_out_without_locale == parseint32_out_with_locale);
+ }
+ int64_t parseint64_out_with_locale;
+ const bool parseint64_with_locale = ParseInt64(random_string, &parseint64_out_with_locale);
+ assert(parseint64_without_locale == parseint64_with_locale);
+ if (parseint64_without_locale) {
+ assert(parseint64_out_without_locale == parseint64_out_with_locale);
+ }
+ const int64_t atoi64_with_locale = atoi64(random_string);
+ assert(atoi64_without_locale == atoi64_with_locale);
+ const int64_t atoi64c_with_locale = atoi64(random_string.c_str());
+ assert(atoi64c_without_locale == atoi64c_with_locale);
+ const int atoi_with_locale = atoi(random_string);
+ assert(atoi_without_locale == atoi_with_locale);
+ const std::string tostring_with_locale = ToString(random_int64);
+ assert(tostring_without_locale == tostring_with_locale);
+ const std::string strprintf_int_with_locale = strprintf("%d", random_int64);
+ assert(strprintf_int_without_locale == strprintf_int_with_locale);
+ const std::string strprintf_double_with_locale = strprintf("%f", random_double);
+ assert(strprintf_double_without_locale == strprintf_double_with_locale);
+
+ const std::locale current_cpp_locale;
+ assert(current_cpp_locale == std::locale::classic());
+}
diff --git a/src/test/fuzz/merkleblock.cpp b/src/test/fuzz/merkleblock.cpp
new file mode 100644
index 0000000000..eb8fa1d421
--- /dev/null
+++ b/src/test/fuzz/merkleblock.cpp
@@ -0,0 +1,27 @@
+// 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 <merkleblock.h>
+#include <optional.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <uint256.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ Optional<CPartialMerkleTree> partial_merkle_tree = ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider);
+ if (!partial_merkle_tree) {
+ return;
+ }
+ (void)partial_merkle_tree->GetNumTransactions();
+ std::vector<uint256> matches;
+ std::vector<unsigned int> indices;
+ (void)partial_merkle_tree->ExtractMatches(matches, indices);
+}
diff --git a/src/test/fuzz/multiplication_overflow.cpp b/src/test/fuzz/multiplication_overflow.cpp
new file mode 100644
index 0000000000..a4b158c18b
--- /dev/null
+++ b/src/test/fuzz/multiplication_overflow.cpp
@@ -0,0 +1,55 @@
+// 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/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#if defined(__has_builtin)
+#if __has_builtin(__builtin_mul_overflow)
+#define HAVE_BUILTIN_MUL_OVERFLOW
+#endif
+#elif defined(__GNUC__) && (__GNUC__ >= 5)
+#define HAVE_BUILTIN_MUL_OVERFLOW
+#endif
+
+namespace {
+template <typename T>
+void TestMultiplicationOverflow(FuzzedDataProvider& fuzzed_data_provider)
+{
+ const T i = fuzzed_data_provider.ConsumeIntegral<T>();
+ const T j = fuzzed_data_provider.ConsumeIntegral<T>();
+ const bool is_multiplication_overflow_custom = MultiplicationOverflow(i, j);
+#if defined(HAVE_BUILTIN_MUL_OVERFLOW)
+ T result_builtin;
+ const bool is_multiplication_overflow_builtin = __builtin_mul_overflow(i, j, &result_builtin);
+ assert(is_multiplication_overflow_custom == is_multiplication_overflow_builtin);
+ if (!is_multiplication_overflow_custom) {
+ assert(i * j == result_builtin);
+ }
+#else
+ if (!is_multiplication_overflow_custom) {
+ (void)(i * j);
+ }
+#endif
+}
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ TestMultiplicationOverflow<int64_t>(fuzzed_data_provider);
+ TestMultiplicationOverflow<uint64_t>(fuzzed_data_provider);
+ TestMultiplicationOverflow<int32_t>(fuzzed_data_provider);
+ TestMultiplicationOverflow<uint32_t>(fuzzed_data_provider);
+ TestMultiplicationOverflow<int16_t>(fuzzed_data_provider);
+ TestMultiplicationOverflow<uint16_t>(fuzzed_data_provider);
+ TestMultiplicationOverflow<char>(fuzzed_data_provider);
+ TestMultiplicationOverflow<unsigned char>(fuzzed_data_provider);
+ TestMultiplicationOverflow<signed char>(fuzzed_data_provider);
+}
diff --git a/src/test/fuzz/net_permissions.cpp b/src/test/fuzz/net_permissions.cpp
new file mode 100644
index 0000000000..bfc5d21427
--- /dev/null
+++ b/src/test/fuzz/net_permissions.cpp
@@ -0,0 +1,51 @@
+// 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 <net_permissions.h>
+#include <optional.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const std::string s = fuzzed_data_provider.ConsumeRandomLengthString(32);
+ const NetPermissionFlags net_permission_flags = fuzzed_data_provider.ConsumeBool() ? fuzzed_data_provider.PickValueInArray<NetPermissionFlags>({
+ NetPermissionFlags::PF_NONE,
+ NetPermissionFlags::PF_BLOOMFILTER,
+ NetPermissionFlags::PF_RELAY,
+ NetPermissionFlags::PF_FORCERELAY,
+ NetPermissionFlags::PF_NOBAN,
+ NetPermissionFlags::PF_MEMPOOL,
+ NetPermissionFlags::PF_ISIMPLICIT,
+ NetPermissionFlags::PF_ALL,
+ }) :
+ static_cast<NetPermissionFlags>(fuzzed_data_provider.ConsumeIntegral<uint32_t>());
+
+ NetWhitebindPermissions net_whitebind_permissions;
+ std::string error_net_whitebind_permissions;
+ if (NetWhitebindPermissions::TryParse(s, net_whitebind_permissions, error_net_whitebind_permissions)) {
+ (void)NetPermissions::ToStrings(net_whitebind_permissions.m_flags);
+ (void)NetPermissions::AddFlag(net_whitebind_permissions.m_flags, net_permission_flags);
+ assert(NetPermissions::HasFlag(net_whitebind_permissions.m_flags, net_permission_flags));
+ (void)NetPermissions::ClearFlag(net_whitebind_permissions.m_flags, net_permission_flags);
+ (void)NetPermissions::ToStrings(net_whitebind_permissions.m_flags);
+ }
+
+ NetWhitelistPermissions net_whitelist_permissions;
+ std::string error_net_whitelist_permissions;
+ if (NetWhitelistPermissions::TryParse(s, net_whitelist_permissions, error_net_whitelist_permissions)) {
+ (void)NetPermissions::ToStrings(net_whitelist_permissions.m_flags);
+ (void)NetPermissions::AddFlag(net_whitelist_permissions.m_flags, net_permission_flags);
+ assert(NetPermissions::HasFlag(net_whitelist_permissions.m_flags, net_permission_flags));
+ (void)NetPermissions::ClearFlag(net_whitelist_permissions.m_flags, net_permission_flags);
+ (void)NetPermissions::ToStrings(net_whitelist_permissions.m_flags);
+ }
+}
diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp
new file mode 100644
index 0000000000..d8d53566c7
--- /dev/null
+++ b/src/test/fuzz/netaddress.cpp
@@ -0,0 +1,134 @@
+// 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 <netaddress.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+
+#include <cassert>
+#include <cstdint>
+#include <netinet/in.h>
+#include <vector>
+
+namespace {
+CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
+{
+ const Network network = fuzzed_data_provider.PickValueInArray({Network::NET_IPV4, Network::NET_IPV6, Network::NET_INTERNAL, Network::NET_ONION});
+ if (network == Network::NET_IPV4) {
+ const in_addr v4_addr = {
+ .s_addr = fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
+ return CNetAddr{v4_addr};
+ } else if (network == Network::NET_IPV6) {
+ if (fuzzed_data_provider.remaining_bytes() < 16) {
+ return CNetAddr{};
+ }
+ in6_addr v6_addr = {};
+ memcpy(v6_addr.s6_addr, fuzzed_data_provider.ConsumeBytes<uint8_t>(16).data(), 16);
+ return CNetAddr{v6_addr, fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
+ } else if (network == Network::NET_INTERNAL) {
+ CNetAddr net_addr;
+ net_addr.SetInternal(fuzzed_data_provider.ConsumeBytesAsString(32));
+ return net_addr;
+ } else if (network == Network::NET_ONION) {
+ CNetAddr net_addr;
+ net_addr.SetSpecial(fuzzed_data_provider.ConsumeBytesAsString(32));
+ return net_addr;
+ } else {
+ assert(false);
+ }
+}
+}; // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ const CNetAddr net_addr = ConsumeNetAddr(fuzzed_data_provider);
+ for (int i = 0; i < 15; ++i) {
+ (void)net_addr.GetByte(i);
+ }
+ (void)net_addr.GetHash();
+ (void)net_addr.GetNetClass();
+ if (net_addr.GetNetwork() == Network::NET_IPV4) {
+ assert(net_addr.IsIPv4());
+ }
+ if (net_addr.GetNetwork() == Network::NET_IPV6) {
+ assert(net_addr.IsIPv6());
+ }
+ if (net_addr.GetNetwork() == Network::NET_ONION) {
+ assert(net_addr.IsTor());
+ }
+ if (net_addr.GetNetwork() == Network::NET_INTERNAL) {
+ assert(net_addr.IsInternal());
+ }
+ if (net_addr.GetNetwork() == Network::NET_UNROUTABLE) {
+ assert(!net_addr.IsRoutable());
+ }
+ (void)net_addr.IsBindAny();
+ if (net_addr.IsInternal()) {
+ assert(net_addr.GetNetwork() == Network::NET_INTERNAL);
+ }
+ if (net_addr.IsIPv4()) {
+ assert(net_addr.GetNetwork() == Network::NET_IPV4 || net_addr.GetNetwork() == Network::NET_UNROUTABLE);
+ }
+ if (net_addr.IsIPv6()) {
+ assert(net_addr.GetNetwork() == Network::NET_IPV6 || net_addr.GetNetwork() == Network::NET_UNROUTABLE);
+ }
+ (void)net_addr.IsLocal();
+ if (net_addr.IsRFC1918() || net_addr.IsRFC2544() || net_addr.IsRFC6598() || net_addr.IsRFC5737() || net_addr.IsRFC3927()) {
+ assert(net_addr.IsIPv4());
+ }
+ (void)net_addr.IsRFC2544();
+ if (net_addr.IsRFC3849() || net_addr.IsRFC3964() || net_addr.IsRFC4380() || net_addr.IsRFC4843() || net_addr.IsRFC7343() || net_addr.IsRFC4862() || net_addr.IsRFC6052() || net_addr.IsRFC6145()) {
+ assert(net_addr.IsIPv6());
+ }
+ (void)net_addr.IsRFC3927();
+ (void)net_addr.IsRFC3964();
+ if (net_addr.IsRFC4193()) {
+ assert(net_addr.GetNetwork() == Network::NET_ONION || net_addr.GetNetwork() == Network::NET_INTERNAL || net_addr.GetNetwork() == Network::NET_UNROUTABLE);
+ }
+ (void)net_addr.IsRFC4380();
+ (void)net_addr.IsRFC4843();
+ (void)net_addr.IsRFC4862();
+ (void)net_addr.IsRFC5737();
+ (void)net_addr.IsRFC6052();
+ (void)net_addr.IsRFC6145();
+ (void)net_addr.IsRFC6598();
+ (void)net_addr.IsRFC7343();
+ if (!net_addr.IsRoutable()) {
+ assert(net_addr.GetNetwork() == Network::NET_UNROUTABLE || net_addr.GetNetwork() == Network::NET_INTERNAL);
+ }
+ if (net_addr.IsTor()) {
+ assert(net_addr.GetNetwork() == Network::NET_ONION);
+ }
+ (void)net_addr.IsValid();
+ (void)net_addr.ToString();
+ (void)net_addr.ToStringIP();
+
+ const CSubNet sub_net{net_addr, fuzzed_data_provider.ConsumeIntegral<int32_t>()};
+ (void)sub_net.IsValid();
+ (void)sub_net.ToString();
+
+ const CService service{net_addr, fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
+ (void)service.GetKey();
+ (void)service.GetPort();
+ (void)service.ToString();
+ (void)service.ToStringIPPort();
+ (void)service.ToStringPort();
+
+ const CNetAddr other_net_addr = ConsumeNetAddr(fuzzed_data_provider);
+ (void)net_addr.GetReachabilityFrom(&other_net_addr);
+ (void)sub_net.Match(other_net_addr);
+
+ const CService other_service{net_addr, fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
+ assert((service == other_service) != (service != other_service));
+ (void)(service < other_service);
+
+ const CSubNet sub_net_copy_1{net_addr, other_net_addr};
+ const CSubNet sub_net_copy_2{net_addr};
+
+ CNetAddr mutable_net_addr;
+ mutable_net_addr.SetIP(net_addr);
+ assert(net_addr == mutable_net_addr);
+}
diff --git a/src/test/fuzz/p2p_transport_deserializer.cpp b/src/test/fuzz/p2p_transport_deserializer.cpp
new file mode 100644
index 0000000000..57393fed45
--- /dev/null
+++ b/src/test/fuzz/p2p_transport_deserializer.cpp
@@ -0,0 +1,47 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chainparams.h>
+#include <net.h>
+#include <protocol.h>
+#include <test/fuzz/fuzz.h>
+
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <vector>
+
+void initialize()
+{
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ V1TransportDeserializer deserializer{Params().MessageStart(), 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);
+ if (handled < 0) {
+ break;
+ }
+ pch += handled;
+ n_bytes -= handled;
+ if (deserializer.Complete()) {
+ const int64_t m_time = std::numeric_limits<int64_t>::max();
+ const CNetMessage msg = deserializer.GetMessage(Params().MessageStart(), m_time);
+ assert(msg.m_command.size() <= CMessageHeader::COMMAND_SIZE);
+ assert(msg.m_raw_message_size <= buffer.size());
+ assert(msg.m_raw_message_size == CMessageHeader::HEADER_SIZE + msg.m_message_size);
+ assert(msg.m_time == m_time);
+ if (msg.m_valid_header) {
+ assert(msg.m_valid_netmagic);
+ }
+ if (!msg.m_valid_netmagic) {
+ assert(!msg.m_valid_header);
+ }
+ }
+ }
+}
diff --git a/src/test/fuzz/parse_hd_keypath.cpp b/src/test/fuzz/parse_hd_keypath.cpp
index 9a23f4b2d4..f668ca8c48 100644
--- a/src/test/fuzz/parse_hd_keypath.cpp
+++ b/src/test/fuzz/parse_hd_keypath.cpp
@@ -2,12 +2,22 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
#include <util/bip32.h>
+#include <cstdint>
+#include <vector>
+
void test_one_input(const std::vector<uint8_t>& buffer)
{
const std::string keypath_str(buffer.begin(), buffer.end());
std::vector<uint32_t> keypath;
(void)ParseHDKeypath(keypath_str, keypath);
+
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const std::vector<uint32_t> random_keypath = ConsumeRandomLengthIntegralVector<uint32_t>(fuzzed_data_provider);
+ (void)FormatHDKeypath(random_keypath);
+ (void)WriteHDKeypath(random_keypath);
}
diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp
index 3ad112dbad..a269378607 100644
--- a/src/test/fuzz/parse_univalue.cpp
+++ b/src/test/fuzz/parse_univalue.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -14,7 +14,7 @@
void initialize()
{
- static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+ static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}
@@ -35,21 +35,31 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
try {
(void)ParseHashO(univalue, "A");
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
(void)ParseHashO(univalue, random_string);
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
}
try {
(void)ParseHashV(univalue, "A");
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
(void)ParseHashV(univalue, random_string);
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
}
try {
(void)ParseHexO(univalue, "A");
+ } catch (const UniValue&) {
+ }
+ try {
(void)ParseHexO(univalue, random_string);
} catch (const UniValue&) {
- } catch (const std::runtime_error&) {
}
try {
(void)ParseHexUV(univalue, "A");
@@ -59,6 +69,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
try {
(void)ParseHexV(univalue, "A");
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
(void)ParseHexV(univalue, random_string);
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp
new file mode 100644
index 0000000000..201f49c87b
--- /dev/null
+++ b/src/test/fuzz/policy_estimator.cpp
@@ -0,0 +1,69 @@
+// 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 <optional.h>
+#include <policy/fees.h>
+#include <primitives/transaction.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <txmempool.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ CBlockPolicyEstimator block_policy_estimator;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 3)) {
+ case 0: {
+ const Optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ if (!mtx) {
+ break;
+ }
+ const CTransaction tx{*mtx};
+ block_policy_estimator.processTransaction(ConsumeTxMemPoolEntry(fuzzed_data_provider, tx), fuzzed_data_provider.ConsumeBool());
+ if (fuzzed_data_provider.ConsumeBool()) {
+ (void)block_policy_estimator.removeTx(tx.GetHash(), /* inBlock */ fuzzed_data_provider.ConsumeBool());
+ }
+ break;
+ }
+ case 1: {
+ std::vector<CTxMemPoolEntry> mempool_entries;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ const Optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ if (!mtx) {
+ break;
+ }
+ const CTransaction tx{*mtx};
+ mempool_entries.push_back(ConsumeTxMemPoolEntry(fuzzed_data_provider, tx));
+ }
+ std::vector<const CTxMemPoolEntry*> ptrs;
+ ptrs.reserve(mempool_entries.size());
+ for (const CTxMemPoolEntry& mempool_entry : mempool_entries) {
+ ptrs.push_back(&mempool_entry);
+ }
+ block_policy_estimator.processBlock(fuzzed_data_provider.ConsumeIntegral<unsigned int>(), ptrs);
+ break;
+ }
+ case 2: {
+ (void)block_policy_estimator.removeTx(ConsumeUInt256(fuzzed_data_provider), /* inBlock */ fuzzed_data_provider.ConsumeBool());
+ break;
+ }
+ case 3: {
+ block_policy_estimator.FlushUnconfirmed();
+ break;
+ }
+ }
+ (void)block_policy_estimator.estimateFee(fuzzed_data_provider.ConsumeIntegral<int>());
+ EstimationResult result;
+ (void)block_policy_estimator.estimateRawFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeFloatingPoint<double>(), fuzzed_data_provider.PickValueInArray({FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}), fuzzed_data_provider.ConsumeBool() ? &result : nullptr);
+ FeeCalculation fee_calculation;
+ (void)block_policy_estimator.estimateSmartFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeBool() ? &fee_calculation : nullptr, fuzzed_data_provider.ConsumeBool());
+ (void)block_policy_estimator.HighestTargetTracked(fuzzed_data_provider.PickValueInArray({FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}));
+ }
+}
diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp
new file mode 100644
index 0000000000..0343d33401
--- /dev/null
+++ b/src/test/fuzz/pow.cpp
@@ -0,0 +1,81 @@
+// 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 <chain.h>
+#include <chainparams.h>
+#include <optional.h>
+#include <pow.h>
+#include <primitives/block.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void initialize()
+{
+ SelectParams(CBaseChainParams::MAIN);
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const Consensus::Params& consensus_params = Params().GetConsensus();
+ std::vector<CBlockIndex> blocks;
+ const uint32_t fixed_time = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
+ const uint32_t fixed_bits = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
+ while (fuzzed_data_provider.remaining_bytes() > 0) {
+ const Optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
+ if (!block_header) {
+ continue;
+ }
+ CBlockIndex current_block{*block_header};
+ {
+ CBlockIndex* previous_block = !blocks.empty() ? &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)] : nullptr;
+ const int current_height = (previous_block != nullptr && previous_block->nHeight != std::numeric_limits<int>::max()) ? previous_block->nHeight + 1 : 0;
+ if (fuzzed_data_provider.ConsumeBool()) {
+ current_block.pprev = previous_block;
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ current_block.nHeight = current_height;
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ current_block.nTime = fixed_time + current_height * consensus_params.nPowTargetSpacing;
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ current_block.nBits = fixed_bits;
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ current_block.nChainWork = previous_block != nullptr ? previous_block->nChainWork + GetBlockProof(*previous_block) : arith_uint256{0};
+ } else {
+ current_block.nChainWork = ConsumeArithUInt256(fuzzed_data_provider);
+ }
+ blocks.push_back(current_block);
+ }
+ {
+ (void)GetBlockProof(current_block);
+ (void)CalculateNextWorkRequired(&current_block, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, std::numeric_limits<int64_t>::max()), consensus_params);
+ if (current_block.nHeight != std::numeric_limits<int>::max() && current_block.nHeight - (consensus_params.DifficultyAdjustmentInterval() - 1) >= 0) {
+ (void)GetNextWorkRequired(&current_block, &(*block_header), consensus_params);
+ }
+ }
+ {
+ const CBlockIndex* to = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)];
+ const CBlockIndex* from = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)];
+ const CBlockIndex* tip = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)];
+ try {
+ (void)GetBlockProofEquivalentTime(*to, *from, *tip, consensus_params);
+ } catch (const uint_error&) {
+ }
+ }
+ {
+ const Optional<uint256> hash = ConsumeDeserializable<uint256>(fuzzed_data_provider);
+ if (hash) {
+ (void)CheckProofOfWork(*hash, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), consensus_params);
+ }
+ }
+ }
+}
diff --git a/src/test/fuzz/prevector.cpp b/src/test/fuzz/prevector.cpp
new file mode 100644
index 0000000000..64920f4af5
--- /dev/null
+++ b/src/test/fuzz/prevector.cpp
@@ -0,0 +1,263 @@
+// Copyright (c) 2015-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/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+
+#include <prevector.h>
+#include <vector>
+
+#include <reverse_iterator.h>
+#include <serialize.h>
+#include <streams.h>
+
+namespace {
+
+template<unsigned int N, typename T>
+class prevector_tester {
+ typedef std::vector<T> realtype;
+ realtype real_vector;
+ realtype real_vector_alt;
+
+ typedef prevector<N, T> pretype;
+ pretype pre_vector;
+ pretype pre_vector_alt;
+
+ typedef typename pretype::size_type Size;
+
+public:
+ void test() const {
+ const pretype& const_pre_vector = pre_vector;
+ assert(real_vector.size() == pre_vector.size());
+ assert(real_vector.empty() == pre_vector.empty());
+ for (Size s = 0; s < real_vector.size(); s++) {
+ assert(real_vector[s] == pre_vector[s]);
+ assert(&(pre_vector[s]) == &(pre_vector.begin()[s]));
+ assert(&(pre_vector[s]) == &*(pre_vector.begin() + s));
+ assert(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
+ }
+ // assert(realtype(pre_vector) == real_vector);
+ assert(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
+ assert(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
+ size_t pos = 0;
+ for (const T& v : pre_vector) {
+ assert(v == real_vector[pos]);
+ ++pos;
+ }
+ for (const T& v : reverse_iterate(pre_vector)) {
+ --pos;
+ assert(v == real_vector[pos]);
+ }
+ for (const T& v : const_pre_vector) {
+ assert(v == real_vector[pos]);
+ ++pos;
+ }
+ for (const T& v : reverse_iterate(const_pre_vector)) {
+ --pos;
+ assert(v == real_vector[pos]);
+ }
+ CDataStream ss1(SER_DISK, 0);
+ CDataStream ss2(SER_DISK, 0);
+ ss1 << real_vector;
+ ss2 << pre_vector;
+ assert(ss1.size() == ss2.size());
+ for (Size s = 0; s < ss1.size(); s++) {
+ assert(ss1[s] == ss2[s]);
+ }
+ }
+
+ void resize(Size s) {
+ real_vector.resize(s);
+ assert(real_vector.size() == s);
+ pre_vector.resize(s);
+ assert(pre_vector.size() == s);
+ }
+
+ void reserve(Size s) {
+ real_vector.reserve(s);
+ assert(real_vector.capacity() >= s);
+ pre_vector.reserve(s);
+ assert(pre_vector.capacity() >= s);
+ }
+
+ void insert(Size position, const T& value) {
+ real_vector.insert(real_vector.begin() + position, value);
+ pre_vector.insert(pre_vector.begin() + position, value);
+ }
+
+ void insert(Size position, Size count, const T& value) {
+ real_vector.insert(real_vector.begin() + position, count, value);
+ pre_vector.insert(pre_vector.begin() + position, count, value);
+ }
+
+ template<typename I>
+ void insert_range(Size position, I first, I last) {
+ real_vector.insert(real_vector.begin() + position, first, last);
+ pre_vector.insert(pre_vector.begin() + position, first, last);
+ }
+
+ void erase(Size position) {
+ real_vector.erase(real_vector.begin() + position);
+ pre_vector.erase(pre_vector.begin() + position);
+ }
+
+ void erase(Size first, Size last) {
+ real_vector.erase(real_vector.begin() + first, real_vector.begin() + last);
+ pre_vector.erase(pre_vector.begin() + first, pre_vector.begin() + last);
+ }
+
+ void update(Size pos, const T& value) {
+ real_vector[pos] = value;
+ pre_vector[pos] = value;
+ }
+
+ void push_back(const T& value) {
+ real_vector.push_back(value);
+ pre_vector.push_back(value);
+ }
+
+ void pop_back() {
+ real_vector.pop_back();
+ pre_vector.pop_back();
+ }
+
+ void clear() {
+ real_vector.clear();
+ pre_vector.clear();
+ }
+
+ void assign(Size n, const T& value) {
+ real_vector.assign(n, value);
+ pre_vector.assign(n, value);
+ }
+
+ Size size() const {
+ return real_vector.size();
+ }
+
+ Size capacity() const {
+ return pre_vector.capacity();
+ }
+
+ void shrink_to_fit() {
+ pre_vector.shrink_to_fit();
+ }
+
+ void swap() {
+ real_vector.swap(real_vector_alt);
+ pre_vector.swap(pre_vector_alt);
+ }
+
+ void move() {
+ real_vector = std::move(real_vector_alt);
+ real_vector_alt.clear();
+ pre_vector = std::move(pre_vector_alt);
+ pre_vector_alt.clear();
+ }
+
+ void copy() {
+ real_vector = real_vector_alt;
+ pre_vector = pre_vector_alt;
+ }
+
+ void resize_uninitialized(realtype values) {
+ size_t r = values.size();
+ size_t s = real_vector.size() / 2;
+ if (real_vector.capacity() < s + r) {
+ real_vector.reserve(s + r);
+ }
+ real_vector.resize(s);
+ pre_vector.resize_uninitialized(s);
+ for (auto v : values) {
+ real_vector.push_back(v);
+ }
+ auto p = pre_vector.size();
+ pre_vector.resize_uninitialized(p + r);
+ for (auto v : values) {
+ pre_vector[p] = v;
+ ++p;
+ }
+ }
+};
+
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider prov(buffer.data(), buffer.size());
+ prevector_tester<8, int> test;
+
+ while (prov.remaining_bytes()) {
+ switch (prov.ConsumeIntegralInRange<int>(0, 13 + 3 * (test.size() > 0))) {
+ case 0:
+ test.insert(prov.ConsumeIntegralInRange<size_t>(0, test.size()), prov.ConsumeIntegral<int>());
+ break;
+ case 1:
+ test.resize(std::max(0, std::min(30, (int)test.size() + prov.ConsumeIntegralInRange<int>(0, 4) - 2)));
+ break;
+ case 2:
+ test.insert(prov.ConsumeIntegralInRange<size_t>(0, test.size()), 1 + prov.ConsumeBool(), prov.ConsumeIntegral<int>());
+ break;
+ case 3: {
+ int del = prov.ConsumeIntegralInRange<int>(0, test.size());
+ int beg = prov.ConsumeIntegralInRange<int>(0, test.size() - del);
+ test.erase(beg, beg + del);
+ break;
+ }
+ case 4:
+ test.push_back(prov.ConsumeIntegral<int>());
+ break;
+ case 5: {
+ int values[4];
+ int num = 1 + prov.ConsumeIntegralInRange<int>(0, 3);
+ for (int k = 0; k < num; ++k) {
+ values[k] = prov.ConsumeIntegral<int>();
+ }
+ test.insert_range(prov.ConsumeIntegralInRange<size_t>(0, test.size()), values, values + num);
+ break;
+ }
+ case 6: {
+ int num = 1 + prov.ConsumeIntegralInRange<int>(0, 15);
+ std::vector<int> values(num);
+ for (auto& v : values) {
+ v = prov.ConsumeIntegral<int>();
+ }
+ test.resize_uninitialized(values);
+ break;
+ }
+ case 7:
+ test.reserve(prov.ConsumeIntegralInRange<size_t>(0, 32767));
+ break;
+ case 8:
+ test.shrink_to_fit();
+ break;
+ case 9:
+ test.clear();
+ break;
+ case 10:
+ test.assign(prov.ConsumeIntegralInRange<size_t>(0, 32767), prov.ConsumeIntegral<int>());
+ break;
+ case 11:
+ test.swap();
+ break;
+ case 12:
+ test.copy();
+ break;
+ case 13:
+ test.move();
+ break;
+ case 14:
+ test.update(prov.ConsumeIntegralInRange<size_t>(0, test.size() - 1), prov.ConsumeIntegral<int>());
+ break;
+ case 15:
+ test.erase(prov.ConsumeIntegralInRange<size_t>(0, test.size() - 1));
+ break;
+ case 16:
+ test.pop_back();
+ break;
+ }
+ }
+
+ test.test();
+}
diff --git a/src/test/fuzz/primitives_transaction.cpp b/src/test/fuzz/primitives_transaction.cpp
new file mode 100644
index 0000000000..2e5ba6bdb0
--- /dev/null
+++ b/src/test/fuzz/primitives_transaction.cpp
@@ -0,0 +1,34 @@
+// 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 <optional.h>
+#include <primitives/transaction.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const CScript script = ConsumeScript(fuzzed_data_provider);
+ const Optional<COutPoint> out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
+ if (out_point) {
+ const CTxIn tx_in{*out_point, script, fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
+ (void)tx_in;
+ }
+ const CTxOut tx_out_1{ConsumeMoney(fuzzed_data_provider), script};
+ const CTxOut tx_out_2{ConsumeMoney(fuzzed_data_provider), ConsumeScript(fuzzed_data_provider)};
+ assert((tx_out_1 == tx_out_2) != (tx_out_1 != tx_out_2));
+ const Optional<CMutableTransaction> mutable_tx_1 = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ const Optional<CMutableTransaction> mutable_tx_2 = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ if (mutable_tx_1 && mutable_tx_2) {
+ const CTransaction tx_1{*mutable_tx_1};
+ const CTransaction tx_2{*mutable_tx_2};
+ assert((tx_1 == tx_2) != (tx_1 != tx_2));
+ }
+}
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
new file mode 100644
index 0000000000..c03365199a
--- /dev/null
+++ b/src/test/fuzz/process_message.cpp
@@ -0,0 +1,81 @@
+// 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 <banman.h>
+#include <chainparams.h>
+#include <consensus/consensus.h>
+#include <net.h>
+#include <net_processing.h>
+#include <protocol.h>
+#include <scheduler.h>
+#include <script/script.h>
+#include <streams.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/util/mining.h>
+#include <test/util/setup_common.h>
+#include <util/memory.h>
+#include <validationinterface.h>
+#include <version.h>
+
+#include <atomic>
+#include <cassert>
+#include <chrono>
+#include <cstdint>
+#include <iosfwd>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <vector>
+
+bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc);
+
+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()
+{
+ static TestingSetup setup{
+ CBaseChainParams::REGTEST,
+ {
+ "-nodebuglogfile",
+ },
+ };
+ g_setup = &setup;
+
+ for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
+ MineBlock(g_setup->m_node, CScript() << OP_TRUE);
+ }
+ SyncWithValidationInterfaceQueue();
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ 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;
+ }
+ CDataStream random_bytes_data_stream{fuzzed_data_provider.ConsumeRemainingBytes<unsigned char>(), SER_NETWORK, PROTOCOL_VERSION};
+ CNode p2p_node{0, ServiceFlags(NODE_NETWORK | NODE_WITNESS | NODE_BLOOM), 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, false};
+ p2p_node.fSuccessfullyConnected = true;
+ p2p_node.nVersion = PROTOCOL_VERSION;
+ p2p_node.SetSendVersion(PROTOCOL_VERSION);
+ g_setup->m_node.peer_logic->InitializeNode(&p2p_node);
+ try {
+ (void)ProcessMessage(&p2p_node, random_message_type, random_bytes_data_stream, GetTimeMillis(), Params(), *g_setup->m_node.mempool, g_setup->m_node.connman.get(), g_setup->m_node.banman.get(), std::atomic<bool>{false});
+ } catch (const std::ios_base::failure&) {
+ }
+ SyncWithValidationInterfaceQueue();
+}
diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp
new file mode 100644
index 0000000000..bcbf65bdca
--- /dev/null
+++ b/src/test/fuzz/process_messages.cpp
@@ -0,0 +1,80 @@
+// 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 <consensus/consensus.h>
+#include <net.h>
+#include <net_processing.h>
+#include <protocol.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <test/util/mining.h>
+#include <test/util/net.h>
+#include <test/util/setup_common.h>
+#include <util/memory.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+const TestingSetup* g_setup;
+
+void initialize()
+{
+ static TestingSetup setup{
+ CBaseChainParams::REGTEST,
+ {
+ "-nodebuglogfile",
+ },
+ };
+ g_setup = &setup;
+
+ for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
+ MineBlock(g_setup->m_node, CScript() << OP_TRUE);
+ }
+ SyncWithValidationInterfaceQueue();
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
+ std::vector<CNode*> peers;
+
+ const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3);
+ for (int i = 0; i < num_peers_to_add; ++i) {
+ const ServiceFlags service_flags = ServiceFlags(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
+ const bool inbound{fuzzed_data_provider.ConsumeBool()};
+ const bool block_relay_only{fuzzed_data_provider.ConsumeBool()};
+ peers.push_back(MakeUnique<CNode>(i, service_flags, 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, inbound, block_relay_only).release());
+ CNode& p2p_node = *peers.back();
+
+ p2p_node.fSuccessfullyConnected = true;
+ p2p_node.fPauseSend = false;
+ p2p_node.nVersion = PROTOCOL_VERSION;
+ p2p_node.SetSendVersion(PROTOCOL_VERSION);
+ g_setup->m_node.peer_logic->InitializeNode(&p2p_node);
+
+ connman.AddTestNode(p2p_node);
+ }
+
+ while (fuzzed_data_provider.ConsumeBool()) {
+ const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()};
+
+ CSerializedNetMsg net_msg;
+ net_msg.command = random_message_type;
+ net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+
+ CNode& random_node = *peers.at(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, peers.size() - 1));
+
+ (void)connman.ReceiveMsgFrom(random_node, net_msg);
+ random_node.fPauseSend = false;
+
+ try {
+ connman.ProcessMessagesOnce(random_node);
+ } catch (const std::ios_base::failure&) {
+ }
+ }
+ connman.ClearTestNodes();
+ SyncWithValidationInterfaceQueue();
+}
diff --git a/src/test/fuzz/protocol.cpp b/src/test/fuzz/protocol.cpp
new file mode 100644
index 0000000000..954471de6c
--- /dev/null
+++ b/src/test/fuzz/protocol.cpp
@@ -0,0 +1,32 @@
+// 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 <optional.h>
+#include <protocol.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <stdexcept>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const Optional<CInv> inv = ConsumeDeserializable<CInv>(fuzzed_data_provider);
+ if (!inv) {
+ return;
+ }
+ try {
+ (void)inv->GetCommand();
+ } catch (const std::out_of_range&) {
+ }
+ (void)inv->ToString();
+ const Optional<CInv> another_inv = ConsumeDeserializable<CInv>(fuzzed_data_provider);
+ if (!another_inv) {
+ return;
+ }
+ (void)(*inv < *another_inv);
+}
diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp
index 1ce28f9a6d..64328fb66e 100644
--- a/src/test/fuzz/psbt.cpp
+++ b/src/test/fuzz/psbt.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -19,7 +19,7 @@
void initialize()
{
- static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+ static const ECCVerifyHandle verify_handle;
}
void test_one_input(const std::vector<uint8_t>& buffer)
diff --git a/src/test/fuzz/random.cpp b/src/test/fuzz/random.cpp
new file mode 100644
index 0000000000..7df6594ad6
--- /dev/null
+++ b/src/test/fuzz/random.cpp
@@ -0,0 +1,31 @@
+// 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 <random.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ FastRandomContext fast_random_context{ConsumeUInt256(fuzzed_data_provider)};
+ (void)fast_random_context.rand64();
+ (void)fast_random_context.randbits(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 64));
+ (void)fast_random_context.randrange(fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(FastRandomContext::min() + 1, FastRandomContext::max()));
+ (void)fast_random_context.randbytes(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 1024));
+ (void)fast_random_context.rand32();
+ (void)fast_random_context.rand256();
+ (void)fast_random_context.randbool();
+ (void)fast_random_context();
+
+ std::vector<int64_t> integrals = ConsumeRandomLengthIntegralVector<int64_t>(fuzzed_data_provider);
+ Shuffle(integrals.begin(), integrals.end(), fast_random_context);
+ std::shuffle(integrals.begin(), integrals.end(), fast_random_context);
+}
diff --git a/src/test/fuzz/rbf.cpp b/src/test/fuzz/rbf.cpp
new file mode 100644
index 0000000000..eb54b05df9
--- /dev/null
+++ b/src/test/fuzz/rbf.cpp
@@ -0,0 +1,47 @@
+// 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 <optional.h>
+#include <policy/rbf.h>
+#include <primitives/transaction.h>
+#include <sync.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <txmempool.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ Optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ if (!mtx) {
+ return;
+ }
+ CTxMemPool pool;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ const Optional<CMutableTransaction> another_mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ if (!another_mtx) {
+ break;
+ }
+ const CTransaction another_tx{*another_mtx};
+ if (fuzzed_data_provider.ConsumeBool() && !mtx->vin.empty()) {
+ mtx->vin[0].prevout = COutPoint{another_tx.GetHash(), 0};
+ }
+ LOCK2(cs_main, pool.cs);
+ pool.addUnchecked(ConsumeTxMemPoolEntry(fuzzed_data_provider, another_tx));
+ }
+ const CTransaction tx{*mtx};
+ if (fuzzed_data_provider.ConsumeBool()) {
+ LOCK2(cs_main, pool.cs);
+ pool.addUnchecked(ConsumeTxMemPoolEntry(fuzzed_data_provider, tx));
+ }
+ {
+ LOCK(pool.cs);
+ (void)IsRBFOptIn(tx, pool);
+ }
+}
diff --git a/src/test/fuzz/rolling_bloom_filter.cpp b/src/test/fuzz/rolling_bloom_filter.cpp
new file mode 100644
index 0000000000..3b37321977
--- /dev/null
+++ b/src/test/fuzz/rolling_bloom_filter.cpp
@@ -0,0 +1,50 @@
+// 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 <bloom.h>
+#include <optional.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <uint256.h>
+
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ CRollingBloomFilter rolling_bloom_filter{
+ fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(1, 1000),
+ 0.999 / fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(1, std::numeric_limits<unsigned int>::max())};
+ while (fuzzed_data_provider.remaining_bytes() > 0) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 2)) {
+ case 0: {
+ const std::vector<unsigned char> b = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ (void)rolling_bloom_filter.contains(b);
+ rolling_bloom_filter.insert(b);
+ const bool present = rolling_bloom_filter.contains(b);
+ assert(present);
+ break;
+ }
+ case 1: {
+ const Optional<uint256> u256 = ConsumeDeserializable<uint256>(fuzzed_data_provider);
+ if (!u256) {
+ break;
+ }
+ (void)rolling_bloom_filter.contains(*u256);
+ rolling_bloom_filter.insert(*u256);
+ const bool present = rolling_bloom_filter.contains(*u256);
+ assert(present);
+ break;
+ }
+ case 2:
+ rolling_bloom_filter.reset();
+ break;
+ }
+ }
+}
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index 0469e87de6..de82122dd6 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -9,26 +9,43 @@
#include <policy/policy.h>
#include <pubkey.h>
#include <script/descriptor.h>
+#include <script/interpreter.h>
#include <script/script.h>
#include <script/sign.h>
#include <script/signingprovider.h>
#include <script/standard.h>
#include <streams.h>
+#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <univalue.h>
#include <util/memory.h>
void initialize()
{
// Fuzzers using pubkey must hold an ECCVerifyHandle.
- static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+ static const ECCVerifyHandle verify_handle;
+
+ SelectParams(CBaseChainParams::REGTEST);
}
void test_one_input(const std::vector<uint8_t>& buffer)
{
- const CScript script(buffer.begin(), buffer.end());
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const Optional<CScript> script_opt = ConsumeDeserializable<CScript>(fuzzed_data_provider);
+ if (!script_opt) return;
+ const CScript script{*script_opt};
std::vector<unsigned char> compressed;
- (void)CompressScript(script, compressed);
+ if (CompressScript(script, compressed)) {
+ const unsigned int size = compressed[0];
+ compressed.erase(compressed.begin());
+ assert(size >= 0 && size <= 5);
+ CScript decompressed_script;
+ const bool ok = DecompressScript(decompressed_script, size, compressed);
+ assert(ok);
+ assert(script == decompressed_script);
+ }
CTxDestination address;
(void)ExtractDestination(script, address);
@@ -61,4 +78,45 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)script.IsPushOnly();
(void)script.IsUnspendable();
(void)script.GetSigOpCount(/* fAccurate= */ false);
+
+ (void)FormatScript(script);
+ (void)ScriptToAsmStr(script, false);
+ (void)ScriptToAsmStr(script, true);
+
+ UniValue o1(UniValue::VOBJ);
+ ScriptPubKeyToUniv(script, o1, true);
+ UniValue o2(UniValue::VOBJ);
+ ScriptPubKeyToUniv(script, o2, false);
+ UniValue o3(UniValue::VOBJ);
+ ScriptToUniv(script, o3, true);
+ UniValue o4(UniValue::VOBJ);
+ ScriptToUniv(script, o4, false);
+
+ {
+ const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ // DecompressScript(..., ..., bytes) is not guaranteed to be defined if the bytes vector is too short
+ if (bytes.size() >= 32) {
+ CScript decompressed_script;
+ DecompressScript(decompressed_script, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), bytes);
+ }
+ }
+
+ const Optional<CScript> other_script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
+ if (other_script) {
+ {
+ CScript script_mut{script};
+ (void)FindAndDelete(script_mut, *other_script);
+ }
+ const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider);
+ const uint32_t u32{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
+ const uint32_t flags{u32 | SCRIPT_VERIFY_P2SH};
+ {
+ CScriptWitness wit;
+ for (const auto& s : random_string_vector) {
+ wit.stack.emplace_back(s.begin(), s.end());
+ }
+ (void)CountWitnessSigOps(script, *other_script, &wit, flags);
+ wit.SetNull();
+ }
+ }
}
diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp
index 08622d0979..ffc65eedc0 100644
--- a/src/test/fuzz/script_flags.cpp
+++ b/src/test/fuzz/script_flags.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -15,7 +15,7 @@ static bool IsValidFlagCombination(unsigned flags);
void initialize()
{
- static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+ static const ECCVerifyHandle verify_handle;
}
void test_one_input(const std::vector<uint8_t>& buffer)
diff --git a/src/test/fuzz/script_ops.cpp b/src/test/fuzz/script_ops.cpp
new file mode 100644
index 0000000000..7d24af20ac
--- /dev/null
+++ b/src/test/fuzz/script_ops.cpp
@@ -0,0 +1,71 @@
+// 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 <script/script.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ CScript script = ConsumeScript(fuzzed_data_provider);
+ while (fuzzed_data_provider.remaining_bytes() > 0) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 7)) {
+ case 0: {
+ CScript s = ConsumeScript(fuzzed_data_provider);
+ script = std::move(s);
+ break;
+ }
+ case 1: {
+ const CScript& s = ConsumeScript(fuzzed_data_provider);
+ script = s;
+ break;
+ }
+ case 2:
+ script << fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ break;
+ case 3:
+ script << ConsumeOpcodeType(fuzzed_data_provider);
+ break;
+ case 4:
+ script << ConsumeScriptNum(fuzzed_data_provider);
+ break;
+ case 5:
+ script << ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ break;
+ case 6:
+ script.clear();
+ break;
+ case 7: {
+ (void)script.GetSigOpCount(false);
+ (void)script.GetSigOpCount(true);
+ (void)script.GetSigOpCount(script);
+ (void)script.HasValidOps();
+ (void)script.IsPayToScriptHash();
+ (void)script.IsPayToWitnessScriptHash();
+ (void)script.IsPushOnly();
+ (void)script.IsUnspendable();
+ {
+ CScript::const_iterator pc = script.begin();
+ opcodetype opcode;
+ (void)script.GetOp(pc, opcode);
+ std::vector<uint8_t> data;
+ (void)script.GetOp(pc, opcode, data);
+ (void)script.IsPushOnly(pc);
+ }
+ {
+ int version;
+ std::vector<uint8_t> program;
+ (void)script.IsWitnessProgram(version, program);
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/src/test/fuzz/scriptnum_ops.cpp b/src/test/fuzz/scriptnum_ops.cpp
new file mode 100644
index 0000000000..f4e079fb89
--- /dev/null
+++ b/src/test/fuzz/scriptnum_ops.cpp
@@ -0,0 +1,134 @@
+// 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 <script/script.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <vector>
+
+namespace {
+bool IsValidAddition(const CScriptNum& lhs, const CScriptNum& rhs)
+{
+ return rhs == 0 || (rhs > 0 && lhs <= CScriptNum{std::numeric_limits<int64_t>::max()} - rhs) || (rhs < 0 && lhs >= CScriptNum{std::numeric_limits<int64_t>::min()} - rhs);
+}
+
+bool IsValidSubtraction(const CScriptNum& lhs, const CScriptNum& rhs)
+{
+ return rhs == 0 || (rhs > 0 && lhs >= CScriptNum{std::numeric_limits<int64_t>::min()} + rhs) || (rhs < 0 && lhs <= CScriptNum{std::numeric_limits<int64_t>::max()} + rhs);
+}
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ CScriptNum script_num = ConsumeScriptNum(fuzzed_data_provider);
+ while (fuzzed_data_provider.remaining_bytes() > 0) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 11)) {
+ case 0: {
+ const int64_t i = fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ assert((script_num == i) != (script_num != i));
+ assert((script_num <= i) != script_num > i);
+ assert((script_num >= i) != (script_num < i));
+ // Avoid signed integer overflow:
+ // script/script.h:264:93: runtime error: signed integer overflow: -2261405121394637306 + -9223372036854775802 cannot be represented in type 'long'
+ if (IsValidAddition(script_num, CScriptNum{i})) {
+ assert((script_num + i) - i == script_num);
+ }
+ // Avoid signed integer overflow:
+ // script/script.h:265:93: runtime error: signed integer overflow: 9223371895120855039 - -9223372036854710486 cannot be represented in type 'long'
+ if (IsValidSubtraction(script_num, CScriptNum{i})) {
+ assert((script_num - i) + i == script_num);
+ }
+ break;
+ }
+ case 1: {
+ const CScriptNum random_script_num = ConsumeScriptNum(fuzzed_data_provider);
+ assert((script_num == random_script_num) != (script_num != random_script_num));
+ assert((script_num <= random_script_num) != (script_num > random_script_num));
+ assert((script_num >= random_script_num) != (script_num < random_script_num));
+ // Avoid signed integer overflow:
+ // script/script.h:264:93: runtime error: signed integer overflow: -9223126527765971126 + -9223372036854756825 cannot be represented in type 'long'
+ if (IsValidAddition(script_num, random_script_num)) {
+ assert((script_num + random_script_num) - random_script_num == script_num);
+ }
+ // Avoid signed integer overflow:
+ // script/script.h:265:93: runtime error: signed integer overflow: 6052837899185946624 - -9223372036854775808 cannot be represented in type 'long'
+ if (IsValidSubtraction(script_num, random_script_num)) {
+ assert((script_num - random_script_num) + random_script_num == script_num);
+ }
+ break;
+ }
+ case 2: {
+ const CScriptNum random_script_num = ConsumeScriptNum(fuzzed_data_provider);
+ if (!IsValidAddition(script_num, random_script_num)) {
+ // Avoid assertion failure:
+ // ./script/script.h:292: CScriptNum &CScriptNum::operator+=(const int64_t &): Assertion `rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) || (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs)' failed.
+ break;
+ }
+ script_num += random_script_num;
+ break;
+ }
+ case 3: {
+ const CScriptNum random_script_num = ConsumeScriptNum(fuzzed_data_provider);
+ if (!IsValidSubtraction(script_num, random_script_num)) {
+ // Avoid assertion failure:
+ // ./script/script.h:300: CScriptNum &CScriptNum::operator-=(const int64_t &): Assertion `rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) || (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs)' failed.
+ break;
+ }
+ script_num -= random_script_num;
+ break;
+ }
+ case 4:
+ script_num = script_num & fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ break;
+ case 5:
+ script_num = script_num & ConsumeScriptNum(fuzzed_data_provider);
+ break;
+ case 6:
+ script_num &= ConsumeScriptNum(fuzzed_data_provider);
+ break;
+ case 7:
+ if (script_num == CScriptNum{std::numeric_limits<int64_t>::min()}) {
+ // Avoid assertion failure:
+ // ./script/script.h:279: CScriptNum CScriptNum::operator-() const: Assertion `m_value != std::numeric_limits<int64_t>::min()' failed.
+ break;
+ }
+ script_num = -script_num;
+ break;
+ case 8:
+ script_num = fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ break;
+ case 9: {
+ const int64_t random_integer = fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ if (!IsValidAddition(script_num, CScriptNum{random_integer})) {
+ // Avoid assertion failure:
+ // ./script/script.h:292: CScriptNum &CScriptNum::operator+=(const int64_t &): Assertion `rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) || (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs)' failed.
+ break;
+ }
+ script_num += random_integer;
+ break;
+ }
+ case 10: {
+ const int64_t random_integer = fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ if (!IsValidSubtraction(script_num, CScriptNum{random_integer})) {
+ // Avoid assertion failure:
+ // ./script/script.h:300: CScriptNum &CScriptNum::operator-=(const int64_t &): Assertion `rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) || (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs)' failed.
+ break;
+ }
+ script_num -= random_integer;
+ break;
+ }
+ case 11:
+ script_num &= fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ break;
+ }
+ (void)script_num.getint();
+ (void)script_num.getvch();
+ }
+}
diff --git a/src/test/fuzz/signature_checker.cpp b/src/test/fuzz/signature_checker.cpp
new file mode 100644
index 0000000000..4a8c7a63af
--- /dev/null
+++ b/src/test/fuzz/signature_checker.cpp
@@ -0,0 +1,68 @@
+// Copyright (c) 2009-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 <pubkey.h>
+#include <script/interpreter.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <util/memory.h>
+
+#include <cstdint>
+#include <limits>
+#include <string>
+#include <vector>
+
+void initialize()
+{
+ static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+}
+
+namespace {
+class FuzzedSignatureChecker : public BaseSignatureChecker
+{
+ FuzzedDataProvider& m_fuzzed_data_provider;
+
+public:
+ FuzzedSignatureChecker(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider(fuzzed_data_provider)
+ {
+ }
+
+ virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
+ {
+ return m_fuzzed_data_provider.ConsumeBool();
+ }
+
+ virtual bool CheckLockTime(const CScriptNum& nLockTime) const
+ {
+ return m_fuzzed_data_provider.ConsumeBool();
+ }
+
+ virtual bool CheckSequence(const CScriptNum& nSequence) const
+ {
+ return m_fuzzed_data_provider.ConsumeBool();
+ }
+
+ virtual ~FuzzedSignatureChecker() {}
+};
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
+ const SigVersion sig_version = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0});
+ const std::string script_string_1 = fuzzed_data_provider.ConsumeRandomLengthString(65536);
+ const std::vector<uint8_t> script_bytes_1{script_string_1.begin(), script_string_1.end()};
+ const std::string script_string_2 = fuzzed_data_provider.ConsumeRandomLengthString(65536);
+ const std::vector<uint8_t> script_bytes_2{script_string_2.begin(), script_string_2.end()};
+ std::vector<std::vector<unsigned char>> stack;
+ (void)EvalScript(stack, {script_bytes_1.begin(), script_bytes_1.end()}, flags, FuzzedSignatureChecker(fuzzed_data_provider), sig_version, nullptr);
+ if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0 && ((flags & SCRIPT_VERIFY_P2SH) == 0 || (flags & SCRIPT_VERIFY_WITNESS) == 0)) {
+ return;
+ }
+ if ((flags & SCRIPT_VERIFY_WITNESS) != 0 && (flags & SCRIPT_VERIFY_P2SH) == 0) {
+ return;
+ }
+ (void)VerifyScript({script_bytes_1.begin(), script_bytes_1.end()}, {script_bytes_2.begin(), script_bytes_2.end()}, nullptr, flags, FuzzedSignatureChecker(fuzzed_data_provider), nullptr);
+}
diff --git a/src/test/fuzz/span.cpp b/src/test/fuzz/span.cpp
new file mode 100644
index 0000000000..4aea530ef2
--- /dev/null
+++ b/src/test/fuzz/span.cpp
@@ -0,0 +1,39 @@
+// 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 <span.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ std::string str = fuzzed_data_provider.ConsumeBytesAsString(32);
+ const Span<const char> span = MakeSpan(str);
+ (void)span.data();
+ (void)span.begin();
+ (void)span.end();
+ if (span.size() > 0) {
+ const std::ptrdiff_t idx = fuzzed_data_provider.ConsumeIntegralInRange<std::ptrdiff_t>(0U, span.size() - 1U);
+ (void)span.first(idx);
+ (void)span.last(idx);
+ (void)span.subspan(idx);
+ (void)span.subspan(idx, span.size() - idx);
+ (void)span[idx];
+ }
+
+ std::string another_str = fuzzed_data_provider.ConsumeBytesAsString(32);
+ const Span<const char> another_span = MakeSpan(another_str);
+ assert((span <= another_span) != (span > another_span));
+ assert((span == another_span) != (span != another_span));
+ assert((span >= another_span) != (span < another_span));
+}
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
new file mode 100644
index 0000000000..49bee0e81f
--- /dev/null
+++ b/src/test/fuzz/string.cpp
@@ -0,0 +1,122 @@
+// 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 <blockfilter.h>
+#include <clientversion.h>
+#include <logging.h>
+#include <netbase.h>
+#include <outputtype.h>
+#include <rpc/client.h>
+#include <rpc/request.h>
+#include <rpc/server.h>
+#include <rpc/util.h>
+#include <script/descriptor.h>
+#include <serialize.h>
+#include <streams.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <util/error.h>
+#include <util/fees.h>
+#include <util/message.h>
+#include <util/settings.h>
+#include <util/strencodings.h>
+#include <util/string.h>
+#include <util/system.h>
+#include <util/translation.h>
+#include <util/url.h>
+#include <version.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const std::string random_string_1 = fuzzed_data_provider.ConsumeRandomLengthString(32);
+ const std::string random_string_2 = fuzzed_data_provider.ConsumeRandomLengthString(32);
+ const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider);
+
+ (void)AmountErrMsg(random_string_1, random_string_2);
+ (void)AmountHighWarn(random_string_1);
+ BlockFilterType block_filter_type;
+ (void)BlockFilterTypeByName(random_string_1, block_filter_type);
+ (void)Capitalize(random_string_1);
+ (void)CopyrightHolders(random_string_1);
+ FeeEstimateMode fee_estimate_mode;
+ (void)FeeModeFromString(random_string_1, fee_estimate_mode);
+ (void)FormatParagraph(random_string_1, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 1000), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 1000));
+ (void)FormatSubVersion(random_string_1, fuzzed_data_provider.ConsumeIntegral<int>(), random_string_vector);
+ (void)GetDescriptorChecksum(random_string_1);
+ (void)HelpExampleCli(random_string_1, random_string_2);
+ (void)HelpExampleRpc(random_string_1, random_string_2);
+ (void)HelpMessageGroup(random_string_1);
+ (void)HelpMessageOpt(random_string_1, random_string_2);
+ (void)IsDeprecatedRPCEnabled(random_string_1);
+ (void)Join(random_string_vector, random_string_1);
+ (void)JSONRPCError(fuzzed_data_provider.ConsumeIntegral<int>(), random_string_1);
+ const util::Settings settings;
+ (void)OnlyHasDefaultSectionSetting(settings, random_string_1, random_string_2);
+ (void)ParseNetwork(random_string_1);
+ try {
+ (void)ParseNonRFCJSONValue(random_string_1);
+ } catch (const std::runtime_error&) {
+ }
+ OutputType output_type;
+ (void)ParseOutputType(random_string_1, output_type);
+ (void)ResolveErrMsg(random_string_1, random_string_2);
+ try {
+ (void)RPCConvertNamedValues(random_string_1, random_string_vector);
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ (void)RPCConvertValues(random_string_1, random_string_vector);
+ } catch (const std::runtime_error&) {
+ }
+ (void)SanitizeString(random_string_1);
+ (void)SanitizeString(random_string_1, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 3));
+ (void)ShellEscape(random_string_1);
+ int port_out;
+ std::string host_out;
+ SplitHostPort(random_string_1, port_out, host_out);
+ (void)TimingResistantEqual(random_string_1, random_string_2);
+ (void)ToLower(random_string_1);
+ (void)ToUpper(random_string_1);
+ (void)TrimString(random_string_1);
+ (void)TrimString(random_string_1, random_string_2);
+ (void)urlDecode(random_string_1);
+ (void)ValidAsCString(random_string_1);
+ (void)_(random_string_1.c_str());
+
+ {
+ CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
+ std::string s;
+ LimitedString<10> limited_string = LIMITED_STRING(s, 10);
+ data_stream << random_string_1;
+ try {
+ data_stream >> limited_string;
+ assert(data_stream.empty());
+ assert(s.size() <= random_string_1.size());
+ assert(s.size() <= 10);
+ if (!random_string_1.empty()) {
+ assert(!s.empty());
+ }
+ } catch (const std::ios_base::failure&) {
+ }
+ }
+ {
+ CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
+ const LimitedString<10> limited_string = LIMITED_STRING(random_string_1, 10);
+ data_stream << limited_string;
+ std::string deserialized_string;
+ data_stream >> deserialized_string;
+ assert(data_stream.empty());
+ assert(deserialized_string == random_string_1);
+ }
+ {
+ int64_t amount_out;
+ (void)ParseFixedPoint(random_string_1, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1024), &amount_out);
+ }
+}
diff --git a/src/test/fuzz/strprintf.cpp b/src/test/fuzz/strprintf.cpp
index 0de21f0e7c..d5be1070bd 100644
--- a/src/test/fuzz/strprintf.cpp
+++ b/src/test/fuzz/strprintf.cpp
@@ -8,7 +8,6 @@
#include <util/strencodings.h>
#include <algorithm>
-#include <cassert>
#include <cstdint>
#include <string>
#include <vector>
@@ -27,7 +26,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
// * strprintf("%.222222200000000$", 1.1);
//
// Upstream bug report: https://github.com/c42f/tinyformat/issues/70
- if (format_string.find("%") != std::string::npos && digits_in_format_specifier >= 7) {
+ if (format_string.find('%') != std::string::npos && digits_in_format_specifier >= 7) {
return;
}
@@ -35,7 +34,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
// * strprintf("%1$*1$*", -11111111);
//
// Upstream bug report: https://github.com/c42f/tinyformat/issues/70
- if (format_string.find("%") != std::string::npos && format_string.find("$") != std::string::npos && format_string.find("*") != std::string::npos && digits_in_format_specifier > 0) {
+ if (format_string.find('%') != std::string::npos && format_string.find('$') != std::string::npos && format_string.find('*') != std::string::npos && digits_in_format_specifier > 0) {
return;
}
@@ -96,7 +95,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
try {
- switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 13)) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 5)) {
case 0:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeRandomLengthString(32));
break;
@@ -115,32 +114,52 @@ void test_one_input(const std::vector<uint8_t>& buffer)
case 5:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeBool());
break;
- case 6:
+ }
+ } catch (const tinyformat::format_error&) {
+ }
+
+ if (format_string.find('%') != std::string::npos && format_string.find('c') != std::string::npos) {
+ // Avoid triggering the following:
+ // * strprintf("%c", 1.31783e+38);
+ // tinyformat.h:244:36: runtime error: 1.31783e+38 is outside the range of representable values of type 'char'
+ return;
+ }
+
+ if (format_string.find('%') != std::string::npos && format_string.find('*') != std::string::npos) {
+ // Avoid triggering the following:
+ // * strprintf("%*", -2.33527e+38);
+ // tinyformat.h:283:65: runtime error: -2.33527e+38 is outside the range of representable values of type 'int'
+ // * strprintf("%*", -2147483648);
+ // tinyformat.h:763:25: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself
+ return;
+ }
+
+ try {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 7)) {
+ case 0:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeFloatingPoint<float>());
break;
- case 7:
+ case 1:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeFloatingPoint<double>());
break;
- case 8:
+ case 2:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int16_t>());
break;
- case 9:
+ case 3:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint16_t>());
break;
- case 10:
+ case 4:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int32_t>());
break;
- case 11:
+ case 5:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint32_t>());
break;
- case 12:
+ case 6:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int64_t>());
break;
- case 13:
+ case 7:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint64_t>());
break;
- default:
- assert(false);
}
} catch (const tinyformat::format_error&) {
}
diff --git a/src/test/fuzz/system.cpp b/src/test/fuzz/system.cpp
new file mode 100644
index 0000000000..7f378c2b13
--- /dev/null
+++ b/src/test/fuzz/system.cpp
@@ -0,0 +1,123 @@
+// 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/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <util/system.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace {
+std::string GetArgumentName(const std::string& name)
+{
+ size_t idx = name.find('=');
+ if (idx == std::string::npos) {
+ idx = name.size();
+ }
+ return name.substr(0, idx);
+}
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ ArgsManager args_manager{};
+
+ if (fuzzed_data_provider.ConsumeBool()) {
+ SetupHelpOptions(args_manager);
+ }
+
+ while (fuzzed_data_provider.ConsumeBool()) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 7)) {
+ case 0: {
+ args_manager.SelectConfigNetwork(fuzzed_data_provider.ConsumeRandomLengthString(16));
+ break;
+ }
+ case 1: {
+ args_manager.SoftSetArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeRandomLengthString(16));
+ break;
+ }
+ case 2: {
+ args_manager.ForceSetArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeRandomLengthString(16));
+ break;
+ }
+ case 3: {
+ args_manager.SoftSetBoolArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeBool());
+ break;
+ }
+ case 4: {
+ const OptionsCategory options_category = fuzzed_data_provider.PickValueInArray<OptionsCategory>({OptionsCategory::OPTIONS, OptionsCategory::CONNECTION, OptionsCategory::WALLET, OptionsCategory::WALLET_DEBUG_TEST, OptionsCategory::ZMQ, OptionsCategory::DEBUG_TEST, OptionsCategory::CHAINPARAMS, OptionsCategory::NODE_RELAY, OptionsCategory::BLOCK_CREATION, OptionsCategory::RPC, OptionsCategory::GUI, OptionsCategory::COMMANDS, OptionsCategory::REGISTER_COMMANDS, OptionsCategory::HIDDEN});
+ // Avoid hitting:
+ // util/system.cpp:425: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
+ const std::string argument_name = GetArgumentName(fuzzed_data_provider.ConsumeRandomLengthString(16));
+ if (args_manager.GetArgFlags(argument_name) != nullopt) {
+ break;
+ }
+ args_manager.AddArg(argument_name, fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeIntegral<unsigned int>(), options_category);
+ break;
+ }
+ case 5: {
+ // Avoid hitting:
+ // util/system.cpp:425: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
+ const std::vector<std::string> names = ConsumeRandomLengthStringVector(fuzzed_data_provider);
+ std::vector<std::string> hidden_arguments;
+ for (const std::string& name : names) {
+ const std::string hidden_argument = GetArgumentName(name);
+ if (args_manager.GetArgFlags(hidden_argument) != nullopt) {
+ continue;
+ }
+ if (std::find(hidden_arguments.begin(), hidden_arguments.end(), hidden_argument) != hidden_arguments.end()) {
+ continue;
+ }
+ hidden_arguments.push_back(hidden_argument);
+ }
+ args_manager.AddHiddenArgs(hidden_arguments);
+ break;
+ }
+ case 6: {
+ args_manager.ClearArgs();
+ break;
+ }
+ case 7: {
+ const std::vector<std::string> random_arguments = ConsumeRandomLengthStringVector(fuzzed_data_provider);
+ std::vector<const char*> argv;
+ argv.resize(random_arguments.size());
+ for (const std::string& random_argument : random_arguments) {
+ argv.push_back(random_argument.c_str());
+ }
+ try {
+ std::string error;
+ (void)args_manager.ParseParameters(argv.size(), argv.data(), error);
+ } catch (const std::logic_error&) {
+ }
+ break;
+ }
+ }
+ }
+
+ const std::string s1 = fuzzed_data_provider.ConsumeRandomLengthString(16);
+ const std::string s2 = fuzzed_data_provider.ConsumeRandomLengthString(16);
+ const int64_t i64 = fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ const bool b = fuzzed_data_provider.ConsumeBool();
+
+ (void)args_manager.GetArg(s1, i64);
+ (void)args_manager.GetArg(s1, s2);
+ (void)args_manager.GetArgFlags(s1);
+ (void)args_manager.GetArgs(s1);
+ (void)args_manager.GetBoolArg(s1, b);
+ try {
+ (void)args_manager.GetChainName();
+ } catch (const std::runtime_error&) {
+ }
+ (void)args_manager.GetHelpMessage();
+ (void)args_manager.GetUnrecognizedSections();
+ (void)args_manager.GetUnsuitableSectionOnlyArgs();
+ (void)args_manager.IsArgNegated(s1);
+ (void)args_manager.IsArgSet(s1);
+
+ (void)HelpRequested(args_manager);
+}
diff --git a/src/test/fuzz/timedata.cpp b/src/test/fuzz/timedata.cpp
new file mode 100644
index 0000000000..a0e579a88f
--- /dev/null
+++ b/src/test/fuzz/timedata.cpp
@@ -0,0 +1,29 @@
+// 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/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <timedata.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const unsigned int max_size = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 1000);
+ // Divide by 2 to avoid signed integer overflow in .median()
+ const int64_t initial_value = fuzzed_data_provider.ConsumeIntegral<int64_t>() / 2;
+ CMedianFilter<int64_t> median_filter{max_size, initial_value};
+ while (fuzzed_data_provider.remaining_bytes() > 0) {
+ (void)median_filter.median();
+ assert(median_filter.size() > 0);
+ assert(static_cast<size_t>(median_filter.size()) == median_filter.sorted().size());
+ assert(static_cast<unsigned int>(median_filter.size()) <= max_size || max_size == 0);
+ // Divide by 2 to avoid signed integer overflow in .median()
+ median_filter.input(fuzzed_data_provider.ConsumeIntegral<int64_t>() / 2);
+ }
+}
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index fefafda36b..d6deb7fc3d 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -1,7 +1,8 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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 <coins.h>
#include <consensus/tx_check.h>
#include <consensus/tx_verify.h>
@@ -13,12 +14,18 @@
#include <primitives/transaction.h>
#include <streams.h>
#include <test/fuzz/fuzz.h>
+#include <univalue.h>
#include <util/rbf.h>
#include <validation.h>
#include <version.h>
#include <cassert>
+void initialize()
+{
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
void test_one_input(const std::vector<uint8_t>& buffer)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
@@ -85,4 +92,23 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)IsStandardTx(tx, reason);
(void)RecursiveDynamicUsage(tx);
(void)SignalsOptInRBF(tx);
+
+ CCoinsView coins_view;
+ const CCoinsViewCache coins_view_cache(&coins_view);
+ (void)AreInputsStandard(tx, coins_view_cache);
+ (void)IsWitnessStandard(tx, coins_view_cache);
+
+ UniValue u(UniValue::VOBJ);
+ // ValueFromAmount(i) not defined when i == std::numeric_limits<int64_t>::min()
+ bool skip_tx_to_univ = false;
+ for (const CTxOut& txout : tx.vout) {
+ if (txout.nValue == std::numeric_limits<int64_t>::min()) {
+ skip_tx_to_univ = true;
+ }
+ }
+ if (!skip_tx_to_univ) {
+ TxToUniv(tx, /* hashBlock */ {}, u);
+ static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
+ TxToUniv(tx, u256_max, u);
+ }
}
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
new file mode 100644
index 0000000000..501bb1de5a
--- /dev/null
+++ b/src/test/fuzz/util.h
@@ -0,0 +1,152 @@
+// Copyright (c) 2009-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_FUZZ_UTIL_H
+#define BITCOIN_TEST_FUZZ_UTIL_H
+
+#include <amount.h>
+#include <arith_uint256.h>
+#include <attributes.h>
+#include <consensus/consensus.h>
+#include <optional.h>
+#include <primitives/transaction.h>
+#include <script/script.h>
+#include <serialize.h>
+#include <streams.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <txmempool.h>
+#include <uint256.h>
+#include <version.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+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 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;
+ for (size_t i = 0; i < n_elements; ++i) {
+ r.push_back(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
+ }
+ return r;
+}
+
+template <typename T>
+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;
+ for (size_t i = 0; i < n_elements; ++i) {
+ r.push_back(fuzzed_data_provider.ConsumeIntegral<T>());
+ }
+ return r;
+}
+
+template <typename T>
+NODISCARD inline 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};
+ T obj;
+ try {
+ ds >> obj;
+ } catch (const std::ios_base::failure&) {
+ return nullopt;
+ }
+ return obj;
+}
+
+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
+{
+ return fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, MAX_MONEY);
+}
+
+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
+{
+ return CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
+}
+
+NODISCARD inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept
+{
+ const std::vector<unsigned char> v256 = fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint256));
+ if (v256.size() != sizeof(uint256)) {
+ return {};
+ }
+ return uint256{v256};
+}
+
+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
+{
+ // Avoid:
+ // policy/feerate.cpp:28:34: runtime error: signed integer overflow: 34873208148477500 * 1000 cannot be represented in type 'long'
+ //
+ // Reproduce using CFeeRate(348732081484775, 10).GetFeePerK()
+ const CAmount fee = std::min<CAmount>(ConsumeMoney(fuzzed_data_provider), std::numeric_limits<CAmount>::max() / static_cast<CAmount>(100000));
+ assert(MoneyRange(fee));
+ const int64_t time = fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ const unsigned int entry_height = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
+ const bool spends_coinbase = fuzzed_data_provider.ConsumeBool();
+ const unsigned int sig_op_cost = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, MAX_BLOCK_SIGOPS_COST);
+ return CTxMemPoolEntry{MakeTransactionRef(tx), fee, time, entry_height, spends_coinbase, sig_op_cost, {}};
+}
+
+template <typename T>
+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) {
+ if (i > 0) {
+ if (j > 0) {
+ return i > (std::numeric_limits<T>::max() / j);
+ } else {
+ return j < (std::numeric_limits<T>::min() / i);
+ }
+ } else {
+ if (j > 0) {
+ return i < (std::numeric_limits<T>::min() / j);
+ } else {
+ return i != 0 && (j < (std::numeric_limits<T>::max() / i));
+ }
+ }
+ } else {
+ return j != 0 && i > std::numeric_limits<T>::max() / j;
+ }
+}
+
+template <class T>
+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) {
+ return (i > 0 && j > std::numeric_limits<T>::max() - i) ||
+ (i < 0 && j < std::numeric_limits<T>::min() - i);
+ }
+ return std::numeric_limits<T>::max() - i < j;
+}
+
+#endif // BITCOIN_TEST_FUZZ_UTIL_H
diff --git a/src/test/gen/crypto_gen.cpp b/src/test/gen/crypto_gen.cpp
deleted file mode 100644
index ca8c65806f..0000000000
--- a/src/test/gen/crypto_gen.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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.
-#include <test/gen/crypto_gen.h>
-
-#include <key.h>
-
-#include <rapidcheck/gen/Arbitrary.h>
-#include <rapidcheck/Gen.h>
-#include <rapidcheck/gen/Predicate.h>
-#include <rapidcheck/gen/Container.h>
-
-/** Generates 1 to 20 keys for OP_CHECKMULTISIG */
-rc::Gen<std::vector<CKey>> MultisigKeys()
-{
- return rc::gen::suchThat(rc::gen::arbitrary<std::vector<CKey>>(), [](const std::vector<CKey>& keys) {
- return keys.size() >= 1 && keys.size() <= 15;
- });
-};
diff --git a/src/test/gen/crypto_gen.h b/src/test/gen/crypto_gen.h
deleted file mode 100644
index 7c2fb0350f..0000000000
--- a/src/test/gen/crypto_gen.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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.
-#ifndef BITCOIN_TEST_GEN_CRYPTO_GEN_H
-#define BITCOIN_TEST_GEN_CRYPTO_GEN_H
-
-#include <key.h>
-#include <random.h>
-#include <uint256.h>
-#include <rapidcheck/gen/Arbitrary.h>
-#include <rapidcheck/Gen.h>
-#include <rapidcheck/gen/Create.h>
-#include <rapidcheck/gen/Numeric.h>
-
-/** Generates 1 to 15 keys for OP_CHECKMULTISIG */
-rc::Gen<std::vector<CKey>> MultisigKeys();
-
-namespace rc
-{
-/** Generator for a new CKey */
-template <>
-struct Arbitrary<CKey> {
- static Gen<CKey> arbitrary()
- {
- return rc::gen::map<int>([](int x) {
- CKey key;
- key.MakeNewKey(true);
- return key;
- });
- };
-};
-
-/** Generator for a CPrivKey */
-template <>
-struct Arbitrary<CPrivKey> {
- static Gen<CPrivKey> arbitrary()
- {
- return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) {
- return key.GetPrivKey();
- });
- };
-};
-
-/** Generator for a new CPubKey */
-template <>
-struct Arbitrary<CPubKey> {
- static Gen<CPubKey> arbitrary()
- {
- return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) {
- return key.GetPubKey();
- });
- };
-};
-/** Generates a arbitrary uint256 */
-template <>
-struct Arbitrary<uint256> {
- static Gen<uint256> arbitrary()
- {
- return rc::gen::just(GetRandHash());
- };
-};
-} //namespace rc
-#endif
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index 10fb05ca8a..512e48f8e5 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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/setup_common.h>
#include <util/strencodings.h>
#include <util/system.h>
-#include <test/util/setup_common.h>
#include <string>
#include <utility>
diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp
index b864e6e599..87f6470afa 100644
--- a/src/test/hash_tests.cpp
+++ b/src/test/hash_tests.cpp
@@ -1,12 +1,12 @@
-// Copyright (c) 2013-2019 The Bitcoin Core developers
+// Copyright (c) 2013-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 <clientversion.h>
#include <crypto/siphash.h>
#include <hash.h>
-#include <util/strencodings.h>
#include <test/util/setup_common.h>
+#include <util/strencodings.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp
new file mode 100644
index 0000000000..b0d4de89f3
--- /dev/null
+++ b/src/test/interfaces_tests.cpp
@@ -0,0 +1,163 @@
+// 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 <consensus/validation.h>
+#include <interfaces/chain.h>
+#include <script/standard.h>
+#include <test/util/setup_common.h>
+#include <validation.h>
+
+#include <boost/test/unit_test.hpp>
+
+using interfaces::FoundBlock;
+
+BOOST_FIXTURE_TEST_SUITE(interfaces_tests, TestChain100Setup)
+
+BOOST_AUTO_TEST_CASE(findBlock)
+{
+ auto chain = interfaces::MakeChain(m_node);
+ auto& active = ChainActive();
+
+ uint256 hash;
+ BOOST_CHECK(chain->findBlock(active[10]->GetBlockHash(), FoundBlock().hash(hash)));
+ BOOST_CHECK_EQUAL(hash, active[10]->GetBlockHash());
+
+ int height = -1;
+ BOOST_CHECK(chain->findBlock(active[20]->GetBlockHash(), FoundBlock().height(height)));
+ BOOST_CHECK_EQUAL(height, active[20]->nHeight);
+
+ CBlock data;
+ BOOST_CHECK(chain->findBlock(active[30]->GetBlockHash(), FoundBlock().data(data)));
+ BOOST_CHECK_EQUAL(data.GetHash(), active[30]->GetBlockHash());
+
+ int64_t time = -1;
+ BOOST_CHECK(chain->findBlock(active[40]->GetBlockHash(), FoundBlock().time(time)));
+ BOOST_CHECK_EQUAL(time, active[40]->GetBlockTime());
+
+ int64_t max_time = -1;
+ BOOST_CHECK(chain->findBlock(active[50]->GetBlockHash(), FoundBlock().maxTime(max_time)));
+ BOOST_CHECK_EQUAL(max_time, active[50]->GetBlockTimeMax());
+
+ int64_t mtp_time = -1;
+ BOOST_CHECK(chain->findBlock(active[60]->GetBlockHash(), FoundBlock().mtpTime(mtp_time)));
+ BOOST_CHECK_EQUAL(mtp_time, active[60]->GetMedianTimePast());
+
+ BOOST_CHECK(!chain->findBlock({}, FoundBlock()));
+}
+
+BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
+{
+ auto chain = interfaces::MakeChain(m_node);
+ auto& active = ChainActive();
+ uint256 hash;
+ int height;
+ BOOST_CHECK(chain->findFirstBlockWithTimeAndHeight(/* min_time= */ 0, /* min_height= */ 5, FoundBlock().hash(hash).height(height)));
+ BOOST_CHECK_EQUAL(hash, active[5]->GetBlockHash());
+ BOOST_CHECK_EQUAL(height, 5);
+ 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();
+ uint256 hash;
+ BOOST_CHECK(chain->findAncestorByHeight(active[20]->GetBlockHash(), 10, FoundBlock().hash(hash)));
+ BOOST_CHECK_EQUAL(hash, active[10]->GetBlockHash());
+ BOOST_CHECK(!chain->findAncestorByHeight(active[10]->GetBlockHash(), 20));
+}
+
+BOOST_AUTO_TEST_CASE(findAncestorByHash)
+{
+ auto chain = interfaces::MakeChain(m_node);
+ auto& active = ChainActive();
+ int height = -1;
+ BOOST_CHECK(chain->findAncestorByHash(active[20]->GetBlockHash(), active[10]->GetBlockHash(), FoundBlock().height(height)));
+ BOOST_CHECK_EQUAL(height, 10);
+ BOOST_CHECK(!chain->findAncestorByHash(active[10]->GetBlockHash(), active[20]->GetBlockHash()));
+}
+
+BOOST_AUTO_TEST_CASE(findCommonAncestor)
+{
+ auto chain = interfaces::MakeChain(m_node);
+ auto& active = ChainActive();
+ auto* orig_tip = active.Tip();
+ for (int i = 0; i < 10; ++i) {
+ BlockValidationState state;
+ ChainstateActive().InvalidateBlock(state, Params(), active.Tip());
+ }
+ BOOST_CHECK_EQUAL(active.Height(), orig_tip->nHeight - 10);
+ coinbaseKey.MakeNewKey(true);
+ for (int i = 0; i < 20; ++i) {
+ CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+ }
+ BOOST_CHECK_EQUAL(active.Height(), orig_tip->nHeight + 10);
+ uint256 fork_hash;
+ int fork_height;
+ int orig_height;
+ BOOST_CHECK(chain->findCommonAncestor(orig_tip->GetBlockHash(), active.Tip()->GetBlockHash(), FoundBlock().height(fork_height).hash(fork_hash), FoundBlock().height(orig_height)));
+ BOOST_CHECK_EQUAL(orig_height, orig_tip->nHeight);
+ BOOST_CHECK_EQUAL(fork_height, orig_tip->nHeight - 10);
+ BOOST_CHECK_EQUAL(fork_hash, active[fork_height]->GetBlockHash());
+
+ uint256 active_hash, orig_hash;
+ BOOST_CHECK(!chain->findCommonAncestor(active.Tip()->GetBlockHash(), {}, {}, FoundBlock().hash(active_hash), {}));
+ BOOST_CHECK(!chain->findCommonAncestor({}, orig_tip->GetBlockHash(), {}, {}, FoundBlock().hash(orig_hash)));
+ BOOST_CHECK_EQUAL(active_hash, active.Tip()->GetBlockHash());
+ BOOST_CHECK_EQUAL(orig_hash, orig_tip->GetBlockHash());
+}
+
+BOOST_AUTO_TEST_CASE(hasBlocks)
+{
+ auto chain = interfaces::MakeChain(m_node);
+ auto& active = ChainActive();
+
+ // Test ranges
+ BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 10, 90));
+ BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 10, {}));
+ BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 0, 90));
+ BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 0, {}));
+ BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), -1000, 1000));
+ active[5]->nStatus &= ~BLOCK_HAVE_DATA;
+ BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 10, 90));
+ BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 10, {}));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 0, 90));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 0, {}));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), -1000, 1000));
+ active[95]->nStatus &= ~BLOCK_HAVE_DATA;
+ BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 10, 90));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 10, {}));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 0, 90));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 0, {}));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), -1000, 1000));
+ active[50]->nStatus &= ~BLOCK_HAVE_DATA;
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 10, 90));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 10, {}));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 0, 90));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 0, {}));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), -1000, 1000));
+
+ // Test edge cases
+ BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 6, 49));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 5, 49));
+ BOOST_CHECK(!chain->hasBlocks(active.Tip()->GetBlockHash(), 6, 50));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp
index b52513f4af..d465ee6759 100644
--- a/src/test/key_io_tests.cpp
+++ b/src/test/key_io_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -8,8 +8,8 @@
#include <key.h>
#include <key_io.h>
#include <script/script.h>
-#include <util/strencodings.h>
#include <test/util/setup_common.h>
+#include <util/strencodings.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp
deleted file mode 100644
index 0e45a2549d..0000000000
--- a/src/test/key_properties.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2018-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 <key.h>
-
-#include <uint256.h>
-#include <test/util/setup_common.h>
-#include <vector>
-
-#include <boost/test/unit_test.hpp>
-#include <rapidcheck/boost_test.h>
-#include <rapidcheck/gen/Arbitrary.h>
-#include <rapidcheck/Gen.h>
-
-#include <test/gen/crypto_gen.h>
-
-BOOST_FIXTURE_TEST_SUITE(key_properties, BasicTestingSetup)
-
-/** Check CKey uniqueness */
-RC_BOOST_PROP(key_uniqueness, (const CKey& key1, const CKey& key2))
-{
- RC_ASSERT(!(key1 == key2));
-}
-
-/** Verify that a private key generates the correct public key */
-RC_BOOST_PROP(key_generates_correct_pubkey, (const CKey& key))
-{
- CPubKey pubKey = key.GetPubKey();
- RC_ASSERT(key.VerifyPubKey(pubKey));
-}
-
-/** Create a CKey using the 'Set' function must give us the same key */
-RC_BOOST_PROP(key_set_symmetry, (const CKey& key))
-{
- CKey key1;
- key1.Set(key.begin(), key.end(), key.IsCompressed());
- RC_ASSERT(key1 == key);
-}
-
-/** Create a CKey, sign a piece of data, then verify it with the public key */
-RC_BOOST_PROP(key_sign_symmetry, (const CKey& key, const uint256& hash))
-{
- std::vector<unsigned char> vchSig;
- key.Sign(hash, vchSig, 0);
- const CPubKey& pubKey = key.GetPubKey();
- RC_ASSERT(pubKey.Verify(hash, vchSig));
-}
-BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index 85dc961bea..cf2bd03698 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -1,14 +1,15 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <key.h>
#include <key_io.h>
+#include <test/util/setup_common.h>
#include <uint256.h>
-#include <util/system.h>
#include <util/strencodings.h>
-#include <test/util/setup_common.h>
+#include <util/string.h>
+#include <util/system.h>
#include <string>
#include <vector>
@@ -176,7 +177,7 @@ BOOST_AUTO_TEST_CASE(key_signature_tests)
bool found_small = false;
for (int i = 0; i < 256; ++i) {
sig.clear();
- std::string msg = "A message to be signed" + std::to_string(i);
+ std::string msg = "A message to be signed" + ToString(i);
msg_hash = Hash(msg.begin(), msg.end());
BOOST_CHECK(key.Sign(msg_hash, sig));
found = sig[3] == 0x20;
diff --git a/src/test/main.cpp b/src/test/main.cpp
index e6529949e2..5885564074 100644
--- a/src/test/main.cpp
+++ b/src/test/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -11,12 +11,16 @@
#include <test/util/setup_common.h>
-/** Redirect debug log to boost log */
+#include <iostream>
+
+/** Redirect debug log to unit_test.log files */
const std::function<void(const std::string&)> G_TEST_LOG_FUN = [](const std::string& s) {
- if (s.back() == '\n') {
- // boost will insert the new line
- BOOST_TEST_MESSAGE(s.substr(0, s.size() - 1));
- } else {
- BOOST_TEST_MESSAGE(s);
- }
+ static const bool should_log{std::any_of(
+ &boost::unit_test::framework::master_test_suite().argv[1],
+ &boost::unit_test::framework::master_test_suite().argv[boost::unit_test::framework::master_test_suite().argc],
+ [](const char* arg) {
+ return std::string{"DEBUG_LOG_OUT"} == arg;
+ })};
+ if (!should_log) return;
+ std::cout << s;
};
diff --git a/src/test/merkleblock_tests.cpp b/src/test/merkleblock_tests.cpp
index 9f8c4ba5c5..98b27994a6 100644
--- a/src/test/merkleblock_tests.cpp
+++ b/src/test/merkleblock_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <merkleblock.h>
-#include <uint256.h>
#include <test/util/setup_common.h>
+#include <uint256.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 97a918da45..dd2890c134 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -1,17 +1,17 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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 <key.h>
#include <policy/policy.h>
+#include <script/interpreter.h>
#include <script/script.h>
#include <script/script_error.h>
-#include <script/interpreter.h>
#include <script/sign.h>
#include <script/signingprovider.h>
+#include <test/util/setup_common.h>
#include <tinyformat.h>
#include <uint256.h>
-#include <test/util/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index cb1ef5dcf3..84bf593497 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -1,22 +1,24 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <clientversion.h>
-#include <test/util/setup_common.h>
-#include <string>
-#include <boost/test/unit_test.hpp>
-#include <serialize.h>
-#include <streams.h>
#include <net.h>
#include <netbase.h>
-#include <chainparams.h>
+#include <serialize.h>
+#include <streams.h>
+#include <test/util/setup_common.h>
#include <util/memory.h>
+#include <util/string.h>
#include <util/system.h>
+#include <boost/test/unit_test.hpp>
+
#include <memory>
+#include <string>
class CAddrManSerializationMock : public CAddrMan
{
@@ -85,7 +87,7 @@ BOOST_AUTO_TEST_CASE(cnode_listen_port)
BOOST_CHECK(port == Params().GetDefaultPort());
// test set port
unsigned short altPort = 12345;
- BOOST_CHECK(gArgs.SoftSetArg("-port", std::to_string(altPort)));
+ BOOST_CHECK(gArgs.SoftSetArg("-port", ToString(altPort)));
port = GetListenPort();
BOOST_CHECK(port == altPort);
}
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 9730b40580..ec6a290334 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <netbase.h>
#include <net_permissions.h>
+#include <netbase.h>
#include <test/util/setup_common.h>
#include <util/strencodings.h>
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index bf58bd63b9..a9d661438c 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -1,15 +1,15 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <arith_uint256.h>
#include <consensus/merkle.h>
#include <merkleblock.h>
#include <serialize.h>
#include <streams.h>
+#include <test/util/setup_common.h>
#include <uint256.h>
-#include <arith_uint256.h>
#include <version.h>
-#include <test/util/setup_common.h>
#include <vector>
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 025e2b78ca..06877898a4 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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 <policy/policy.h>
#include <policy/fees.h>
+#include <policy/policy.h>
#include <txmempool.h>
#include <uint256.h>
#include <util/time.h>
diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp
index 9782b78f2c..12c5848eaf 100644
--- a/src/test/prevector_tests.cpp
+++ b/src/test/prevector_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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 <vector>
#include <prevector.h>
+#include <vector>
#include <reverse_iterator.h>
#include <serialize.h>
diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp
index e0df41a971..ca3b92f2e1 100644
--- a/src/test/random_tests.cpp
+++ b/src/test/random_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -8,8 +8,8 @@
#include <boost/test/unit_test.hpp>
-#include <random>
#include <algorithm>
+#include <random>
BOOST_FIXTURE_TEST_SUITE(random_tests, BasicTestingSetup)
diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp
index 532fe143ae..a42608a66d 100644
--- a/src/test/reverselock_tests.cpp
+++ b/src/test/reverselock_tests.cpp
@@ -1,8 +1,8 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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 <reverselock.h>
+#include <sync.h>
#include <test/util/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -11,21 +11,50 @@ BOOST_FIXTURE_TEST_SUITE(reverselock_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(reverselock_basics)
{
- boost::mutex mutex;
- boost::unique_lock<boost::mutex> lock(mutex);
+ Mutex mutex;
+ WAIT_LOCK(mutex, lock);
BOOST_CHECK(lock.owns_lock());
{
- reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ REVERSE_LOCK(lock);
BOOST_CHECK(!lock.owns_lock());
}
BOOST_CHECK(lock.owns_lock());
}
+BOOST_AUTO_TEST_CASE(reverselock_multiple)
+{
+ Mutex mutex2;
+ Mutex mutex;
+ WAIT_LOCK(mutex2, lock2);
+ WAIT_LOCK(mutex, lock);
+
+ // Make sure undoing two locks succeeds
+ {
+ REVERSE_LOCK(lock);
+ BOOST_CHECK(!lock.owns_lock());
+ REVERSE_LOCK(lock2);
+ BOOST_CHECK(!lock2.owns_lock());
+ }
+ BOOST_CHECK(lock.owns_lock());
+ BOOST_CHECK(lock2.owns_lock());
+}
+
BOOST_AUTO_TEST_CASE(reverselock_errors)
{
- boost::mutex mutex;
- boost::unique_lock<boost::mutex> lock(mutex);
+ Mutex mutex2;
+ Mutex mutex;
+ WAIT_LOCK(mutex2, lock2);
+ WAIT_LOCK(mutex, lock);
+
+#ifdef DEBUG_LOCKORDER
+ // Make sure trying to reverse lock a previous lock fails
+ try {
+ REVERSE_LOCK(lock2);
+ BOOST_CHECK(false); // REVERSE_LOCK(lock2) succeeded
+ } catch(...) { }
+ BOOST_CHECK(lock2.owns_lock());
+#endif
// Make sure trying to reverse lock an unlocked lock fails
lock.unlock();
@@ -34,7 +63,7 @@ BOOST_AUTO_TEST_CASE(reverselock_errors)
bool failed = false;
try {
- reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ REVERSE_LOCK(lock);
} catch(...) {
failed = true;
}
@@ -49,7 +78,7 @@ BOOST_AUTO_TEST_CASE(reverselock_errors)
lock.lock();
BOOST_CHECK(lock.owns_lock());
{
- reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ REVERSE_LOCK(lock);
BOOST_CHECK(!lock.owns_lock());
}
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 84a3980b19..d9c66f1c19 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <rpc/server.h>
#include <rpc/client.h>
+#include <rpc/server.h>
#include <rpc/util.h>
#include <core_io.h>
diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp
index 4d50845256..9a490aaf6b 100644
--- a/src/test/sanity_tests.cpp
+++ b/src/test/sanity_tests.cpp
@@ -14,7 +14,7 @@ BOOST_AUTO_TEST_CASE(basic_sanity)
{
BOOST_CHECK_MESSAGE(glibc_sanity_test() == true, "libc sanity test");
BOOST_CHECK_MESSAGE(glibcxx_sanity_test() == true, "stdlib sanity test");
- BOOST_CHECK_MESSAGE(ECC_InitSanityCheck() == true, "openssl ECC test");
+ BOOST_CHECK_MESSAGE(ECC_InitSanityCheck() == true, "secp256k1 sanity test");
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
index b292d5b0d0..1395a7f38c 100644
--- a/src/test/scheduler_tests.cpp
+++ b/src/test/scheduler_tests.cpp
@@ -1,42 +1,31 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <random.h>
#include <scheduler.h>
+#include <util/time.h>
-#include <test/util/setup_common.h>
-
-#include <boost/thread.hpp>
#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
+
+#include <mutex>
BOOST_AUTO_TEST_SUITE(scheduler_tests)
-static void microTask(CScheduler& s, boost::mutex& mutex, int& counter, int delta, boost::chrono::system_clock::time_point rescheduleTime)
+static void microTask(CScheduler& s, std::mutex& mutex, int& counter, int delta, std::chrono::system_clock::time_point rescheduleTime)
{
{
- boost::unique_lock<boost::mutex> lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
counter += delta;
}
- boost::chrono::system_clock::time_point noTime = boost::chrono::system_clock::time_point::min();
+ std::chrono::system_clock::time_point noTime = std::chrono::system_clock::time_point::min();
if (rescheduleTime != noTime) {
CScheduler::Function f = std::bind(&microTask, std::ref(s), std::ref(mutex), std::ref(counter), -delta + 1, noTime);
s.schedule(f, rescheduleTime);
}
}
-static void MicroSleep(uint64_t n)
-{
-#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
- boost::this_thread::sleep_for(boost::chrono::microseconds(n));
-#elif defined(HAVE_WORKING_BOOST_SLEEP)
- boost::this_thread::sleep(boost::posix_time::microseconds(n));
-#else
- //should never get here
- #error missing boost sleep implementation
-#endif
-}
-
BOOST_AUTO_TEST_CASE(manythreads)
{
// Stress test: hundreds of microsecond-scheduled tasks,
@@ -51,22 +40,22 @@ BOOST_AUTO_TEST_CASE(manythreads)
// counters should sum to the number of initial tasks performed.
CScheduler microTasks;
- boost::mutex counterMutex[10];
+ std::mutex counterMutex[10];
int counter[10] = { 0 };
FastRandomContext rng{/* fDeterministic */ true};
auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9]
auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + (int)rc.randrange(1012); }; // [-11, 1000]
auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + (int)rc.randrange(2001); }; // [-1000, 1000]
- boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now();
- boost::chrono::system_clock::time_point now = start;
- boost::chrono::system_clock::time_point first, last;
+ std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
+ std::chrono::system_clock::time_point now = start;
+ std::chrono::system_clock::time_point first, last;
size_t nTasks = microTasks.getQueueInfo(first, last);
BOOST_CHECK(nTasks == 0);
for (int i = 0; i < 100; ++i) {
- boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng));
- boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng));
+ std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
+ std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
int whichCounter = zeroToNine(rng);
CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
@@ -83,15 +72,15 @@ BOOST_AUTO_TEST_CASE(manythreads)
for (int i = 0; i < 5; i++)
microThreads.create_thread(std::bind(&CScheduler::serviceQueue, &microTasks));
- MicroSleep(600);
- now = boost::chrono::system_clock::now();
+ UninterruptibleSleep(std::chrono::microseconds{600});
+ now = std::chrono::system_clock::now();
// More threads and more tasks:
for (int i = 0; i < 5; i++)
microThreads.create_thread(std::bind(&CScheduler::serviceQueue, &microTasks));
for (int i = 0; i < 100; i++) {
- boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng));
- boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng));
+ std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
+ std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
int whichCounter = zeroToNine(rng);
CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
@@ -111,6 +100,24 @@ BOOST_AUTO_TEST_CASE(manythreads)
BOOST_CHECK_EQUAL(counterSum, 200);
}
+BOOST_AUTO_TEST_CASE(wait_until_past)
+{
+ std::condition_variable condvar;
+ Mutex mtx;
+ WAIT_LOCK(mtx, lock);
+
+ const auto no_wait= [&](const std::chrono::seconds& d) {
+ return condvar.wait_until(lock, std::chrono::system_clock::now() - d);
+ };
+
+ BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::seconds{1}));
+ BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::minutes{1}));
+ BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::hours{1}));
+ BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::hours{10}));
+ BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::hours{100}));
+ BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::hours{1000}));
+}
+
BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered)
{
CScheduler scheduler;
@@ -155,4 +162,45 @@ BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered)
BOOST_CHECK_EQUAL(counter2, 100);
}
+BOOST_AUTO_TEST_CASE(mockforward)
+{
+ CScheduler scheduler;
+
+ int counter{0};
+ CScheduler::Function dummy = [&counter]{counter++;};
+
+ // schedule jobs for 2, 5 & 8 minutes into the future
+
+ scheduler.scheduleFromNow(dummy, std::chrono::minutes{2});
+ scheduler.scheduleFromNow(dummy, std::chrono::minutes{5});
+ scheduler.scheduleFromNow(dummy, std::chrono::minutes{8});
+
+ // check taskQueue
+ std::chrono::system_clock::time_point first, last;
+ size_t num_tasks = scheduler.getQueueInfo(first, last);
+ BOOST_CHECK_EQUAL(num_tasks, 3ul);
+
+ std::thread scheduler_thread([&]() { scheduler.serviceQueue(); });
+
+ // bump the scheduler forward 5 minutes
+ scheduler.MockForward(std::chrono::minutes{5});
+
+ // ensure scheduler has chance to process all tasks queued for before 1 ms from now.
+ scheduler.scheduleFromNow([&scheduler] { scheduler.stop(false); }, std::chrono::milliseconds{1});
+ scheduler_thread.join();
+
+ // check that the queue only has one job remaining
+ num_tasks = scheduler.getQueueInfo(first, last);
+ BOOST_CHECK_EQUAL(num_tasks, 1ul);
+
+ // check that the dummy function actually ran
+ BOOST_CHECK_EQUAL(counter, 2);
+
+ // check that the time of the remaining job has been updated
+ std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
+ int delta = std::chrono::duration_cast<std::chrono::seconds>(first - now).count();
+ // should be between 2 & 3 minutes from now
+ BOOST_CHECK(delta > 2*60 && delta < 3*60);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
index 8c1e843b0b..f6824a4e5e 100644
--- a/src/test/script_p2sh_tests.cpp
+++ b/src/test/script_p2sh_tests.cpp
@@ -1,17 +1,17 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <consensus/tx_verify.h>
#include <key.h>
-#include <validation.h>
#include <policy/policy.h>
+#include <policy/settings.h>
#include <script/script.h>
#include <script/script_error.h>
-#include <policy/settings.h>
#include <script/sign.h>
#include <script/signingprovider.h>
#include <test/util/setup_common.h>
+#include <validation.h>
#include <vector>
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 26015ca4c2..56454f61f3 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -6,16 +6,16 @@
#include <core_io.h>
#include <key.h>
+#include <rpc/util.h>
#include <script/script.h>
#include <script/script_error.h>
#include <script/sign.h>
#include <script/signingprovider.h>
-#include <util/system.h>
-#include <util/strencodings.h>
-#include <test/util/transaction_utils.h>
-#include <test/util/setup_common.h>
-#include <rpc/util.h>
#include <streams.h>
+#include <test/util/setup_common.h>
+#include <test/util/transaction_utils.h>
+#include <util/strencodings.h>
+#include <util/system.h>
#if defined(HAVE_CONSENSUS_LIB)
#include <script/bitcoinconsensus.h>
@@ -217,7 +217,6 @@ struct KeyData
KeyData()
{
-
key0.Set(vchKey0, vchKey0 + 32, false);
key0C.Set(vchKey0, vchKey0 + 32, true);
pubkey0 = key0.GetPubKey();
@@ -272,9 +271,9 @@ private:
void DoPush(const std::vector<unsigned char>& data)
{
- DoPush();
- push = data;
- havePush = true;
+ DoPush();
+ push = data;
+ havePush = true;
}
public:
@@ -306,10 +305,10 @@ public:
return *this;
}
- TestBuilder& Add(const CScript& _script)
+ TestBuilder& Opcode(const opcodetype& _op)
{
DoPush();
- spendTx.vin[0].scriptSig += _script;
+ spendTx.vin[0].scriptSig << _op;
return *this;
}
@@ -326,8 +325,9 @@ public:
return *this;
}
- TestBuilder& Push(const CScript& _script) {
- DoPush(std::vector<unsigned char>(_script.begin(), _script.end()));
+ TestBuilder& Push(const CScript& _script)
+ {
+ DoPush(std::vector<unsigned char>(_script.begin(), _script.end()));
return *this;
}
@@ -681,22 +681,22 @@ BOOST_AUTO_TEST_CASE(script_build)
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY", 0
- ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP));
+ ).Num(0).PushSig(keys.key1).Opcode(OP_DUP));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed using OP_DUP", SCRIPT_VERIFY_SIGPUSHONLY
- ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP).ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
+ ).Num(0).PushSig(keys.key1).Opcode(OP_DUP).ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY", 0, true
- ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem());
+ ).PushSig(keys.key2).Opcode(OP_NOP8).PushRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with non-push scriptSig but with P2SH validation", 0
- ).PushSig(keys.key2).Add(CScript() << OP_NOP8));
+ ).PushSig(keys.key2).Opcode(OP_NOP8));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", SCRIPT_VERIFY_P2SH, true
- ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
+ ).PushSig(keys.key2).Opcode(OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2SH(P2PK) with non-push scriptSig but not P2SH", SCRIPT_VERIFY_SIGPUSHONLY, true
- ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
+ ).PushSig(keys.key2).Opcode(OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed", SCRIPT_VERIFY_SIGPUSHONLY
).Num(0).PushSig(keys.key1).PushSig(keys.key1));
@@ -1470,24 +1470,6 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps)
BOOST_CHECK(!script.HasValidOps());
}
-BOOST_AUTO_TEST_CASE(script_can_append_self)
-{
- CScript s, d;
-
- s = ScriptFromHex("00");
- s += s;
- d = ScriptFromHex("0000");
- BOOST_CHECK(s == d);
-
- // check doubling a script that's large enough to require reallocation
- static const char hex[] = "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f";
- s = CScript() << ParseHex(hex) << OP_CHECKSIG;
- d = CScript() << ParseHex(hex) << OP_CHECKSIG << ParseHex(hex) << OP_CHECKSIG;
- s += s;
- BOOST_CHECK(s == d);
-}
-
-
#if defined(HAVE_CONSENSUS_LIB)
/* Test simple (successful) usage of bitcoinconsensus_verify_script */
diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h
index 9f928827cb..352797f18d 100644
--- a/src/test/scriptnum10.h
+++ b/src/test/scriptnum10.h
@@ -1,17 +1,17 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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_SCRIPTNUM10_H
#define BITCOIN_TEST_SCRIPTNUM10_H
+#include <assert.h>
#include <limits>
#include <stdexcept>
#include <stdint.h>
#include <string>
#include <vector>
-#include <assert.h>
class scriptnum10_error : public std::runtime_error
{
diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp
index 40a6f69668..281018be9f 100644
--- a/src/test/scriptnum_tests.cpp
+++ b/src/test/scriptnum_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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/scriptnum10.h>
#include <script/script.h>
+#include <test/scriptnum10.h>
#include <test/util/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 303bb9b88c..9a6c721ab8 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <hash.h>
#include <serialize.h>
#include <streams.h>
-#include <hash.h>
#include <test/util/setup_common.h>
#include <util/strencodings.h>
@@ -182,8 +182,8 @@ BOOST_AUTO_TEST_CASE(varints)
CDataStream ss(SER_DISK, 0);
CDataStream::size_type size = 0;
for (int i = 0; i < 100000; i++) {
- ss << VARINT(i, VarIntMode::NONNEGATIVE_SIGNED);
- size += ::GetSerializeSize(VARINT(i, VarIntMode::NONNEGATIVE_SIGNED), 0);
+ ss << VARINT_MODE(i, VarIntMode::NONNEGATIVE_SIGNED);
+ size += ::GetSerializeSize(VARINT_MODE(i, VarIntMode::NONNEGATIVE_SIGNED), 0);
BOOST_CHECK(size == ss.size());
}
@@ -196,7 +196,7 @@ BOOST_AUTO_TEST_CASE(varints)
// decode
for (int i = 0; i < 100000; i++) {
int j = -1;
- ss >> VARINT(j, VarIntMode::NONNEGATIVE_SIGNED);
+ ss >> VARINT_MODE(j, VarIntMode::NONNEGATIVE_SIGNED);
BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
}
@@ -210,21 +210,21 @@ BOOST_AUTO_TEST_CASE(varints)
BOOST_AUTO_TEST_CASE(varints_bitpatterns)
{
CDataStream ss(SER_DISK, 0);
- ss << VARINT(0, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "00"); ss.clear();
- ss << VARINT(0x7f, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
- ss << VARINT((int8_t)0x7f, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
- ss << VARINT(0x80, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
+ ss << VARINT_MODE(0, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "00"); ss.clear();
+ ss << VARINT_MODE(0x7f, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
+ ss << VARINT_MODE((int8_t)0x7f, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
+ ss << VARINT_MODE(0x80, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
ss << VARINT((uint8_t)0x80); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
- ss << VARINT(0x1234, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
- ss << VARINT((int16_t)0x1234, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
- ss << VARINT(0xffff, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
+ ss << VARINT_MODE(0x1234, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
+ ss << VARINT_MODE((int16_t)0x1234, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
+ ss << VARINT_MODE(0xffff, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
ss << VARINT((uint16_t)0xffff); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
- ss << VARINT(0x123456, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
- ss << VARINT((int32_t)0x123456, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
+ ss << VARINT_MODE(0x123456, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
+ ss << VARINT_MODE((int32_t)0x123456, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
ss << VARINT(0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear();
ss << VARINT((uint32_t)0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear();
ss << VARINT(0xffffffff); BOOST_CHECK_EQUAL(HexStr(ss), "8efefefe7f"); ss.clear();
- ss << VARINT(0x7fffffffffffffffLL, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "fefefefefefefefe7f"); ss.clear();
+ ss << VARINT_MODE(0x7fffffffffffffffLL, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "fefefefefefefefe7f"); ss.clear();
ss << VARINT(0xffffffffffffffffULL); BOOST_CHECK_EQUAL(HexStr(ss), "80fefefefefefefefe7f"); ss.clear();
}
diff --git a/src/test/settings_tests.cpp b/src/test/settings_tests.cpp
index 45644834a5..fcd831ccda 100644
--- a/src/test/settings_tests.cpp
+++ b/src/test/settings_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -11,6 +11,7 @@
#include <boost/test/unit_test.hpp>
#include <univalue.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <vector>
BOOST_FIXTURE_TEST_SUITE(settings_tests, BasicTestingSetup)
@@ -114,7 +115,7 @@ BOOST_FIXTURE_TEST_CASE(Merge, MergeTestingSetup)
std::vector<util::SettingsValue>& dest) {
if (action == SET || action == SECTION_SET) {
for (int i = 0; i < 2; ++i) {
- dest.push_back(value_prefix + std::to_string(++value_suffix));
+ dest.push_back(value_prefix + ToString(++value_suffix));
desc += " " + name_prefix + name + "=" + dest.back().get_str();
}
} else if (action == NEGATE || action == SECTION_NEGATE) {
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index bcc4a46873..5ca136ea6e 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -1,18 +1,18 @@
-// Copyright (c) 2013-2019 The Bitcoin Core developers
+// Copyright (c) 2013-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 <consensus/tx_check.h>
#include <consensus/validation.h>
-#include <test/data/sighash.json.h>
#include <hash.h>
#include <script/interpreter.h>
#include <script/script.h>
#include <serialize.h>
#include <streams.h>
+#include <test/data/sighash.json.h>
#include <test/util/setup_common.h>
-#include <util/system.h>
#include <util/strencodings.h>
+#include <util/system.h>
#include <version.h>
#include <iostream>
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index 6462fcefe3..6e36bce7a1 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -1,15 +1,15 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <consensus/consensus.h>
#include <consensus/tx_verify.h>
-#include <pubkey.h>
#include <key.h>
+#include <pubkey.h>
#include <script/script.h>
#include <script/standard.h>
-#include <uint256.h>
#include <test/util/setup_common.h>
+#include <uint256.h>
#include <vector>
diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp
index 19bd0d142f..8c880babd1 100644
--- a/src/test/timedata_tests.cpp
+++ b/src/test/timedata_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
//
@@ -8,6 +8,7 @@
#include <test/util/logging.h>
#include <test/util/setup_common.h>
#include <timedata.h>
+#include <util/string.h>
#include <warnings.h>
#include <string>
@@ -46,7 +47,7 @@ static void MultiAddTimeData(int n, int64_t offset)
static int cnt = 0;
for (int i = 0; i < n; ++i) {
CNetAddr addr;
- addr.SetInternal(std::to_string(++cnt));
+ addr.SetInternal(ToString(++cnt));
AddTimeData(addr, offset);
}
}
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index fb45ce0ee6..9d0ae56c3f 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -6,22 +6,23 @@
#include <test/data/tx_valid.json.h>
#include <test/util/setup_common.h>
-#include <clientversion.h>
#include <checkqueue.h>
+#include <clientversion.h>
#include <consensus/tx_check.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <key.h>
-#include <validation.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <script/script.h>
+#include <script/script_error.h>
#include <script/sign.h>
#include <script/signingprovider.h>
-#include <script/script_error.h>
#include <script/standard.h>
#include <streams.h>
+#include <test/util/transaction_utils.h>
#include <util/strencodings.h>
+#include <validation.h>
#include <map>
#include <string>
@@ -122,10 +123,9 @@ BOOST_AUTO_TEST_CASE(tx_valid)
std::map<COutPoint, int64_t> mapprevOutValues;
UniValue inputs = test[0].get_array();
bool fValid = true;
- for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
- const UniValue& input = inputs[inpIdx];
- if (!input.isArray())
- {
+ for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
+ const UniValue& input = inputs[inpIdx];
+ if (!input.isArray()) {
fValid = false;
break;
}
@@ -209,10 +209,9 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
std::map<COutPoint, int64_t> mapprevOutValues;
UniValue inputs = test[0].get_array();
bool fValid = true;
- for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
- const UniValue& input = inputs[inpIdx];
- if (!input.isArray())
- {
+ for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
+ const UniValue& input = inputs[inpIdx];
+ if (!input.isArray()) {
fValid = false;
break;
}
@@ -282,50 +281,13 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
BOOST_CHECK_MESSAGE(!CheckTransaction(CTransaction(tx), state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
}
-//
-// Helper: create two dummy transactions, each with
-// two outputs. The first has 11 and 50 CENT outputs
-// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
-// paid to a TX_PUBKEYHASH.
-//
-static std::vector<CMutableTransaction>
-SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet)
-{
- std::vector<CMutableTransaction> dummyTransactions;
- dummyTransactions.resize(2);
-
- // Add some keys to the keystore:
- CKey key[4];
- for (int i = 0; i < 4; i++)
- {
- key[i].MakeNewKey(i % 2);
- keystoreRet.AddKey(key[i]);
- }
-
- // Create some dummy input transactions
- dummyTransactions[0].vout.resize(2);
- dummyTransactions[0].vout[0].nValue = 11*CENT;
- dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
- dummyTransactions[0].vout[1].nValue = 50*CENT;
- dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
- AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0);
-
- dummyTransactions[1].vout.resize(2);
- dummyTransactions[1].vout[0].nValue = 21*CENT;
- dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey()));
- dummyTransactions[1].vout[1].nValue = 22*CENT;
- dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey()));
- AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0);
-
- return dummyTransactions;
-}
-
BOOST_AUTO_TEST_CASE(test_Get)
{
FillableSigningProvider keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
- std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+ std::vector<CMutableTransaction> dummyTransactions =
+ SetupDummyInputs(keystore, coins, {11*CENT, 50*CENT, 21*CENT, 22*CENT});
CMutableTransaction t1;
t1.vin.resize(3);
@@ -685,7 +647,8 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
FillableSigningProvider keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
- std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+ std::vector<CMutableTransaction> dummyTransactions =
+ SetupDummyInputs(keystore, coins, {11*CENT, 50*CENT, 21*CENT, 22*CENT});
CMutableTransaction t;
t.vin.resize(1);
@@ -821,9 +784,63 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
BOOST_CHECK_EQUAL(reason, "scriptsig-size");
+ // Check scriptSig format (non-standard if there are any other ops than just PUSHs)
+ t.vin[0].scriptSig = CScript()
+ << OP_TRUE << OP_0 << OP_1NEGATE << OP_16 // OP_n (single byte pushes: n = 1, 0, -1, 16)
+ << std::vector<unsigned char>(75, 0) // OP_PUSHx [...x bytes...]
+ << std::vector<unsigned char>(235, 0) // OP_PUSHDATA1 x [...x bytes...]
+ << std::vector<unsigned char>(1234, 0) // OP_PUSHDATA2 x [...x bytes...]
+ << OP_9;
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
+
+ const std::vector<unsigned char> non_push_ops = { // arbitrary set of non-push operations
+ OP_NOP, OP_VERIFY, OP_IF, OP_ROT, OP_3DUP, OP_SIZE, OP_EQUAL, OP_ADD, OP_SUB,
+ OP_HASH256, OP_CODESEPARATOR, OP_CHECKSIG, OP_CHECKLOCKTIMEVERIFY };
+
+ CScript::const_iterator pc = t.vin[0].scriptSig.begin();
+ while (pc < t.vin[0].scriptSig.end()) {
+ opcodetype opcode;
+ CScript::const_iterator prev_pc = pc;
+ t.vin[0].scriptSig.GetOp(pc, opcode); // advance to next op
+ // for the sake of simplicity, we only replace single-byte push operations
+ if (opcode >= 1 && opcode <= OP_PUSHDATA4)
+ continue;
+
+ int index = prev_pc - t.vin[0].scriptSig.begin();
+ unsigned char orig_op = *prev_pc; // save op
+ // replace current push-op with each non-push-op
+ for (auto op : non_push_ops) {
+ t.vin[0].scriptSig[index] = op;
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "scriptsig-not-pushonly");
+ }
+ t.vin[0].scriptSig[index] = orig_op; // restore op
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
+ }
+
+ // Check tx-size (non-standard if transaction weight is > MAX_STANDARD_TX_WEIGHT)
+ t.vin.clear();
+ t.vin.resize(2438); // size per input (empty scriptSig): 41 bytes
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << std::vector<unsigned char>(19, 0); // output size: 30 bytes
+ // tx header: 12 bytes => 48 vbytes
+ // 2438 inputs: 2438*41 = 99958 bytes => 399832 vbytes
+ // 1 output: 30 bytes => 120 vbytes
+ // ===============================
+ // total: 400000 vbytes
+ BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400000);
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
+
+ // increase output size by one byte, so we end up with 400004 vbytes
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << std::vector<unsigned char>(20, 0); // output size: 31 bytes
+ BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
+ reason.clear();
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "tx-size");
+
// Check bare multisig (standard if policy flag fIsBareMultisigStd is set)
fIsBareMultisigStd = true;
t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
+ t.vin.resize(1);
t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp
index 4b0214a15a..5fc172ee86 100644
--- a/src/test/txindex_tests.cpp
+++ b/src/test/txindex_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -34,7 +34,7 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
int64_t time_start = GetTimeMillis();
while (!txindex.BlockUntilSyncedToCurrentChain()) {
BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
- MilliSleep(100);
+ UninterruptibleSleep(std::chrono::milliseconds{100});
}
// Check that txindex excludes genesis block transactions.
@@ -70,10 +70,8 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
// shutdown sequence (c.f. Shutdown() in init.cpp)
txindex.Stop();
- threadGroup.interrupt_all();
- threadGroup.join_all();
-
- // Rest of shutdown sequence and destructors happen in ~TestingSetup()
+ // Let scheduler events finish running to avoid accessing any memory related to txindex after it is destructed
+ SyncWithValidationInterfaceQueue();
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp
index cace75f093..c3d7af8323 100644
--- a/src/test/txvalidation_tests.cpp
+++ b/src/test/txvalidation_tests.cpp
@@ -1,12 +1,12 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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 <validation.h>
#include <consensus/validation.h>
#include <primitives/transaction.h>
#include <script/script.h>
#include <test/util/setup_common.h>
+#include <validation.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index 7842594b80..cdef7dcc3c 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -4,12 +4,12 @@
#include <consensus/validation.h>
#include <key.h>
-#include <validation.h>
-#include <txmempool.h>
-#include <script/standard.h>
#include <script/sign.h>
#include <script/signingprovider.h>
+#include <script/standard.h>
#include <test/util/setup_common.h>
+#include <txmempool.h>
+#include <validation.h>
#include <boost/test/unit_test.hpp>
@@ -108,7 +108,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
// any script flag that is implemented as an upgraded NOP code.
static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
- PrecomputedTransactionData txdata(tx);
+ PrecomputedTransactionData txdata;
// If we add many more flags, this loop can get too expensive, but we can
// rewrite in the future to randomly pick a set of flags to evaluate.
for (uint32_t test_flags=0; test_flags < (1U << 16); test_flags += 1) {
@@ -200,7 +200,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
LOCK(cs_main);
TxValidationState state;
- PrecomputedTransactionData ptd_spend_tx(spend_tx);
+ PrecomputedTransactionData ptd_spend_tx;
BOOST_CHECK(!CheckInputScripts(CTransaction(spend_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
@@ -269,7 +269,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Make it valid, and check again
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
TxValidationState state;
- PrecomputedTransactionData txdata(invalid_with_cltv_tx);
+ PrecomputedTransactionData txdata;
BOOST_CHECK(CheckInputScripts(CTransaction(invalid_with_cltv_tx), state, ::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
}
@@ -297,7 +297,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Make it valid, and check again
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
TxValidationState state;
- PrecomputedTransactionData txdata(invalid_with_csv_tx);
+ PrecomputedTransactionData txdata;
BOOST_CHECK(CheckInputScripts(CTransaction(invalid_with_csv_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
}
@@ -358,7 +358,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
tx.vin[1].scriptWitness.SetNull();
TxValidationState state;
- PrecomputedTransactionData txdata(tx);
+ PrecomputedTransactionData txdata;
// This transaction is now invalid under segwit, because of the second input.
BOOST_CHECK(!CheckInputScripts(CTransaction(tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp
index 7293ecd325..c0ae2f8cf2 100644
--- a/src/test/uint256_tests.cpp
+++ b/src/test/uint256_tests.cpp
@@ -1,16 +1,17 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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 <arith_uint256.h>
#include <streams.h>
+#include <test/util/setup_common.h>
#include <uint256.h>
#include <version.h>
-#include <test/util/setup_common.h>
#include <boost/test/unit_test.hpp>
-#include <sstream>
+
#include <iomanip>
+#include <sstream>
#include <string>
BOOST_FIXTURE_TEST_SUITE(uint256_tests, BasicTestingSetup)
diff --git a/src/test/util/logging.cpp b/src/test/util/logging.cpp
index fe2e69104b..65a64f2384 100644
--- a/src/test/util/logging.cpp
+++ b/src/test/util/logging.cpp
@@ -11,13 +11,13 @@
#include <stdexcept>
-DebugLogHelper::DebugLogHelper(std::string message)
- : m_message{std::move(message)}
+DebugLogHelper::DebugLogHelper(std::string message, MatchFn match)
+ : m_message{std::move(message)}, m_match(std::move(match))
{
m_print_connection = LogInstance().PushBackCallback(
[this](const std::string& s) {
if (m_found) return;
- m_found = s.find(m_message) != std::string::npos;
+ m_found = s.find(m_message) != std::string::npos && m_match(&s);
});
noui_test_redirect();
}
@@ -26,7 +26,7 @@ void DebugLogHelper::check_found()
{
noui_reconnect();
LogInstance().DeleteCallback(m_print_connection);
- if (!m_found) {
+ if (!m_found && m_match(nullptr)) {
throw std::runtime_error(strprintf("'%s' not found in debug log\n", m_message));
}
}
diff --git a/src/test/util/logging.h b/src/test/util/logging.h
index 45ec44173c..1fcf7ca305 100644
--- a/src/test/util/logging.h
+++ b/src/test/util/logging.h
@@ -17,10 +17,22 @@ class DebugLogHelper
bool m_found{false};
std::list<std::function<void(const std::string&)>>::iterator m_print_connection;
+ //! Custom match checking function.
+ //!
+ //! Invoked with pointers to lines containing matching strings, and with
+ //! null if check_found() is called without any successful match.
+ //!
+ //! Can return true to enable default DebugLogHelper behavior of:
+ //! (1) ending search after first successful match, and
+ //! (2) raising an error in check_found if no match was found
+ //! Can return false to do the opposite in either case.
+ using MatchFn = std::function<bool(const std::string* line)>;
+ MatchFn m_match;
+
void check_found();
public:
- DebugLogHelper(std::string message);
+ 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
new file mode 100644
index 0000000000..09f2f1807f
--- /dev/null
+++ b/src/test/util/net.cpp
@@ -0,0 +1,39 @@
+// 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/net.h>
+
+#include <chainparams.h>
+#include <net.h>
+
+void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const
+{
+ assert(node.ReceiveMsgBytes(pch, nBytes, complete));
+ if (complete) {
+ size_t nSizeAdded = 0;
+ auto it(node.vRecvMsg.begin());
+ for (; it != node.vRecvMsg.end(); ++it) {
+ // vRecvMsg contains only completed CNetMessage
+ // the single possible partially deserialized message are held by TransportDeserializer
+ nSizeAdded += it->m_raw_message_size;
+ }
+ {
+ LOCK(node.cs_vProcessMsg);
+ node.vProcessMsg.splice(node.vProcessMsg.end(), node.vRecvMsg, node.vRecvMsg.begin(), it);
+ node.nProcessQueueSize += nSizeAdded;
+ node.fPauseRecv = node.nProcessQueueSize > nReceiveFloodSize;
+ }
+ }
+}
+
+bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const
+{
+ std::vector<unsigned char> 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);
+ return complete;
+}
diff --git a/src/test/util/net.h b/src/test/util/net.h
new file mode 100644
index 0000000000..ca8cb7fad5
--- /dev/null
+++ b/src/test/util/net.h
@@ -0,0 +1,33 @@
+// 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_NET_H
+#define BITCOIN_TEST_UTIL_NET_H
+
+#include <net.h>
+
+struct ConnmanTestMsg : public CConnman {
+ using CConnman::CConnman;
+ void AddTestNode(CNode& node)
+ {
+ LOCK(cs_vNodes);
+ vNodes.push_back(&node);
+ }
+ void ClearTestNodes()
+ {
+ LOCK(cs_vNodes);
+ for (CNode* node : vNodes) {
+ delete node;
+ }
+ vNodes.clear();
+ }
+
+ void ProcessMessagesOnce(CNode& node) { m_msgproc->ProcessMessages(&node, flagInterruptMsgProc); }
+
+ void NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const;
+
+ bool ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const;
+};
+
+#endif // BITCOIN_TEST_UTIL_NET_H
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index ccb3064d59..bf0afc4171 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -13,6 +13,7 @@
#include <init.h>
#include <miner.h>
#include <net.h>
+#include <net_processing.h>
#include <noui.h>
#include <pow.h>
#include <rpc/blockchain.h>
@@ -23,15 +24,18 @@
#include <txdb.h>
#include <util/memory.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <util/time.h>
#include <util/translation.h>
-#include <util/validation.h>
+#include <util/url.h>
+#include <util/vector.h>
#include <validation.h>
#include <validationinterface.h>
#include <functional>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
+UrlDecodeFn* const URL_DECODE = nullptr;
FastRandomContext g_insecure_rand_ctx;
/** Random context to get unique temp data dirs. Separate from g_insecure_rand_ctx, which can be seeded from a const env var */
@@ -62,17 +66,34 @@ std::ostream& operator<<(std::ostream& os, const uint256& num)
return os;
}
-BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
- : m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME / std::to_string(g_insecure_rand_ctx_temp_path.rand32())}
+BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
+ : m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME / g_insecure_rand_ctx_temp_path.rand256().ToString()}
{
+ const std::vector<const char*> arguments = Cat(
+ {
+ "dummy",
+ "-printtoconsole=0",
+ "-logtimemicros",
+ "-debug",
+ "-debugexclude=libevent",
+ "-debugexclude=leveldb",
+ },
+ extra_args);
fs::create_directories(m_path_root);
gArgs.ForceSetArg("-datadir", m_path_root.string());
ClearDatadirCache();
+ {
+ SetupServerArgs(m_node);
+ std::string error;
+ const bool success{m_node.args->ParseParameters(arguments.size(), arguments.data(), error)};
+ assert(success);
+ assert(error.empty());
+ }
SelectParams(chainName);
SeedInsecureRand();
- gArgs.ForceSetArg("-printtoconsole", "0");
if (G_TEST_LOG_FUN) LogInstance().PushBackCallback(G_TEST_LOG_FUN);
InitLogging();
+ AppInitParameterInteraction();
LogInstance().StartLogging();
SHA256AutoDetect();
ECC_Start();
@@ -92,10 +113,12 @@ BasicTestingSetup::~BasicTestingSetup()
{
LogInstance().DisconnectTestLogger();
fs::remove_all(m_path_root);
+ gArgs.ClearArgs();
ECC_Stop();
}
-TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
+TestingSetup::TestingSetup(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
@@ -103,13 +126,16 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
g_rpc_node = &m_node;
RegisterAllCoreRPCCommands(tableRPC);
+ m_node.scheduler = MakeUnique<CScheduler>();
+
// We have to run a scheduler thread to prevent ActivateBestChain
// from blocking due to queue overrun.
- threadGroup.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler));
- GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
+ threadGroup.create_thread([&]{ m_node.scheduler->serviceQueue(); });
+ GetMainSignals().RegisterBackgroundSignalScheduler(*g_rpc_node->scheduler);
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
- g_chainstate = MakeUnique<CChainState>();
+
+ g_chainman.InitializeChainstate();
::ChainstateActive().InitCoinsDB(
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
assert(!::ChainstateActive().CanFlushToDisk());
@@ -121,7 +147,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
BlockValidationState state;
if (!ActivateBestChain(state, chainparams)) {
- throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
+ 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.
@@ -135,10 +161,17 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
m_node.mempool->setSanityCheck(1.0);
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.peer_logic = MakeUnique<PeerLogicValidation>(m_node.connman.get(), m_node.banman.get(), *m_node.scheduler, *m_node.mempool);
+ {
+ CConnman::Options options;
+ options.m_msgproc = m_node.peer_logic.get();
+ m_node.connman->Init(options);
+ }
}
TestingSetup::~TestingSetup()
{
+ if (m_node.scheduler) m_node.scheduler->stop();
threadGroup.interrupt_all();
threadGroup.join_all();
GetMainSignals().FlushBackgroundCallbacks();
@@ -146,9 +179,11 @@ TestingSetup::~TestingSetup()
g_rpc_node = nullptr;
m_node.connman.reset();
m_node.banman.reset();
+ m_node.args = nullptr;
m_node.mempool = nullptr;
+ m_node.scheduler.reset();
UnloadBlockIndex();
- g_chainstate.reset();
+ g_chainman.Reset();
pblocktree.reset();
}
diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h
index 6741be8480..2477f9ad06 100644
--- a/src/test/util/setup_common.h
+++ b/src/test/util/setup_common.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -13,6 +13,7 @@
#include <random.h>
#include <scheduler.h>
#include <txmempool.h>
+#include <util/string.h>
#include <type_traits>
@@ -72,9 +73,11 @@ static constexpr CAmount CENT{1000000};
*/
struct BasicTestingSetup {
ECCVerifyHandle globalVerifyHandle;
+ NodeContext m_node;
- explicit BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ explicit BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
~BasicTestingSetup();
+
private:
const fs::path m_path_root;
};
@@ -83,11 +86,9 @@ private:
* Included are coins database, script check threads setup.
*/
struct TestingSetup : public BasicTestingSetup {
- NodeContext m_node;
boost::thread_group threadGroup;
- CScheduler scheduler;
- explicit TestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ explicit TestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
~TestingSetup();
};
diff --git a/src/test/util/transaction_utils.cpp b/src/test/util/transaction_utils.cpp
index 90b78effb0..7e5bb30a2c 100644
--- a/src/test/util/transaction_utils.cpp
+++ b/src/test/util/transaction_utils.cpp
@@ -1,7 +1,9 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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 <coins.h>
+#include <script/signingprovider.h>
#include <test/util/transaction_utils.h>
CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue)
@@ -37,3 +39,33 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CSc
return txSpend;
}
+
+std::vector<CMutableTransaction> SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet, const std::array<CAmount,4>& nValues)
+{
+ std::vector<CMutableTransaction> dummyTransactions;
+ dummyTransactions.resize(2);
+
+ // Add some keys to the keystore:
+ CKey key[4];
+ for (int i = 0; i < 4; i++) {
+ key[i].MakeNewKey(i % 2);
+ keystoreRet.AddKey(key[i]);
+ }
+
+ // Create some dummy input transactions
+ dummyTransactions[0].vout.resize(2);
+ dummyTransactions[0].vout[0].nValue = nValues[0];
+ dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
+ dummyTransactions[0].vout[1].nValue = nValues[1];
+ dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
+ AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0);
+
+ dummyTransactions[1].vout.resize(2);
+ dummyTransactions[1].vout[0].nValue = nValues[2];
+ dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey()));
+ dummyTransactions[1].vout[1].nValue = nValues[3];
+ dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey()));
+ AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0);
+
+ return dummyTransactions;
+}
diff --git a/src/test/util/transaction_utils.h b/src/test/util/transaction_utils.h
index 57604646e7..1beddd334b 100644
--- a/src/test/util/transaction_utils.h
+++ b/src/test/util/transaction_utils.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -7,6 +7,11 @@
#include <primitives/transaction.h>
+#include <array>
+
+class FillableSigningProvider;
+class CCoinsViewCache;
+
// create crediting transaction
// [1 coinbase input => 1 output with given scriptPubkey and value]
CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0);
@@ -16,4 +21,9 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int n
// 1 output with empty scriptPubKey, full value of referenced transaction]
CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit);
+// Helper: create two dummy transactions, each with two outputs.
+// The first has nValues[0] and nValues[1] outputs paid to a TX_PUBKEY,
+// the second nValues[2] and nValues[3] outputs paid to a TX_PUBKEYHASH.
+std::vector<CMutableTransaction> SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet, const std::array<CAmount,4>& nValues);
+
#endif // BITCOIN_TEST_UTIL_TRANSACTION_UTILS_H
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 6f0e464891..45b7fd4932 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -5,17 +5,22 @@
#include <util/system.h>
#include <clientversion.h>
+#include <hash.h> // For Hash()
+#include <key.h> // For CKey
#include <optional.h>
#include <sync.h>
#include <test/util/setup_common.h>
#include <test/util/str.h>
+#include <uint256.h>
+#include <util/message.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
#include <util/moneystr.h>
+#include <util/spanparsing.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/time.h>
-#include <util/spanparsing.h>
#include <util/vector.h>
+#include <array>
#include <stdint.h>
#include <thread>
#include <univalue.h>
@@ -340,6 +345,27 @@ BOOST_AUTO_TEST_CASE(util_ParseParameters)
BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2);
}
+BOOST_AUTO_TEST_CASE(util_ParseInvalidParameters)
+{
+ TestArgsManager test;
+ test.SetupArgs({{"-registered", ArgsManager::ALLOW_ANY}});
+
+ const char* argv[] = {"ignored", "-registered"};
+ std::string error;
+ BOOST_CHECK(test.ParseParameters(2, (char**)argv, error));
+ BOOST_CHECK_EQUAL(error, "");
+
+ argv[1] = "-unregistered";
+ BOOST_CHECK(!test.ParseParameters(2, (char**)argv, error));
+ BOOST_CHECK_EQUAL(error, "Invalid parameter -unregistered");
+
+ // Make sure registered parameters prefixed with a chain name trigger errors.
+ // (Previously, they were accepted and ignored.)
+ argv[1] = "-test.registered";
+ BOOST_CHECK(!test.ParseParameters(2, (char**)argv, error));
+ BOOST_CHECK_EQUAL(error, "Invalid parameter -test.registered");
+}
+
static void TestParse(const std::string& str, bool expected_bool, int64_t expected_int)
{
TestArgsManager test;
@@ -835,7 +861,8 @@ struct ArgsMergeTestingSetup : public BasicTestingSetup {
void ForEachMergeSetup(Fn&& fn)
{
ActionList arg_actions = {};
- ForEachNoDup(arg_actions, SET, SECTION_NEGATE, [&] {
+ // command_line_options do not have sections. Only iterate over SET and NEGATE
+ ForEachNoDup(arg_actions, SET, NEGATE, [&] {
ActionList conf_actions = {};
ForEachNoDup(conf_actions, SET, SECTION_NEGATE, [&] {
for (bool soft_set : {false, true}) {
@@ -867,7 +894,7 @@ struct ArgsMergeTestingSetup : public BasicTestingSetup {
if (action == SECTION_SET || action == SECTION_NEGATE) prefix = section + ".";
if (action == SET || action == SECTION_SET) {
for (int i = 0; i < 2; ++i) {
- values.push_back(prefix + name + "=" + value_prefix + std::to_string(++suffix));
+ values.push_back(prefix + name + "=" + value_prefix + ToString(++suffix));
}
}
if (action == NEGATE || action == SECTION_NEGATE) {
@@ -995,7 +1022,7 @@ BOOST_FIXTURE_TEST_CASE(util_ArgsMerge, ArgsMergeTestingSetup)
// Results file is formatted like:
//
// <input> || <IsArgSet/IsArgNegated/GetArg output> | <GetArgs output> | <GetUnsuitable output>
- BOOST_CHECK_EQUAL(out_sha_hex, "b835eef5977d69114eb039a976201f8c7121f34fe2b7ea2b73cafb516e5c9dc8");
+ BOOST_CHECK_EQUAL(out_sha_hex, "8fd4877bb8bf337badca950ede6c917441901962f160e52514e06a60dea46cde");
}
// Similar test as above, but for ArgsManager::GetChainName function.
@@ -1155,6 +1182,12 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
BOOST_CHECK_EQUAL(ret, COIN);
BOOST_CHECK(ParseMoney("1", ret));
BOOST_CHECK_EQUAL(ret, COIN);
+ BOOST_CHECK(ParseMoney(" 1", ret));
+ BOOST_CHECK_EQUAL(ret, COIN);
+ BOOST_CHECK(ParseMoney("1 ", ret));
+ BOOST_CHECK_EQUAL(ret, COIN);
+ BOOST_CHECK(ParseMoney(" 1 ", ret));
+ BOOST_CHECK_EQUAL(ret, COIN);
BOOST_CHECK(ParseMoney("0.1", ret));
BOOST_CHECK_EQUAL(ret, COIN/10);
BOOST_CHECK(ParseMoney("0.01", ret));
@@ -1171,6 +1204,26 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
BOOST_CHECK_EQUAL(ret, COIN/10000000);
BOOST_CHECK(ParseMoney("0.00000001", ret));
BOOST_CHECK_EQUAL(ret, COIN/100000000);
+ BOOST_CHECK(ParseMoney(" 0.00000001 ", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/100000000);
+ BOOST_CHECK(ParseMoney("0.00000001 ", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/100000000);
+ BOOST_CHECK(ParseMoney(" 0.00000001", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/100000000);
+
+ // Parsing amount that can not be represented in ret should fail
+ BOOST_CHECK(!ParseMoney("0.000000001", ret));
+
+ // Parsing empty string should fail
+ BOOST_CHECK(!ParseMoney("", ret));
+ BOOST_CHECK(!ParseMoney(" ", ret));
+ BOOST_CHECK(!ParseMoney(" ", ret));
+
+ // Parsing two numbers should fail
+ BOOST_CHECK(!ParseMoney("1 2", ret));
+ BOOST_CHECK(!ParseMoney(" 1 2 ", ret));
+ BOOST_CHECK(!ParseMoney(" 1.2 3 ", ret));
+ BOOST_CHECK(!ParseMoney(" 1 2.3 ", ret));
// Attempted 63 bit overflow should fail
BOOST_CHECK(!ParseMoney("92233720368.54775808", ret));
@@ -1300,7 +1353,7 @@ BOOST_AUTO_TEST_CASE(util_time_GetTime)
SetMockTime(111);
// Check that mock time does not change after a sleep
for (const auto& num_sleep : {0, 1}) {
- MilliSleep(num_sleep);
+ UninterruptibleSleep(std::chrono::milliseconds{num_sleep});
BOOST_CHECK_EQUAL(111, GetTime()); // Deprecated time getter
BOOST_CHECK_EQUAL(111, GetTime<std::chrono::seconds>().count());
BOOST_CHECK_EQUAL(111000, GetTime<std::chrono::milliseconds>().count());
@@ -1311,7 +1364,7 @@ BOOST_AUTO_TEST_CASE(util_time_GetTime)
// Check that system time changes after a sleep
const auto ms_0 = GetTime<std::chrono::milliseconds>();
const auto us_0 = GetTime<std::chrono::microseconds>();
- MilliSleep(1);
+ UninterruptibleSleep(std::chrono::milliseconds{1});
BOOST_CHECK(ms_0 < GetTime<std::chrono::milliseconds>());
BOOST_CHECK(us_0 < GetTime<std::chrono::microseconds>());
}
@@ -2003,4 +2056,109 @@ BOOST_AUTO_TEST_CASE(test_tracked_vector)
BOOST_CHECK_EQUAL(v8[2].copies, 0);
}
+BOOST_AUTO_TEST_CASE(message_sign)
+{
+ const std::array<unsigned char, 32> privkey_bytes = {
+ // just some random data
+ // derived address from this private key: 15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs
+ 0xD9, 0x7F, 0x51, 0x08, 0xF1, 0x1C, 0xDA, 0x6E,
+ 0xEE, 0xBA, 0xAA, 0x42, 0x0F, 0xEF, 0x07, 0x26,
+ 0xB1, 0xF8, 0x98, 0x06, 0x0B, 0x98, 0x48, 0x9F,
+ 0xA3, 0x09, 0x84, 0x63, 0xC0, 0x03, 0x28, 0x66
+ };
+
+ const std::string message = "Trust no one";
+
+ const std::string expected_signature =
+ "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=";
+
+ CKey privkey;
+ std::string generated_signature;
+
+ BOOST_REQUIRE_MESSAGE(!privkey.IsValid(),
+ "Confirm the private key is invalid");
+
+ BOOST_CHECK_MESSAGE(!MessageSign(privkey, message, generated_signature),
+ "Sign with an invalid private key");
+
+ privkey.Set(privkey_bytes.begin(), privkey_bytes.end(), true);
+
+ BOOST_REQUIRE_MESSAGE(privkey.IsValid(),
+ "Confirm the private key is valid");
+
+ BOOST_CHECK_MESSAGE(MessageSign(privkey, message, generated_signature),
+ "Sign with a valid private key");
+
+ BOOST_CHECK_EQUAL(expected_signature, generated_signature);
+}
+
+BOOST_AUTO_TEST_CASE(message_verify)
+{
+ BOOST_CHECK_EQUAL(
+ MessageVerify(
+ "invalid address",
+ "signature should be irrelevant",
+ "message too"),
+ MessageVerificationResult::ERR_INVALID_ADDRESS);
+
+ BOOST_CHECK_EQUAL(
+ MessageVerify(
+ "3B5fQsEXEaV8v6U3ejYc8XaKXAkyQj2MjV",
+ "signature should be irrelevant",
+ "message too"),
+ MessageVerificationResult::ERR_ADDRESS_NO_KEY);
+
+ BOOST_CHECK_EQUAL(
+ MessageVerify(
+ "1KqbBpLy5FARmTPD4VZnDDpYjkUvkr82Pm",
+ "invalid signature, not in base64 encoding",
+ "message should be irrelevant"),
+ MessageVerificationResult::ERR_MALFORMED_SIGNATURE);
+
+ BOOST_CHECK_EQUAL(
+ MessageVerify(
+ "1KqbBpLy5FARmTPD4VZnDDpYjkUvkr82Pm",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
+ "message should be irrelevant"),
+ MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED);
+
+ BOOST_CHECK_EQUAL(
+ MessageVerify(
+ "15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs",
+ "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
+ "I never signed this"),
+ MessageVerificationResult::ERR_NOT_SIGNED);
+
+ BOOST_CHECK_EQUAL(
+ MessageVerify(
+ "15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs",
+ "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
+ "Trust no one"),
+ MessageVerificationResult::OK);
+
+ BOOST_CHECK_EQUAL(
+ MessageVerify(
+ "11canuhp9X2NocwCq7xNrQYTmUgZAnLK3",
+ "IIcaIENoYW5jZWxsb3Igb24gYnJpbmsgb2Ygc2Vjb25kIGJhaWxvdXQgZm9yIGJhbmtzIAaHRtbCeDZINyavx14=",
+ "Trust me"),
+ MessageVerificationResult::OK);
+}
+
+BOOST_AUTO_TEST_CASE(message_hash)
+{
+ const std::string unsigned_tx = "...";
+ const std::string prefixed_message =
+ std::string(1, (char)MESSAGE_MAGIC.length()) +
+ MESSAGE_MAGIC +
+ std::string(1, (char)unsigned_tx.length()) +
+ unsigned_tx;
+
+ const uint256 signature_hash = Hash(unsigned_tx.begin(), unsigned_tx.end());
+ const uint256 message_hash1 = Hash(prefixed_message.begin(), prefixed_message.end());
+ const uint256 message_hash2 = MessageHash(unsigned_tx);
+
+ BOOST_CHECK_EQUAL(message_hash1, message_hash2);
+ BOOST_CHECK_NE(message_hash1, signature_hash);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_threadnames_tests.cpp b/src/test/util_threadnames_tests.cpp
index 78dbf848bb..f226caf717 100644
--- a/src/test/util_threadnames_tests.cpp
+++ b/src/test/util_threadnames_tests.cpp
@@ -1,14 +1,15 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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 <util/threadnames.h>
#include <test/util/setup_common.h>
+#include <util/string.h>
+#include <util/threadnames.h>
+#include <mutex>
+#include <set>
#include <thread>
#include <vector>
-#include <set>
-#include <mutex>
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
@@ -32,7 +33,7 @@ std::set<std::string> RenameEnMasse(int num_threads)
std::mutex lock;
auto RenameThisThread = [&](int i) {
- util::ThreadRename(TEST_THREAD_NAME_BASE + std::to_string(i));
+ util::ThreadRename(TEST_THREAD_NAME_BASE + ToString(i));
std::lock_guard<std::mutex> guard(lock);
names.insert(util::ThreadGetInternalName());
};
@@ -65,7 +66,7 @@ BOOST_AUTO_TEST_CASE(util_threadnames_test_rename_threaded)
// Names "test_thread.[n]" should exist for n = [0, 99]
for (int i = 0; i < 100; ++i) {
- BOOST_CHECK(names.find(TEST_THREAD_NAME_BASE + std::to_string(i)) != names.end());
+ BOOST_CHECK(names.find(TEST_THREAD_NAME_BASE + ToString(i)) != names.end());
}
}
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index dae389a167..c345f1eafb 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
@@ -42,7 +42,7 @@ struct TestSubscriber : public CValidationInterface {
BOOST_CHECK_EQUAL(m_expected_tip, pindexNew->GetBlockHash());
}
- void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex, const std::vector<CTransactionRef>& txnConflicted) override
+ void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override
{
BOOST_CHECK_EQUAL(m_expected_tip, block->hashPrevBlock);
BOOST_CHECK_EQUAL(m_expected_tip, pindex->pprev->GetBlockHash());
@@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
t.join();
}
while (GetMainSignals().CallbacksPending() > 0) {
- MilliSleep(100);
+ UninterruptibleSleep(std::chrono::milliseconds{100});
}
UnregisterValidationInterface(&sub);
@@ -340,4 +340,38 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
rpc_thread.join();
}
}
+
+BOOST_AUTO_TEST_CASE(witness_commitment_index)
+{
+ CScript pubKey;
+ pubKey << 1 << OP_TRUE;
+ auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(pubKey);
+ CBlock pblock = ptemplate->block;
+
+ CTxOut witness;
+ witness.scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT);
+ witness.scriptPubKey[0] = OP_RETURN;
+ witness.scriptPubKey[1] = 0x24;
+ witness.scriptPubKey[2] = 0xaa;
+ witness.scriptPubKey[3] = 0x21;
+ witness.scriptPubKey[4] = 0xa9;
+ witness.scriptPubKey[5] = 0xed;
+
+ // A witness larger than the minimum size is still valid
+ CTxOut min_plus_one = witness;
+ min_plus_one.scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT + 1);
+
+ CTxOut invalid = witness;
+ invalid.scriptPubKey[0] = OP_VERIFY;
+
+ CMutableTransaction txCoinbase(*pblock.vtx[0]);
+ txCoinbase.vout.resize(4);
+ txCoinbase.vout[0] = witness;
+ txCoinbase.vout[1] = witness;
+ txCoinbase.vout[2] = min_plus_one;
+ txCoinbase.vout[3] = invalid;
+ pblock.vtx[0] = MakeTransactionRef(std::move(txCoinbase));
+
+ BOOST_CHECK_EQUAL(GetWitnessCommitmentIndex(pblock), 2);
+}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp
new file mode 100644
index 0000000000..0d149285ad
--- /dev/null
+++ b/src/test/validation_chainstatemanager_tests.cpp
@@ -0,0 +1,107 @@
+// Copyright (c) 2019-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 <consensus/validation.h>
+#include <random.h>
+#include <sync.h>
+#include <test/util/setup_common.h>
+#include <uint256.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, TestingSetup)
+
+//! Basic tests for ChainstateManager.
+//!
+//! First create a legacy (IBD) chainstate, then create a snapshot chainstate.
+BOOST_AUTO_TEST_CASE(chainstatemanager)
+{
+ ChainstateManager manager;
+ std::vector<CChainState*> chainstates;
+ const CChainParams& chainparams = Params();
+
+ // Create a legacy (IBD) chainstate.
+ //
+ ENTER_CRITICAL_SECTION(cs_main);
+ CChainState& c1 = manager.InitializeChainstate();
+ LEAVE_CRITICAL_SECTION(cs_main);
+ chainstates.push_back(&c1);
+ c1.InitCoinsDB(
+ /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
+ WITH_LOCK(::cs_main, c1.InitCoinsCache());
+
+ BOOST_CHECK(!manager.IsSnapshotActive());
+ BOOST_CHECK(!manager.IsSnapshotValidated());
+ BOOST_CHECK(!manager.IsBackgroundIBD(&c1));
+ auto all = manager.GetAll();
+ BOOST_CHECK_EQUAL_COLLECTIONS(all.begin(), all.end(), chainstates.begin(), chainstates.end());
+
+ auto& active_chain = manager.ActiveChain();
+ BOOST_CHECK_EQUAL(&active_chain, &c1.m_chain);
+
+ BOOST_CHECK_EQUAL(manager.ActiveHeight(), -1);
+
+ auto active_tip = manager.ActiveTip();
+ auto exp_tip = c1.m_chain.Tip();
+ BOOST_CHECK_EQUAL(active_tip, exp_tip);
+
+ auto& validated_cs = manager.ValidatedChainstate();
+ BOOST_CHECK_EQUAL(&validated_cs, &c1);
+
+ // Create a snapshot-based chainstate.
+ //
+ ENTER_CRITICAL_SECTION(cs_main);
+ CChainState& c2 = manager.InitializeChainstate(GetRandHash());
+ LEAVE_CRITICAL_SECTION(cs_main);
+ chainstates.push_back(&c2);
+ c2.InitCoinsDB(
+ /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
+ WITH_LOCK(::cs_main, c2.InitCoinsCache());
+ // Unlike c1, which doesn't have any blocks. Gets us different tip, height.
+ c2.LoadGenesisBlock(chainparams);
+ BlockValidationState _;
+ BOOST_CHECK(c2.ActivateBestChain(_, chainparams, nullptr));
+
+ BOOST_CHECK(manager.IsSnapshotActive());
+ BOOST_CHECK(!manager.IsSnapshotValidated());
+ BOOST_CHECK(manager.IsBackgroundIBD(&c1));
+ BOOST_CHECK(!manager.IsBackgroundIBD(&c2));
+ auto all2 = manager.GetAll();
+ BOOST_CHECK_EQUAL_COLLECTIONS(all2.begin(), all2.end(), chainstates.begin(), chainstates.end());
+
+ auto& active_chain2 = manager.ActiveChain();
+ BOOST_CHECK_EQUAL(&active_chain2, &c2.m_chain);
+
+ BOOST_CHECK_EQUAL(manager.ActiveHeight(), 0);
+
+ auto active_tip2 = manager.ActiveTip();
+ auto exp_tip2 = c2.m_chain.Tip();
+ BOOST_CHECK_EQUAL(active_tip2, exp_tip2);
+
+ // Ensure that these pointers actually correspond to different
+ // CCoinsViewCache instances.
+ BOOST_CHECK(exp_tip != exp_tip2);
+
+ auto& validated_cs2 = manager.ValidatedChainstate();
+ BOOST_CHECK_EQUAL(&validated_cs2, &c1);
+
+ auto& validated_chain = manager.ValidatedChain();
+ BOOST_CHECK_EQUAL(&validated_chain, &c1.m_chain);
+
+ auto validated_tip = manager.ValidatedTip();
+ exp_tip = c1.m_chain.Tip();
+ BOOST_CHECK_EQUAL(validated_tip, exp_tip);
+
+ // Let scheduler events finish running to avoid accessing memory that is going to be unloaded
+ SyncWithValidationInterfaceQueue();
+
+ WITH_LOCK(::cs_main, manager.Unload());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/validation_flush_tests.cpp b/src/test/validation_flush_tests.cpp
index ab8b957f7d..388a2dbd13 100644
--- a/src/test/validation_flush_tests.cpp
+++ b/src/test/validation_flush_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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 <txmempool.h>
-#include <validation.h>
#include <sync.h>
#include <test/util/setup_common.h>
+#include <txmempool.h>
+#include <validation.h>
#include <boost/test/unit_test.hpp>
@@ -85,12 +85,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate)
// This is contingent not only on the dynamic memory usage of the Coins
// that we're adding (COIN_SIZE bytes per), but also on how much memory the
// cacheCoins (unordered_map) preallocates.
- //
- // I came up with the count by examining the printed memory usage of the
- // CCoinsCacheView, so it's sort of arbitrary - but it shouldn't change
- // unless we somehow change the way the cacheCoins map allocates memory.
- //
- constexpr int COINS_UNTIL_CRITICAL = is_64_bit ? 4 : 5;
+ constexpr int COINS_UNTIL_CRITICAL{3};
for (int i{0}; i < COINS_UNTIL_CRITICAL; ++i) {
COutPoint res = add_coin(view);
@@ -101,17 +96,14 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate)
CoinsCacheSizeState::OK);
}
- // Adding an additional coin will push us over the edge to CRITICAL.
- add_coin(view);
- print_view_mem_usage(view);
-
- auto size_state = chainstate.GetCoinsCacheSizeState(
- tx_pool, MAX_COINS_CACHE_BYTES, /*max_mempool_size_bytes*/ 0);
-
- if (!is_64_bit && size_state == CoinsCacheSizeState::LARGE) {
- // On 32 bit hosts, we may hit LARGE before CRITICAL.
+ // Adding some additional coins will push us over the edge to CRITICAL.
+ for (int i{0}; i < 4; ++i) {
add_coin(view);
print_view_mem_usage(view);
+ if (chainstate.GetCoinsCacheSizeState(tx_pool, MAX_COINS_CACHE_BYTES, /*max_mempool_size_bytes*/ 0) ==
+ CoinsCacheSizeState::CRITICAL) {
+ break;
+ }
}
BOOST_CHECK_EQUAL(
diff --git a/src/test/validationinterface_tests.cpp b/src/test/validationinterface_tests.cpp
new file mode 100644
index 0000000000..208be92852
--- /dev/null
+++ b/src/test/validationinterface_tests.cpp
@@ -0,0 +1,60 @@
+// 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 <boost/test/unit_test.hpp>
+#include <consensus/validation.h>
+#include <primitives/block.h>
+#include <scheduler.h>
+#include <test/util/setup_common.h>
+#include <util/check.h>
+#include <validationinterface.h>
+
+BOOST_FIXTURE_TEST_SUITE(validationinterface_tests, TestingSetup)
+
+class TestInterface : public CValidationInterface
+{
+public:
+ TestInterface(std::function<void()> on_call = nullptr, std::function<void()> on_destroy = nullptr)
+ : m_on_call(std::move(on_call)), m_on_destroy(std::move(on_destroy))
+ {
+ }
+ virtual ~TestInterface()
+ {
+ if (m_on_destroy) m_on_destroy();
+ }
+ void BlockChecked(const CBlock& block, const BlockValidationState& state) override
+ {
+ if (m_on_call) m_on_call();
+ }
+ static void Call()
+ {
+ CBlock block;
+ BlockValidationState state;
+ GetMainSignals().BlockChecked(block, state);
+ }
+ std::function<void()> m_on_call;
+ std::function<void()> m_on_destroy;
+};
+
+// Regression test to ensure UnregisterAllValidationInterfaces calls don't
+// destroy a validation interface while it is being called. Bug:
+// https://github.com/bitcoin/bitcoin/pull/18551
+BOOST_AUTO_TEST_CASE(unregister_all_during_call)
+{
+ bool destroyed = false;
+ RegisterSharedValidationInterface(std::make_shared<TestInterface>(
+ [&] {
+ // First call should decrements reference count 2 -> 1
+ UnregisterAllValidationInterfaces();
+ BOOST_CHECK(!destroyed);
+ // Second call should not decrement reference count 1 -> 0
+ UnregisterAllValidationInterfaces();
+ BOOST_CHECK(!destroyed);
+ },
+ [&] { destroyed = true; }));
+ TestInterface::Call();
+ BOOST_CHECK(destroyed);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index 7b59d539a6..11c6bdad91 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -1,13 +1,13 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-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 <chain.h>
-#include <versionbits.h>
-#include <test/util/setup_common.h>
#include <chainparams.h>
-#include <validation.h>
#include <consensus/params.h>
+#include <test/util/setup_common.h>
+#include <validation.h>
+#include <versionbits.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 35bbdab00d..071aa1336b 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -339,7 +339,7 @@ public:
::Unserialize(s, Using<TxOutCompression>(vout[i]));
}
// coinbase height
- ::Unserialize(s, VARINT(nHeight, VarIntMode::NONNEGATIVE_SIGNED));
+ ::Unserialize(s, VARINT_MODE(nHeight, VarIntMode::NONNEGATIVE_SIGNED));
}
};
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 5768219f3a..c5c0208d8f 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -355,7 +355,6 @@ void CTxMemPool::AddTransactionsUpdated(unsigned int n)
void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate)
{
- NotifyEntryAdded(entry.GetSharedTx());
// Add to memory pool without checking anything.
// Used by AcceptToMemoryPool(), which DOES do
// all the appropriate checks.
@@ -406,16 +405,20 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
{
- CTransactionRef ptx = it->GetSharedTx();
- NotifyEntryRemoved(ptx, reason);
- if (reason != MemPoolRemovalReason::BLOCK && reason != MemPoolRemovalReason::CONFLICT) {
- GetMainSignals().TransactionRemovedFromMempool(ptx);
+ if (reason != MemPoolRemovalReason::BLOCK) {
+ // Notify clients that a transaction has been removed from the mempool
+ // for any reason except being included in a block. Clients interested
+ // in transactions included in blocks can subscribe to the BlockConnected
+ // notification.
+ GetMainSignals().TransactionRemovedFromMempool(it->GetSharedTx());
}
const uint256 hash = it->GetTx().GetHash();
for (const CTxIn& txin : it->GetTx().vin)
mapNextTx.erase(txin.prevout);
+ RemoveUnbroadcastTx(hash, true /* add logging because unchecked */ );
+
if (vTxHashes.size() > 1) {
vTxHashes[it->vTxHashesIdx] = std::move(vTxHashes.back());
vTxHashes[it->vTxHashesIdx].second->vTxHashesIdx = it->vTxHashesIdx;
@@ -918,6 +921,15 @@ size_t CTxMemPool::DynamicMemoryUsage() const {
return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 12 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + memusage::DynamicUsage(vTxHashes) + cachedInnerUsage;
}
+void CTxMemPool::RemoveUnbroadcastTx(const uint256& txid, const bool unchecked) {
+ LOCK(cs);
+
+ if (m_unbroadcast_txids.erase(txid))
+ {
+ LogPrint(BCLog::MEMPOOL, "Removed %i from set of unbroadcast txns%s\n", txid.GetHex(), (unchecked ? " before confirmation that txn was sent out" : ""));
+ }
+}
+
void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) {
AssertLockHeld(cs);
UpdateForRemoveFromMempool(stage, updateDescendants);
diff --git a/src/txmempool.h b/src/txmempool.h
index de11d626b4..4bee78b8d6 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -27,7 +27,6 @@
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
-#include <boost/signals2/signal.hpp>
class CBlockIndex;
extern RecursiveMutex cs_main;
@@ -550,6 +549,9 @@ private:
std::vector<indexed_transaction_set::const_iterator> GetSortedDepthAndScore() const EXCLUSIVE_LOCKS_REQUIRED(cs);
+ /** track locally submitted transactions to periodically retry initial broadcast */
+ std::set<uint256> m_unbroadcast_txids GUARDED_BY(cs);
+
public:
indirectmap<COutPoint, const CTransaction*> mapNextTx GUARDED_BY(cs);
std::map<uint256, CAmount> mapDeltas;
@@ -699,8 +701,20 @@ public:
size_t DynamicMemoryUsage() const;
- boost::signals2::signal<void (CTransactionRef)> NotifyEntryAdded;
- boost::signals2::signal<void (CTransactionRef, MemPoolRemovalReason)> NotifyEntryRemoved;
+ /** Adds a transaction to the unbroadcast set */
+ void AddUnbroadcastTx(const uint256& txid) {
+ LOCK(cs);
+ m_unbroadcast_txids.insert(txid);
+ }
+
+ /** Removes a transaction from the unbroadcast set */
+ void RemoveUnbroadcastTx(const uint256& txid, const bool unchecked = false);
+
+ /** Returns transactions in unbroadcast set */
+ const std::set<uint256> GetUnbroadcastTxs() const {
+ LOCK(cs);
+ return m_unbroadcast_txids;
+ }
private:
/** UpdateForDescendants is used by UpdateTransactionsFromBlock to update
@@ -753,7 +767,7 @@ public:
* determine if that transaction has not yet been visited during the current
* traversal's epoch.
* Algorithms using std::set can be replaced on a one by one basis.
- * Both techniques are not fundamentally incomaptible across the codebase.
+ * Both techniques are not fundamentally incompatible across the codebase.
* Generally speaking, however, the remaining use of std::set for mempool
* traversal should be viewed as a TODO for replacement with an epoch based
* traversal, rather than a preference for std::set over epochs in that
diff --git a/src/undo.h b/src/undo.h
index 2009c721ab..a98f046735 100644
--- a/src/undo.h
+++ b/src/undo.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -13,58 +13,42 @@
#include <serialize.h>
#include <version.h>
-/** Undo information for a CTxIn
+/** Formatter for undo information for a CTxIn
*
* Contains the prevout's CTxOut being spent, and its metadata as well
* (coinbase or not, height). The serialization contains a dummy value of
* zero. This is compatible with older versions which expect to see
* the transaction version there.
*/
-class TxInUndoSerializer
+struct TxInUndoFormatter
{
- const Coin* txout;
-
-public:
template<typename Stream>
- void Serialize(Stream &s) const {
- ::Serialize(s, VARINT(txout->nHeight * 2 + (txout->fCoinBase ? 1u : 0u)));
- if (txout->nHeight > 0) {
+ void Ser(Stream &s, const Coin& txout) {
+ ::Serialize(s, VARINT(txout.nHeight * uint32_t{2} + txout.fCoinBase ));
+ if (txout.nHeight > 0) {
// Required to maintain compatibility with older undo format.
::Serialize(s, (unsigned char)0);
}
- ::Serialize(s, Using<TxOutCompression>(REF(txout->out)));
+ ::Serialize(s, Using<TxOutCompression>(txout.out));
}
- explicit TxInUndoSerializer(const Coin* coin) : txout(coin) {}
-};
-
-class TxInUndoDeserializer
-{
- Coin* txout;
-
-public:
template<typename Stream>
- void Unserialize(Stream &s) {
- unsigned int nCode = 0;
+ void Unser(Stream &s, Coin& txout) {
+ uint32_t nCode = 0;
::Unserialize(s, VARINT(nCode));
- txout->nHeight = nCode / 2;
- txout->fCoinBase = nCode & 1;
- if (txout->nHeight > 0) {
+ txout.nHeight = nCode >> 1;
+ txout.fCoinBase = nCode & 1;
+ if (txout.nHeight > 0) {
// Old versions stored the version number for the last spend of
// a transaction's outputs. Non-final spends were indicated with
// height = 0.
unsigned int nVersionDummy;
::Unserialize(s, VARINT(nVersionDummy));
}
- ::Unserialize(s, Using<TxOutCompression>(REF(txout->out)));
+ ::Unserialize(s, Using<TxOutCompression>(txout.out));
}
-
- explicit TxInUndoDeserializer(Coin* coin) : txout(coin) {}
};
-static const size_t MIN_TRANSACTION_INPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxIn(), PROTOCOL_VERSION);
-static const size_t MAX_INPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_INPUT_WEIGHT;
-
/** Undo information for a CTransaction */
class CTxUndo
{
@@ -72,29 +56,7 @@ public:
// undo information for all txins
std::vector<Coin> vprevout;
- template <typename Stream>
- void Serialize(Stream& s) const {
- // TODO: avoid reimplementing vector serializer
- uint64_t count = vprevout.size();
- ::Serialize(s, COMPACTSIZE(REF(count)));
- for (const auto& prevout : vprevout) {
- ::Serialize(s, TxInUndoSerializer(&prevout));
- }
- }
-
- template <typename Stream>
- void Unserialize(Stream& s) {
- // TODO: avoid reimplementing vector deserializer
- uint64_t count = 0;
- ::Unserialize(s, COMPACTSIZE(count));
- if (count > MAX_INPUTS_PER_BLOCK) {
- throw std::ios_base::failure("Too many input undo records");
- }
- vprevout.resize(count);
- for (auto& prevout : vprevout) {
- ::Unserialize(s, TxInUndoDeserializer(&prevout));
- }
- }
+ SERIALIZE_METHODS(CTxUndo, obj) { READWRITE(Using<VectorFormatter<TxInUndoFormatter>>(obj.vprevout)); }
};
/** Undo information for a CBlock */
@@ -103,12 +65,7 @@ class CBlockUndo
public:
std::vector<CTxUndo> vtxundo; // for all but the coinbase
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(vtxundo);
- }
+ SERIALIZE_METHODS(CBlockUndo, obj) { READWRITE(obj.vtxundo); }
};
#endif // BITCOIN_UNDO_H
diff --git a/src/univalue/Makefile.am b/src/univalue/Makefile.am
index e283fc890e..0f5ba59954 100644
--- a/src/univalue/Makefile.am
+++ b/src/univalue/Makefile.am
@@ -95,6 +95,7 @@ TEST_FILES = \
$(TEST_DATA_DIR)/fail41.json \
$(TEST_DATA_DIR)/fail42.json \
$(TEST_DATA_DIR)/fail44.json \
+ $(TEST_DATA_DIR)/fail45.json \
$(TEST_DATA_DIR)/fail3.json \
$(TEST_DATA_DIR)/fail4.json \
$(TEST_DATA_DIR)/fail5.json \
@@ -105,6 +106,7 @@ TEST_FILES = \
$(TEST_DATA_DIR)/pass1.json \
$(TEST_DATA_DIR)/pass2.json \
$(TEST_DATA_DIR)/pass3.json \
+ $(TEST_DATA_DIR)/pass4.json \
$(TEST_DATA_DIR)/round1.json \
$(TEST_DATA_DIR)/round2.json \
$(TEST_DATA_DIR)/round3.json \
diff --git a/src/univalue/lib/univalue_read.cpp b/src/univalue/lib/univalue_read.cpp
index 14834db24d..5c6a1acf75 100644
--- a/src/univalue/lib/univalue_read.cpp
+++ b/src/univalue/lib/univalue_read.cpp
@@ -8,6 +8,14 @@
#include "univalue.h"
#include "univalue_utffilter.h"
+/*
+ * According to stackexchange, the original json test suite wanted
+ * to limit depth to 22. Widely-deployed PHP bails at depth 512,
+ * so we will follow PHP's lead, which should be more than sufficient
+ * (further stackexchange comments indicate depth > 32 rarely occurs).
+ */
+static const size_t MAX_JSON_DEPTH = 512;
+
static bool json_isdigit(int ch)
{
return ((ch >= '0') && (ch <= '9'));
@@ -323,6 +331,9 @@ bool UniValue::read(const char *raw, size_t size)
stack.push_back(newTop);
}
+ if (stack.size() > MAX_JSON_DEPTH)
+ return false;
+
if (utyp == VOBJ)
setExpect(OBJ_NAME);
else
diff --git a/src/univalue/test/fail45.json b/src/univalue/test/fail45.json
new file mode 100644
index 0000000000..03a30d8800
--- /dev/null
+++ b/src/univalue/test/fail45.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
diff --git a/src/univalue/test/pass4.json b/src/univalue/test/pass4.json
new file mode 100644
index 0000000000..f5a680b31c
--- /dev/null
+++ b/src/univalue/test/pass4.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
diff --git a/src/univalue/test/unitester.cpp b/src/univalue/test/unitester.cpp
index 75c0dc225a..2308afbcdf 100644
--- a/src/univalue/test/unitester.cpp
+++ b/src/univalue/test/unitester.cpp
@@ -114,6 +114,7 @@ static const char *filenames[] = {
"fail41.json", // invalid unicode: unfinished UTF-8
"fail42.json", // valid json with garbage following a nul byte
"fail44.json", // unterminated string
+ "fail45.json", // nested beyond max depth
"fail3.json",
"fail4.json", // extra comma
"fail5.json",
@@ -124,6 +125,7 @@ static const char *filenames[] = {
"pass1.json",
"pass2.json",
"pass3.json",
+ "pass4.json",
"round1.json", // round-trip test
"round2.json", // unicode
"round3.json", // bare string
diff --git a/src/util/asmap.cpp b/src/util/asmap.cpp
index ac230e9ee5..5354cdb962 100644
--- a/src/util/asmap.cpp
+++ b/src/util/asmap.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -8,13 +8,14 @@
namespace {
-uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, uint8_t minval, const std::vector<uint8_t> &bit_sizes)
+uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos, uint8_t minval, const std::vector<uint8_t> &bit_sizes)
{
uint32_t val = minval;
bool bit;
for (std::vector<uint8_t>::const_iterator bit_sizes_it = bit_sizes.begin();
bit_sizes_it != bit_sizes.end(); ++bit_sizes_it) {
if (bit_sizes_it + 1 != bit_sizes.end()) {
+ if (bitpos == endpos) break;
bit = *bitpos;
bitpos++;
} else {
@@ -24,6 +25,7 @@ uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, uint8_t minval, c
val += (1 << *bit_sizes_it);
} else {
for (int b = 0; b < *bit_sizes_it; b++) {
+ if (bitpos == endpos) break;
bit = *bitpos;
bitpos++;
val += bit << (*bit_sizes_it - 1 - b);
@@ -35,29 +37,29 @@ uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, uint8_t minval, c
}
const std::vector<uint8_t> TYPE_BIT_SIZES{0, 0, 1};
-uint32_t DecodeType(std::vector<bool>::const_iterator& bitpos)
+uint32_t DecodeType(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
- return DecodeBits(bitpos, 0, TYPE_BIT_SIZES);
+ return DecodeBits(bitpos, endpos, 0, TYPE_BIT_SIZES);
}
const std::vector<uint8_t> ASN_BIT_SIZES{15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
-uint32_t DecodeASN(std::vector<bool>::const_iterator& bitpos)
+uint32_t DecodeASN(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
- return DecodeBits(bitpos, 1, ASN_BIT_SIZES);
+ return DecodeBits(bitpos, endpos, 1, ASN_BIT_SIZES);
}
const std::vector<uint8_t> MATCH_BIT_SIZES{1, 2, 3, 4, 5, 6, 7, 8};
-uint32_t DecodeMatch(std::vector<bool>::const_iterator& bitpos)
+uint32_t DecodeMatch(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
- return DecodeBits(bitpos, 2, MATCH_BIT_SIZES);
+ return DecodeBits(bitpos, endpos, 2, MATCH_BIT_SIZES);
}
const std::vector<uint8_t> JUMP_BIT_SIZES{5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
-uint32_t DecodeJump(std::vector<bool>::const_iterator& bitpos)
+uint32_t DecodeJump(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
- return DecodeBits(bitpos, 17, JUMP_BIT_SIZES);
+ return DecodeBits(bitpos, endpos, 17, JUMP_BIT_SIZES);
}
}
@@ -65,33 +67,37 @@ uint32_t DecodeJump(std::vector<bool>::const_iterator& bitpos)
uint32_t Interpret(const std::vector<bool> &asmap, const std::vector<bool> &ip)
{
std::vector<bool>::const_iterator pos = asmap.begin();
+ const std::vector<bool>::const_iterator endpos = asmap.end();
uint8_t bits = ip.size();
- uint8_t default_asn = 0;
+ uint32_t default_asn = 0;
uint32_t opcode, jump, match, matchlen;
- while (1) {
- assert(pos != asmap.end());
- opcode = DecodeType(pos);
+ while (pos != endpos) {
+ opcode = DecodeType(pos, endpos);
if (opcode == 0) {
- return DecodeASN(pos);
+ return DecodeASN(pos, endpos);
} else if (opcode == 1) {
- jump = DecodeJump(pos);
+ jump = DecodeJump(pos, endpos);
+ if (bits == 0) break;
if (ip[ip.size() - bits]) {
+ if (jump >= endpos - pos) break;
pos += jump;
}
bits--;
} else if (opcode == 2) {
- match = DecodeMatch(pos);
+ match = DecodeMatch(pos, endpos);
matchlen = CountBits(match) - 1;
for (uint32_t bit = 0; bit < matchlen; bit++) {
+ if (bits == 0) break;
if ((ip[ip.size() - bits]) != ((match >> (matchlen - 1 - bit)) & 1)) {
return default_asn;
}
bits--;
}
} else if (opcode == 3) {
- default_asn = DecodeASN(pos);
+ default_asn = DecodeASN(pos, endpos);
} else {
- assert(0);
+ break;
}
}
+ return 0; // 0 is not a valid ASN
}
diff --git a/src/util/bip32.cpp b/src/util/bip32.cpp
index 6f176dd5ec..4c7e948368 100644
--- a/src/util/bip32.cpp
+++ b/src/util/bip32.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
diff --git a/src/util/bip32.h b/src/util/bip32.h
index 7e58b79f38..347e83db9e 100644
--- a/src/util/bip32.h
+++ b/src/util/bip32.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
diff --git a/src/util/golombrice.h b/src/util/golombrice.h
new file mode 100644
index 0000000000..425e7f6681
--- /dev/null
+++ b/src/util/golombrice.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2018-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.
+
+#ifndef BITCOIN_UTIL_GOLOMBRICE_H
+#define BITCOIN_UTIL_GOLOMBRICE_H
+
+#include <streams.h>
+
+#include <cstdint>
+
+template <typename OStream>
+void GolombRiceEncode(BitStreamWriter<OStream>& bitwriter, uint8_t P, uint64_t x)
+{
+ // Write quotient as unary-encoded: q 1's followed by one 0.
+ uint64_t q = x >> P;
+ while (q > 0) {
+ int nbits = q <= 64 ? static_cast<int>(q) : 64;
+ bitwriter.Write(~0ULL, nbits);
+ q -= nbits;
+ }
+ bitwriter.Write(0, 1);
+
+ // Write the remainder in P bits. Since the remainder is just the bottom
+ // P bits of x, there is no need to mask first.
+ bitwriter.Write(x, P);
+}
+
+template <typename IStream>
+uint64_t GolombRiceDecode(BitStreamReader<IStream>& bitreader, uint8_t P)
+{
+ // Read unary-encoded quotient: q 1's followed by one 0.
+ uint64_t q = 0;
+ while (bitreader.Read(1) == 1) {
+ ++q;
+ }
+
+ uint64_t r = bitreader.Read(P);
+
+ return (q << P) + r;
+}
+
+#endif // BITCOIN_UTIL_GOLOMBRICE_H
diff --git a/src/util/message.cpp b/src/util/message.cpp
new file mode 100644
index 0000000000..1e7128d225
--- /dev/null
+++ b/src/util/message.cpp
@@ -0,0 +1,92 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-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 <hash.h> // For CHashWriter
+#include <key.h> // For CKey
+#include <key_io.h> // For DecodeDestination()
+#include <pubkey.h> // For CPubKey
+#include <script/standard.h> // For CTxDestination, IsValidDestination(), PKHash
+#include <serialize.h> // For SER_GETHASH
+#include <util/message.h>
+#include <util/strencodings.h> // For DecodeBase64()
+
+#include <string>
+#include <vector>
+
+/**
+ * Text used to signify that a signed message follows and to prevent
+ * inadvertently signing a transaction.
+ */
+const std::string MESSAGE_MAGIC = "Bitcoin Signed Message:\n";
+
+MessageVerificationResult MessageVerify(
+ const std::string& address,
+ const std::string& signature,
+ const std::string& message)
+{
+ CTxDestination destination = DecodeDestination(address);
+ if (!IsValidDestination(destination)) {
+ return MessageVerificationResult::ERR_INVALID_ADDRESS;
+ }
+
+ if (boost::get<PKHash>(&destination) == nullptr) {
+ return MessageVerificationResult::ERR_ADDRESS_NO_KEY;
+ }
+
+ bool invalid = false;
+ std::vector<unsigned char> signature_bytes = DecodeBase64(signature.c_str(), &invalid);
+ if (invalid) {
+ return MessageVerificationResult::ERR_MALFORMED_SIGNATURE;
+ }
+
+ CPubKey pubkey;
+ if (!pubkey.RecoverCompact(MessageHash(message), signature_bytes)) {
+ return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED;
+ }
+
+ if (!(CTxDestination(PKHash(pubkey)) == destination)) {
+ return MessageVerificationResult::ERR_NOT_SIGNED;
+ }
+
+ return MessageVerificationResult::OK;
+}
+
+bool MessageSign(
+ const CKey& privkey,
+ const std::string& message,
+ std::string& signature)
+{
+ std::vector<unsigned char> signature_bytes;
+
+ if (!privkey.SignCompact(MessageHash(message), signature_bytes)) {
+ return false;
+ }
+
+ signature = EncodeBase64(signature_bytes.data(), signature_bytes.size());
+
+ return true;
+}
+
+uint256 MessageHash(const std::string& message)
+{
+ CHashWriter hasher(SER_GETHASH, 0);
+ hasher << MESSAGE_MAGIC << message;
+
+ return hasher.GetHash();
+}
+
+std::string SigningResultString(const SigningResult res)
+{
+ switch (res) {
+ case SigningResult::OK:
+ return "No error";
+ case SigningResult::PRIVATE_KEY_NOT_AVAILABLE:
+ return "Private key not available";
+ case SigningResult::SIGNING_FAILED:
+ return "Sign failed";
+ // no default case, so the compiler can warn about missing cases
+ }
+ assert(false);
+}
diff --git a/src/util/message.h b/src/util/message.h
new file mode 100644
index 0000000000..b31c5f5761
--- /dev/null
+++ b/src/util/message.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-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_UTIL_MESSAGE_H
+#define BITCOIN_UTIL_MESSAGE_H
+
+#include <key.h> // For CKey
+#include <uint256.h>
+
+#include <string>
+
+extern const std::string MESSAGE_MAGIC;
+
+/** The result of a signed message verification.
+ * Message verification takes as an input:
+ * - address (with whose private key the message is supposed to have been signed)
+ * - signature
+ * - message
+ */
+enum class MessageVerificationResult {
+ //! The provided address is invalid.
+ ERR_INVALID_ADDRESS,
+
+ //! The provided address is valid but does not refer to a public key.
+ ERR_ADDRESS_NO_KEY,
+
+ //! The provided signature couldn't be parsed (maybe invalid base64).
+ ERR_MALFORMED_SIGNATURE,
+
+ //! A public key could not be recovered from the provided signature and message.
+ ERR_PUBKEY_NOT_RECOVERED,
+
+ //! The message was not signed with the private key of the provided address.
+ ERR_NOT_SIGNED,
+
+ //! The message verification was successful.
+ OK
+};
+
+enum class SigningResult {
+ OK, //!< No error
+ PRIVATE_KEY_NOT_AVAILABLE,
+ SIGNING_FAILED,
+};
+
+/** Verify a signed message.
+ * @param[in] address Signer's bitcoin address, it must refer to a public key.
+ * @param[in] signature The signature in base64 format.
+ * @param[in] message The message that was signed.
+ * @return result code */
+MessageVerificationResult MessageVerify(
+ const std::string& address,
+ const std::string& signature,
+ const std::string& message);
+
+/** Sign a message.
+ * @param[in] privkey Private key to sign with.
+ * @param[in] message The message to sign.
+ * @param[out] signature Signature, base64 encoded, only set if true is returned.
+ * @return true if signing was successful. */
+bool MessageSign(
+ const CKey& privkey,
+ const std::string& message,
+ std::string& signature);
+
+/**
+ * Hashes a message for signing and verification in a manner that prevents
+ * inadvertently signing a transaction.
+ */
+uint256 MessageHash(const std::string& message);
+
+std::string SigningResultString(const SigningResult res);
+
+#endif // BITCOIN_UTIL_MESSAGE_H
diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp
index 2797f450ca..1bc8d02eab 100644
--- a/src/util/moneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -31,21 +31,19 @@ std::string FormatMoney(const CAmount& n)
}
-bool ParseMoney(const std::string& str, CAmount& nRet)
+bool ParseMoney(const std::string& money_string, CAmount& nRet)
{
- if (!ValidAsCString(str)) {
+ if (!ValidAsCString(money_string)) {
+ return false;
+ }
+ const std::string str = TrimString(money_string);
+ if (str.empty()) {
return false;
}
- return ParseMoney(str.c_str(), nRet);
-}
-bool ParseMoney(const char* pszIn, CAmount& nRet)
-{
std::string strWhole;
int64_t nUnits = 0;
- const char* p = pszIn;
- while (IsSpace(*p))
- p++;
+ const char* p = str.c_str();
for (; *p; p++)
{
if (*p == '.')
@@ -60,14 +58,14 @@ bool ParseMoney(const char* pszIn, CAmount& nRet)
break;
}
if (IsSpace(*p))
- break;
+ return false;
if (!IsDigit(*p))
return false;
strWhole.insert(strWhole.end(), *p);
}
- for (; *p; p++)
- if (!IsSpace(*p))
- return false;
+ if (*p) {
+ return false;
+ }
if (strWhole.size() > 10) // guard against 63 bit overflow
return false;
if (nUnits < 0 || nUnits > COIN)
diff --git a/src/util/moneystr.h b/src/util/moneystr.h
index 027c7e2e53..9d2b6da0fc 100644
--- a/src/util/moneystr.h
+++ b/src/util/moneystr.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -18,7 +18,7 @@
* JSON but use AmountFromValue and ValueFromAmount for that.
*/
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 char* pszIn, CAmount& nRet);
#endif // BITCOIN_UTIL_MONEYSTR_H
diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp
index eec1a52e95..3a903b6897 100644
--- a/src/util/strencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -407,16 +407,6 @@ std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
return out.str();
}
-std::string i64tostr(int64_t n)
-{
- return strprintf("%d", n);
-}
-
-std::string itostr(int n)
-{
- return strprintf("%d", n);
-}
-
int64_t atoi64(const char* psz)
{
#ifdef _MSC_VER
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index ccc4edac12..bd988f1410 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -54,9 +54,7 @@ std::string DecodeBase32(const std::string& str, bool* pf_invalid = nullptr);
std::string EncodeBase32(const unsigned char* pch, size_t len);
std::string EncodeBase32(const std::string& str);
-void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
-std::string i64tostr(int64_t n);
-std::string itostr(int n);
+void SplitHostPort(std::string in, int& portOut, std::string& hostOut);
int64_t atoi64(const char* psz);
int64_t atoi64(const std::string& str);
int atoi(const std::string& str);
diff --git a/src/util/string.h b/src/util/string.h
index 3db8fc8b98..b8e2a06235 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -8,6 +8,8 @@
#include <attributes.h>
#include <cstring>
+#include <locale>
+#include <sstream>
#include <string>
#include <vector>
@@ -52,4 +54,16 @@ NODISCARD inline bool ValidAsCString(const std::string& str) noexcept
return str.size() == strlen(str.c_str());
}
+/**
+ * Locale-independent version of std::to_string
+ */
+template <typename T>
+std::string ToString(const T& t)
+{
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+ oss << t;
+ return oss.str();
+}
+
#endif // BITCOIN_UTIL_STRENCODINGS_H
diff --git a/src/util/system.cpp b/src/util/system.cpp
index ff3967c577..2013b416db 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -17,7 +17,7 @@
#endif
#ifndef WIN32
-// for posix_fallocate
+// for posix_fallocate, in configure.ac we check if it is present after this
#ifdef __linux__
#ifdef _POSIX_C_SOURCE
@@ -63,6 +63,7 @@
#include <malloc.h>
#endif
+#include <boost/algorithm/string/replace.hpp>
#include <thread>
#include <typeinfo>
#include <univalue.h>
@@ -140,6 +141,12 @@ bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes)
return free_bytes_available >= min_disk_space + additional_bytes;
}
+std::streampos GetFileSize(const char* path, std::streamsize max) {
+ std::ifstream file(path, std::ios::binary);
+ file.ignore(max);
+ return file.gcount();
+}
+
/**
* Interpret a string argument as a boolean.
*
@@ -225,10 +232,11 @@ static bool CheckValid(const std::string& key, const util::SettingsValue& val, u
return true;
}
-ArgsManager::ArgsManager()
-{
- // nothing to do
-}
+// Define default constructor and destructor that are not inline, so code instantiating this class doesn't need to
+// #include class definitions for all members.
+// For example, m_settings has an internal dependency on univalue.
+ArgsManager::ArgsManager() {}
+ArgsManager::~ArgsManager() {}
const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
{
@@ -312,21 +320,18 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
std::string section;
util::SettingsValue value = InterpretOption(section, key, val);
Optional<unsigned int> flags = GetArgFlags('-' + key);
- if (flags) {
- if (!CheckValid(key, value, *flags, error)) {
- return false;
- }
- // Weird behavior preserved for backwards compatibility: command
- // line options with section prefixes are allowed but ignored. It
- // would be better if these options triggered the Invalid parameter
- // error below.
- if (section.empty()) {
- m_settings.command_line_options[key].push_back(value);
- }
- } else {
- error = strprintf("Invalid parameter -%s", key);
+
+ // Unknown command line options and command line options with dot
+ // characters (which are returned from InterpretOption with nonempty
+ // section strings) are not valid.
+ if (!flags || !section.empty()) {
+ error = strprintf("Invalid parameter %s", argv[i]);
return false;
}
+
+ if (!CheckValid(key, value, *flags, error)) return false;
+
+ m_settings.command_line_options[key].push_back(value);
}
// we do not allow -includeconf from command line
@@ -1014,7 +1019,7 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
}
ftruncate(fileno(file), static_cast<off_t>(offset) + length);
#else
- #if defined(__linux__)
+ #if defined(HAVE_POSIX_FALLOCATE)
// Version using posix_fallocate
off_t nEndPos = (off_t)offset + length;
if (0 == posix_fallocate(fileno(file), 0, nEndPos)) return;
@@ -1050,6 +1055,15 @@ fs::path GetSpecialFolderPath(int nFolder, bool fCreate)
}
#endif
+#ifndef WIN32
+std::string ShellEscape(const std::string& arg)
+{
+ std::string escaped = arg;
+ boost::replace_all(escaped, "'", "'\"'\"'");
+ return "'" + escaped + "'";
+}
+#endif
+
#if HAVE_SYSTEM
void runCommand(const std::string& strCommand)
{
diff --git a/src/util/system.h b/src/util/system.h
index bb69181de9..a5eea5dfab 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -63,6 +63,14 @@ void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name
bool DirIsWritable(const fs::path& directory);
bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes = 0);
+/** Get the size of a file by scanning it.
+ *
+ * @param[in] path The file path
+ * @param[in] max Stop seeking beyond this limit
+ * @return The file size or max
+ */
+std::streampos GetFileSize(const char* path, std::streamsize max = std::numeric_limits<std::streamsize>::max());
+
/** Release all directory locks. This is used for unit testing only, at runtime
* the global destructor will take care of the locks.
*/
@@ -81,6 +89,9 @@ fs::path GetConfigFile(const std::string& confPath);
#ifdef WIN32
fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
+#ifndef WIN32
+std::string ShellEscape(const std::string& arg);
+#endif
#if HAVE_SYSTEM
void runCommand(const std::string& strCommand);
#endif
@@ -189,6 +200,7 @@ protected:
public:
ArgsManager();
+ ~ArgsManager();
/**
* Select the network in use
diff --git a/src/util/time.cpp b/src/util/time.cpp
index 2afff2626b..e96972fe12 100644
--- a/src/util/time.cpp
+++ b/src/util/time.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -11,10 +11,13 @@
#include <atomic>
#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/thread.hpp>
#include <ctime>
+#include <thread>
+
#include <tinyformat.h>
+void UninterruptibleSleep(const std::chrono::microseconds& n) { std::this_thread::sleep_for(n); }
+
static std::atomic<int64_t> nMockTime(0); //!< For unit testing
int64_t GetTime()
@@ -72,43 +75,29 @@ int64_t GetSystemTimeInSeconds()
return GetTimeMicros()/1000000;
}
-void MilliSleep(int64_t n)
-{
-
-/**
- * Boost's sleep_for was uninterruptible when backed by nanosleep from 1.50
- * until fixed in 1.52. Use the deprecated sleep method for the broken case.
- * See: https://svn.boost.org/trac/boost/ticket/7238
- */
-#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
- boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
-#elif defined(HAVE_WORKING_BOOST_SLEEP)
- boost::this_thread::sleep(boost::posix_time::milliseconds(n));
-#else
-//should never get here
-#error missing boost sleep implementation
-#endif
-}
-
std::string FormatISO8601DateTime(int64_t nTime) {
struct tm ts;
time_t time_val = nTime;
-#ifdef _MSC_VER
- gmtime_s(&ts, &time_val);
+#ifdef HAVE_GMTIME_R
+ if (gmtime_r(&time_val, &ts) == nullptr) {
#else
- gmtime_r(&time_val, &ts);
+ if (gmtime_s(&ts, &time_val) != 0) {
#endif
+ return {};
+ }
return strprintf("%04i-%02i-%02iT%02i:%02i:%02iZ", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec);
}
std::string FormatISO8601Date(int64_t nTime) {
struct tm ts;
time_t time_val = nTime;
-#ifdef _MSC_VER
- gmtime_s(&ts, &time_val);
+#ifdef HAVE_GMTIME_R
+ if (gmtime_r(&time_val, &ts) == nullptr) {
#else
- gmtime_r(&time_val, &ts);
+ if (gmtime_s(&ts, &time_val) != 0) {
#endif
+ return {};
+ }
return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday);
}
@@ -124,4 +113,4 @@ int64_t ParseISO8601DateTime(const std::string& str)
if (ptime.is_not_a_date_time() || epoch > ptime)
return 0;
return (ptime - epoch).total_seconds();
-} \ No newline at end of file
+}
diff --git a/src/util/time.h b/src/util/time.h
index af4390aa1c..b00c25f67c 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -10,6 +10,8 @@
#include <string>
#include <chrono>
+void UninterruptibleSleep(const std::chrono::microseconds& n);
+
/**
* Helper to count the seconds of a duration.
*
@@ -36,8 +38,6 @@ void SetMockTime(int64_t nMockTimeIn);
/** For testing */
int64_t GetMockTime();
-void MilliSleep(int64_t n);
-
/** Return system time (or mocked time, if set) */
template <typename T>
T GetTime();
diff --git a/src/util/url.h b/src/util/url.h
index e9ea2ab765..5a7b11fa04 100644
--- a/src/util/url.h
+++ b/src/util/url.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-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.
@@ -7,6 +7,8 @@
#include <string>
-std::string urlDecode(const std::string &urlEncoded);
+using UrlDecodeFn = std::string(const std::string& url_encoded);
+UrlDecodeFn urlDecode;
+extern UrlDecodeFn* const URL_DECODE;
#endif // BITCOIN_UTIL_URL_H
diff --git a/src/util/validation.cpp b/src/util/validation.cpp
deleted file mode 100644
index 89bc6665a4..0000000000
--- a/src/util/validation.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-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 <util/validation.h>
-
-#include <consensus/validation.h>
-#include <tinyformat.h>
-
-std::string FormatStateMessage(const ValidationState &state)
-{
- if (state.IsValid()) {
- return "Valid";
- }
-
- const std::string debug_message = state.GetDebugMessage();
- if (!debug_message.empty()) {
- return strprintf("%s, %s", state.GetRejectReason(), debug_message);
- }
-
- return state.GetRejectReason();
-}
-
-const std::string strMessageMagic = "Bitcoin Signed Message:\n";
diff --git a/src/util/validation.h b/src/util/validation.h
deleted file mode 100644
index da2cf9f102..0000000000
--- a/src/util/validation.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-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.
-
-#ifndef BITCOIN_UTIL_VALIDATION_H
-#define BITCOIN_UTIL_VALIDATION_H
-
-#include <string>
-
-class ValidationState;
-
-/** Convert ValidationState to a human-readable message for logging */
-std::string FormatStateMessage(const ValidationState &state);
-
-extern const std::string strMessageMagic;
-
-#endif // BITCOIN_UTIL_VALIDATION_H
diff --git a/src/validation.cpp b/src/validation.cpp
index bab04b8e34..259397051c 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -20,6 +20,7 @@
#include <index/txindex.h>
#include <logging.h>
#include <logging/timer.h>
+#include <optional.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/settings.h>
@@ -43,7 +44,6 @@
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
-#include <util/validation.h>
#include <validationinterface.h>
#include <warnings.h>
@@ -59,6 +59,25 @@
#define MICRO 0.000001
#define MILLI 0.001
+/**
+ * An extra transaction can be added to a package, as long as it only has one
+ * ancestor and is no larger than this. Not really any reason to make this
+ * configurable as it doesn't materially change DoS parameters.
+ */
+static const unsigned int EXTRA_DESCENDANT_TX_SIZE_LIMIT = 10000;
+/** Maximum kilobytes for transactions to store for processing during reorg */
+static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE = 20000;
+/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
+static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
+/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
+static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
+/** Time to wait (in seconds) between writing blocks/block index to disk. */
+static const unsigned int DATABASE_WRITE_INTERVAL = 60 * 60;
+/** Time to wait (in seconds) between flushing chainstate to disk. */
+static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60;
+/** Maximum age of our tip in seconds for us to be considered current for fee estimation */
+static const int64_t MAX_FEE_ESTIMATION_TIP_AGE = 3 * 60 * 60;
+
bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIndex *pb) const {
// First sort by most total work, ...
if (pa->nChainWork > pb->nChainWork) return false;
@@ -77,20 +96,19 @@ bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIn
return false;
}
-namespace {
-BlockManager g_blockman;
-} // anon namespace
-
-std::unique_ptr<CChainState> g_chainstate;
+ChainstateManager g_chainman;
-CChainState& ChainstateActive() {
- assert(g_chainstate);
- return *g_chainstate;
+CChainState& ChainstateActive()
+{
+ LOCK(::cs_main);
+ assert(g_chainman.m_active_chainstate);
+ return *g_chainman.m_active_chainstate;
}
-CChain& ChainActive() {
- assert(g_chainstate);
- return g_chainstate->m_chain;
+CChain& ChainActive()
+{
+ LOCK(::cs_main);
+ return ::ChainstateActive().m_chain;
}
/**
@@ -152,8 +170,8 @@ namespace {
CBlockIndex* LookupBlockIndex(const uint256& hash)
{
AssertLockHeld(cs_main);
- BlockMap::const_iterator it = g_blockman.m_block_index.find(hash);
- return it == g_blockman.m_block_index.end() ? nullptr : it->second;
+ BlockMap::const_iterator it = g_chainman.BlockIndex().find(hash);
+ return it == g_chainman.BlockIndex().end() ? nullptr : it->second;
}
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
@@ -662,7 +680,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
CAmount nFees = 0;
if (!Consensus::CheckTxInputs(tx, state, m_view, GetSpendHeight(m_view), nFees)) {
- return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
+ return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), state.ToString());
}
// Check for non-standard pay-to-script-hash in inputs
@@ -951,7 +969,7 @@ bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, Workspace& ws, Precomp
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(::ChainActive().Tip(), chainparams.GetConsensus());
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata)) {
return error("%s: BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s",
- __func__, hash.ToString(), FormatStateMessage(state));
+ __func__, hash.ToString(), state.ToString());
}
return true;
@@ -975,7 +993,7 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)
// Remove conflicting transactions from the mempool
for (CTxMemPool::txiter it : allConflicting)
{
- LogPrint(BCLog::MEMPOOL, "replacing tx %s with %s for %s BTC additional fees, %d delta bytes\n",
+ LogPrint(BCLog::MEMPOOL, "replacing tx %s with %s for %s additional fees, %d delta bytes\n",
it->GetTx().GetHash().ToString(),
hash.ToString(),
FormatMoney(nModifiedFees - nConflictingFees),
@@ -1017,7 +1035,7 @@ bool MemPoolAccept::AcceptSingleTransaction(const CTransactionRef& ptx, ATMPArgs
// scripts (ie, other policy checks pass). We perform the inexpensive
// checks first and avoid hashing and signature verification unless those
// checks pass, to mitigate CPU exhaustion denial-of-service attacks.
- PrecomputedTransactionData txdata(*ptx);
+ PrecomputedTransactionData txdata;
if (!PolicyScriptChecks(args, workspace, txdata)) return false;
@@ -1243,10 +1261,9 @@ void CoinsViews::InitCache()
m_cacheview = MakeUnique<CCoinsViewCache>(&m_catcherview);
}
-// NOTE: for now m_blockman is set to a global, but this will be changed
-// in a future commit.
-CChainState::CChainState() : m_blockman(g_blockman) {}
-
+CChainState::CChainState(BlockManager& blockman, uint256 from_snapshot_blockhash)
+ : m_blockman(blockman),
+ m_from_snapshot_blockhash(from_snapshot_blockhash) {}
void CChainState::InitCoinsDB(
size_t cache_size_bytes,
@@ -1254,6 +1271,10 @@ void CChainState::InitCoinsDB(
bool should_wipe,
std::string leveldb_name)
{
+ if (!m_from_snapshot_blockhash.IsNull()) {
+ leveldb_name += "_" + m_from_snapshot_blockhash.ToString();
+ }
+
m_coins_views = MakeUnique<CoinsViews>(
leveldb_name, cache_size_bytes, in_memory, should_wipe);
}
@@ -1295,7 +1316,8 @@ static CBlockIndex *pindexBestForkTip = nullptr, *pindexBestForkBase = nullptr;
BlockMap& BlockIndex()
{
- return g_blockman.m_block_index;
+ LOCK(::cs_main);
+ return g_chainman.m_blockman.m_block_index;
}
static void AlertNotify(const std::string& strMessage)
@@ -1513,6 +1535,10 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const C
return true;
}
+ if (!txdata.m_ready) {
+ txdata.Init(tx);
+ }
+
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const COutPoint &prevout = tx.vin[i].prevout;
const Coin& coin = inputs.AccessCoin(prevout);
@@ -1669,10 +1695,11 @@ int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out)
return DISCONNECT_FAILED; // adding output for transaction without known metadata
}
}
- // The potential_overwrite parameter to AddCoin is only allowed to be false if we know for
- // sure that the coin did not already exist in the cache. As we have queried for that above
- // using HaveCoin, we don't need to guess. When fClean is false, a coin already existed and
- // it is an overwrite.
+ // If the coin already exists as an unspent coin in the cache, then the
+ // possible_overwrite parameter to AddCoin must be set to true. We have
+ // already checked whether an unspent coin exists above using HaveCoin, so
+ // we don't need to guess. When fClean is false, an unspent coin already
+ // existed and it is an overwrite.
view.AddCoin(out, std::move(undo), !fClean);
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
@@ -1921,13 +1948,15 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
// problems.
return AbortNode(state, "Corrupt block found indicating potential hardware failure; shutting down");
}
- return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
+ return error("%s: Consensus::CheckBlock: %s", __func__, state.ToString());
}
// verify that the view's current state corresponds to the previous block
uint256 hashPrevBlock = pindex->pprev == nullptr ? uint256() : pindex->pprev->GetBlockHash();
assert(hashPrevBlock == view.GetBestBlock());
+ nBlocksTotal++;
+
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) {
@@ -1936,8 +1965,6 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
return true;
}
- nBlocksTotal++;
-
bool fScriptChecks = true;
if (!hashAssumeValid.IsNull()) {
// We've been configured with the hash of a block which has been externally verified to have a valid history.
@@ -2076,15 +2103,19 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
CBlockUndo blockundo;
+ // Precomputed transaction data pointers must not be invalidated
+ // until after `control` has run the script checks (potentially
+ // in multiple threads). Preallocate the vector size so a new allocation
+ // doesn't invalidate pointers into the vector, and keep txsdata in scope
+ // for as long as `control`.
CCheckQueueControl<CScriptCheck> control(fScriptChecks && g_parallel_script_checks ? &scriptcheckqueue : nullptr);
+ std::vector<PrecomputedTransactionData> txsdata(block.vtx.size());
std::vector<int> prevheights;
CAmount nFees = 0;
int nInputs = 0;
int64_t nSigOpsCost = 0;
blockundo.vtxundo.reserve(block.vtx.size() - 1);
- std::vector<PrecomputedTransactionData> txdata;
- txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
const CTransaction &tx = *(block.vtx[i]);
@@ -2099,7 +2130,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
// Any transaction validation failure in ConnectBlock is a block consensus failure
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS,
tx_state.GetRejectReason(), tx_state.GetDebugMessage());
- return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
+ return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), state.ToString());
}
nFees += txfee;
if (!MoneyRange(nFees)) {
@@ -2131,18 +2162,17 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-blk-sigops");
}
- txdata.emplace_back(tx);
if (!tx.IsCoinBase())
{
std::vector<CScriptCheck> vChecks;
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
TxValidationState tx_state;
- if (fScriptChecks && !CheckInputScripts(tx, tx_state, view, flags, fCacheResults, fCacheResults, txdata[i], g_parallel_script_checks ? &vChecks : nullptr)) {
+ if (fScriptChecks && !CheckInputScripts(tx, tx_state, view, flags, fCacheResults, fCacheResults, txsdata[i], g_parallel_script_checks ? &vChecks : nullptr)) {
// Any transaction validation failure in ConnectBlock is a block consensus failure
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS,
tx_state.GetRejectReason(), tx_state.GetDebugMessage());
return error("ConnectBlock(): CheckInputScripts on %s failed with %s",
- tx.GetHash().ToString(), FormatStateMessage(state));
+ tx.GetHash().ToString(), state.ToString());
}
control.Add(vChecks);
}
@@ -2359,7 +2389,7 @@ void CChainState::ForceFlushStateToDisk() {
BlockValidationState state;
const CChainParams& chainparams = Params();
if (!this->FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS)) {
- LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state));
+ LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString());
}
}
@@ -2369,7 +2399,7 @@ void CChainState::PruneAndFlush() {
const CChainParams& chainparams = Params();
if (!this->FlushStateToDisk(chainparams, state, FlushStateMode::NONE)) {
- LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state));
+ LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString());
}
}
@@ -2505,35 +2535,21 @@ static int64_t nTimePostConnect = 0;
struct PerBlockConnectTrace {
CBlockIndex* pindex = nullptr;
std::shared_ptr<const CBlock> pblock;
- std::shared_ptr<std::vector<CTransactionRef>> conflictedTxs;
- PerBlockConnectTrace() : conflictedTxs(std::make_shared<std::vector<CTransactionRef>>()) {}
+ PerBlockConnectTrace() {}
};
/**
* Used to track blocks whose transactions were applied to the UTXO state as a
* part of a single ActivateBestChainStep call.
*
- * This class also tracks transactions that are removed from the mempool as
- * conflicts (per block) and can be used to pass all those transactions
- * through SyncTransaction.
- *
- * This class assumes (and asserts) that the conflicted transactions for a given
- * block are added via mempool callbacks prior to the BlockConnected() associated
- * with those transactions. If any transactions are marked conflicted, it is
- * assumed that an associated block will always be added.
- *
* This class is single-use, once you call GetBlocksConnected() you have to throw
* it away and make a new one.
*/
class ConnectTrace {
private:
std::vector<PerBlockConnectTrace> blocksConnected;
- CTxMemPool &pool;
- boost::signals2::scoped_connection m_connNotifyEntryRemoved;
public:
- explicit ConnectTrace(CTxMemPool &_pool) : blocksConnected(1), pool(_pool) {
- m_connNotifyEntryRemoved = pool.NotifyEntryRemoved.connect(std::bind(&ConnectTrace::NotifyEntryRemoved, this, std::placeholders::_1, std::placeholders::_2));
- }
+ explicit ConnectTrace() : blocksConnected(1) {}
void BlockConnected(CBlockIndex* pindex, std::shared_ptr<const CBlock> pblock) {
assert(!blocksConnected.back().pindex);
@@ -2551,17 +2567,9 @@ public:
// one waiting for the transactions from the next block. We pop
// the last entry here to make sure the list we return is sane.
assert(!blocksConnected.back().pindex);
- assert(blocksConnected.back().conflictedTxs->empty());
blocksConnected.pop_back();
return blocksConnected;
}
-
- void NotifyEntryRemoved(CTransactionRef txRemoved, MemPoolRemovalReason reason) {
- assert(!blocksConnected.back().pindex);
- if (reason == MemPoolRemovalReason::CONFLICT) {
- blocksConnected.back().conflictedTxs->emplace_back(std::move(txRemoved));
- }
- }
};
/**
@@ -2596,9 +2604,10 @@ bool CChainState::ConnectTip(BlockValidationState& state, const CChainParams& ch
if (!rv) {
if (state.IsInvalid())
InvalidBlockFound(pindexNew, state);
- return error("%s: ConnectBlock %s failed, %s", __func__, pindexNew->GetBlockHash().ToString(), FormatStateMessage(state));
+ return error("%s: ConnectBlock %s failed, %s", __func__, pindexNew->GetBlockHash().ToString(), state.ToString());
}
nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
+ assert(nBlocksTotal > 0);
LogPrint(BCLog::BENCH, " - Connect total: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime3 - nTime2) * MILLI, nTimeConnectTotal * MICRO, nTimeConnectTotal * MILLI / nBlocksTotal);
bool flushed = view.Flush();
assert(flushed);
@@ -2854,7 +2863,7 @@ bool CChainState::ActivateBestChain(BlockValidationState &state, const CChainPar
do {
// We absolutely may not unlock cs_main until we've made forward progress
// (with the exception of shutdown due to hardware issues, low disk space, etc).
- ConnectTrace connectTrace(mempool); // Destructed before cs_main is unlocked
+ ConnectTrace connectTrace; // Destructed before cs_main is unlocked
if (pindexMostWork == nullptr) {
pindexMostWork = FindMostWorkChain();
@@ -2881,7 +2890,7 @@ bool CChainState::ActivateBestChain(BlockValidationState &state, const CChainPar
for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) {
assert(trace.pblock && trace.pindex);
- GetMainSignals().BlockConnected(trace.pblock, trace.pindex, trace.conflictedTxs);
+ GetMainSignals().BlockConnected(trace.pblock, trace.pindex);
}
} while (!m_chain.Tip() || (starting_tip && CBlockIndexWorkComparator()(m_chain.Tip(), starting_tip)));
if (!blocks_connected) return true;
@@ -3377,7 +3386,14 @@ int GetWitnessCommitmentIndex(const CBlock& block)
int commitpos = -1;
if (!block.vtx.empty()) {
for (size_t o = 0; o < block.vtx[0]->vout.size(); o++) {
- if (block.vtx[0]->vout[o].scriptPubKey.size() >= 38 && block.vtx[0]->vout[o].scriptPubKey[0] == OP_RETURN && block.vtx[0]->vout[o].scriptPubKey[1] == 0x24 && block.vtx[0]->vout[o].scriptPubKey[2] == 0xaa && block.vtx[0]->vout[o].scriptPubKey[3] == 0x21 && block.vtx[0]->vout[o].scriptPubKey[4] == 0xa9 && block.vtx[0]->vout[o].scriptPubKey[5] == 0xed) {
+ const CTxOut& vout = block.vtx[0]->vout[o];
+ if (vout.scriptPubKey.size() >= MINIMUM_WITNESS_COMMITMENT &&
+ vout.scriptPubKey[0] == OP_RETURN &&
+ vout.scriptPubKey[1] == 0x24 &&
+ vout.scriptPubKey[2] == 0xaa &&
+ vout.scriptPubKey[3] == 0x21 &&
+ vout.scriptPubKey[4] == 0xa9 &&
+ vout.scriptPubKey[5] == 0xed) {
commitpos = o;
}
}
@@ -3408,7 +3424,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
CHash256().Write(witnessroot.begin(), 32).Write(ret.data(), 32).Finalize(witnessroot.begin());
CTxOut out;
out.nValue = 0;
- out.scriptPubKey.resize(38);
+ out.scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT);
out.scriptPubKey[0] = OP_RETURN;
out.scriptPubKey[1] = 0x24;
out.scriptPubKey[2] = 0xaa;
@@ -3465,7 +3481,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
if (fCheckpointsEnabled) {
// Don't accept any forks from the main chain prior to last checkpoint.
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
- // g_blockman.m_block_index.
+ // BlockIndex().
CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints());
if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
LogPrintf("ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__, nHeight);
@@ -3601,7 +3617,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
}
if (!CheckBlockHeader(block, state, chainparams.GetConsensus()))
- return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
+ return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, hash.ToString(), state.ToString());
// Get prev block index
CBlockIndex* pindexPrev = nullptr;
@@ -3616,7 +3632,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, "bad-prevblk");
}
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
- return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
+ return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), state.ToString());
/* Determine if this block descends from any block which has been found
* invalid (m_failed_blocks), then mark pindexPrev and any blocks between
@@ -3673,7 +3689,8 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, BlockValid
LOCK(cs_main);
for (const CBlockHeader& header : headers) {
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
- bool accepted = g_blockman.AcceptBlockHeader(header, state, chainparams, &pindex);
+ bool accepted = g_chainman.m_blockman.AcceptBlockHeader(
+ header, state, chainparams, &pindex);
::ChainstateActive().CheckBlockIndex(chainparams.GetConsensus());
if (!accepted) {
@@ -3766,7 +3783,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
}
- return error("%s: %s", __func__, FormatStateMessage(state));
+ return error("%s: %s", __func__, state.ToString());
}
// Header is valid/has work, merkle tree and segwit merkle tree are good...RELAY NOW
@@ -3816,7 +3833,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
}
if (!ret) {
GetMainSignals().BlockChecked(*pblock, state);
- return error("%s: AcceptBlock FAILED (%s)", __func__, FormatStateMessage(state));
+ return error("%s: AcceptBlock FAILED (%s)", __func__, state.ToString());
}
}
@@ -3824,7 +3841,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
BlockValidationState state; // Only used to report errors, not invalidity - ignore it
if (!::ChainstateActive().ActivateBestChain(state, chainparams, pblock))
- return error("%s: ActivateBestChain failed (%s)", __func__, FormatStateMessage(state));
+ return error("%s: ActivateBestChain failed (%s)", __func__, state.ToString());
return true;
}
@@ -3842,11 +3859,11 @@ bool TestBlockValidity(BlockValidationState& state, const CChainParams& chainpar
// NOTE: CheckBlockHeader is called by CheckBlock
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
- return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state));
+ return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.ToString());
if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot))
- return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
+ return error("%s: Consensus::CheckBlock: %s", __func__, state.ToString());
if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev))
- return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state));
+ return error("%s: Consensus::ContextualCheckBlock: %s", __func__, state.ToString());
if (!::ChainstateActive().ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true))
return false;
assert(state.IsValid());
@@ -3875,7 +3892,7 @@ void PruneOneBlockFile(const int fileNumber)
{
LOCK(cs_LastBlockFile);
- for (const auto& entry : g_blockman.m_block_index) {
+ for (const auto& entry : g_chainman.BlockIndex()) {
CBlockIndex* pindex = entry.second;
if (pindex->nFile == fileNumber) {
pindex->nStatus &= ~BLOCK_HAVE_DATA;
@@ -3889,12 +3906,12 @@ void PruneOneBlockFile(const int fileNumber)
// to be downloaded again in order to consider its chain, at which
// point it would be considered as a candidate for
// m_blocks_unlinked or setBlockIndexCandidates.
- auto range = g_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
+ auto range = g_chainman.m_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
while (range.first != range.second) {
std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first;
range.first++;
if (_it->second == pindex) {
- g_blockman.m_blocks_unlinked.erase(_it);
+ g_chainman.m_blockman.m_blocks_unlinked.erase(_it);
}
}
}
@@ -3944,7 +3961,7 @@ void PruneBlockFilesManual(int nManualPruneHeight)
const CChainParams& chainparams = Params();
if (!::ChainstateActive().FlushStateToDisk(
chainparams, state, FlushStateMode::NONE, nManualPruneHeight)) {
- LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state));
+ LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString());
}
}
@@ -4131,9 +4148,11 @@ void BlockManager::Unload() {
bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
- if (!g_blockman.LoadBlockIndex(
- chainparams.GetConsensus(), *pblocktree, ::ChainstateActive().setBlockIndexCandidates))
+ if (!g_chainman.m_blockman.LoadBlockIndex(
+ chainparams.GetConsensus(), *pblocktree,
+ ::ChainstateActive().setBlockIndexCandidates)) {
return false;
+ }
// Load block file info
pblocktree->ReadLastBlockFile(nLastBlockFile);
@@ -4155,7 +4174,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE
// Check presence of blk files
LogPrintf("Checking all blk files are present...\n");
std::set<int> setBlkDataFiles;
- for (const std::pair<const uint256, CBlockIndex*>& item : g_blockman.m_block_index)
+ for (const std::pair<const uint256, CBlockIndex*>& item : g_chainman.BlockIndex())
{
CBlockIndex* pindex = item.second;
if (pindex->nStatus & BLOCK_HAVE_DATA) {
@@ -4262,7 +4281,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
// check level 1: verify block validity
if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams.GetConsensus()))
return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__,
- pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state));
+ pindex->nHeight, pindex->GetBlockHash().ToString(), state.ToString());
// check level 2: verify undo validity
if (nCheckLevel >= 2 && pindex) {
CBlockUndo undo;
@@ -4311,7 +4330,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
if (!::ChainstateActive().ConnectBlock(block, state, pindex, coins, chainparams))
- return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state));
+ return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), state.ToString());
}
}
@@ -4499,7 +4518,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
// Disconnect block
if (!DisconnectTip(state, params, nullptr)) {
- return error("RewindBlockIndex: unable to disconnect block at height %i (%s)", tip->nHeight, FormatStateMessage(state));
+ return error("RewindBlockIndex: unable to disconnect block at height %i (%s)", tip->nHeight, state.ToString());
}
// Reduce validity flag and have-data flags.
@@ -4519,7 +4538,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
// Occasionally flush state to disk.
if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC)) {
- LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state));
+ LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", state.ToString());
return false;
}
}
@@ -4532,26 +4551,15 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
PruneBlockIndexCandidates();
CheckBlockIndex(params.GetConsensus());
- }
- }
- return true;
-}
-
-bool RewindBlockIndex(const CChainParams& params) {
- if (!::ChainstateActive().RewindBlockIndex(params)) {
- return false;
- }
-
- LOCK(cs_main);
- if (::ChainActive().Tip() != nullptr) {
- // FlushStateToDisk can possibly read ::ChainActive(). Be conservative
- // and skip it here, we're about to -reindex-chainstate anyway, so
- // it'll get called a bunch real soon.
- BlockValidationState state;
- if (!::ChainstateActive().FlushStateToDisk(params, state, FlushStateMode::ALWAYS)) {
- LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state));
- return false;
+ // FlushStateToDisk can possibly read ::ChainActive(). Be conservative
+ // and skip it here, we're about to -reindex-chainstate anyway, so
+ // it'll get called a bunch real soon.
+ BlockValidationState state;
+ if (!FlushStateToDisk(params, state, FlushStateMode::ALWAYS)) {
+ LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", state.ToString());
+ return false;
+ }
}
}
@@ -4569,8 +4577,7 @@ void CChainState::UnloadBlockIndex() {
void UnloadBlockIndex()
{
LOCK(cs_main);
- ::ChainActive().SetTip(nullptr);
- g_blockman.Unload();
+ g_chainman.Unload();
pindexBestInvalid = nullptr;
pindexBestHeader = nullptr;
mempool.clear();
@@ -4583,8 +4590,6 @@ void UnloadBlockIndex()
warningcache[b].clear();
}
fHavePruned = false;
-
- ::ChainstateActive().UnloadBlockIndex();
}
bool LoadBlockIndex(const CChainParams& chainparams)
@@ -4594,7 +4599,7 @@ bool LoadBlockIndex(const CChainParams& chainparams)
if (!fReindex) {
bool ret = LoadBlockIndexDB(chainparams);
if (!ret) return false;
- needs_init = g_blockman.m_block_index.empty();
+ needs_init = g_chainman.m_blockman.m_block_index.empty();
}
if (needs_init) {
@@ -4715,7 +4720,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFi
// Activate the genesis block so normal node progress can continue
if (hash == chainparams.GetConsensus().hashGenesisBlock) {
BlockValidationState state;
- if (!ActivateBestChain(state, chainparams)) {
+ if (!ActivateBestChain(state, chainparams, nullptr)) {
break;
}
}
@@ -4945,6 +4950,14 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
assert(nNodes == forward.size());
}
+std::string CChainState::ToString()
+{
+ CBlockIndex* tip = m_chain.Tip();
+ return strprintf("Chainstate [%s] @ height %d (%s)",
+ m_from_snapshot_blockhash.IsNull() ? "ibd" : "snapshot",
+ tip ? tip->nHeight : -1, tip ? tip->GetBlockHash().ToString() : "null");
+}
+
std::string CBlockFileInfo::ToString() const
{
return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast));
@@ -4992,6 +5005,7 @@ bool LoadMempool(CTxMemPool& pool)
int64_t expired = 0;
int64_t failed = 0;
int64_t already_there = 0;
+ int64_t unbroadcast = 0;
int64_t nNow = GetTime();
try {
@@ -5045,12 +5059,21 @@ bool LoadMempool(CTxMemPool& pool)
for (const auto& i : mapDeltas) {
pool.PrioritiseTransaction(i.first, i.second);
}
+
+ std::set<uint256> unbroadcast_txids;
+ file >> unbroadcast_txids;
+ unbroadcast = unbroadcast_txids.size();
+
+ for (const auto& txid : unbroadcast_txids) {
+ pool.AddUnbroadcastTx(txid);
+ }
+
} catch (const std::exception& e) {
LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
return false;
}
- LogPrintf("Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there\n", count, failed, expired, already_there);
+ LogPrintf("Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there, %i waiting for initial broadcast\n", count, failed, expired, already_there, unbroadcast);
return true;
}
@@ -5060,6 +5083,7 @@ bool DumpMempool(const CTxMemPool& pool)
std::map<uint256, CAmount> mapDeltas;
std::vector<TxMempoolInfo> vinfo;
+ std::set<uint256> unbroadcast_txids;
static Mutex dump_mutex;
LOCK(dump_mutex);
@@ -5070,6 +5094,7 @@ bool DumpMempool(const CTxMemPool& pool)
mapDeltas[i.first] = i.second;
}
vinfo = pool.infoAll();
+ unbroadcast_txids = pool.GetUnbroadcastTxs();
}
int64_t mid = GetTimeMicros();
@@ -5094,6 +5119,10 @@ bool DumpMempool(const CTxMemPool& pool)
}
file << mapDeltas;
+
+ LogPrintf("Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
+ file << unbroadcast_txids;
+
if (!FileCommit(file.Get()))
throw std::runtime_error("FileCommit failed");
file.fclose();
@@ -5132,10 +5161,99 @@ public:
CMainCleanup() {}
~CMainCleanup() {
// block headers
- BlockMap::iterator it1 = g_blockman.m_block_index.begin();
- for (; it1 != g_blockman.m_block_index.end(); it1++)
+ BlockMap::iterator it1 = g_chainman.BlockIndex().begin();
+ for (; it1 != g_chainman.BlockIndex().end(); it1++)
delete (*it1).second;
- g_blockman.m_block_index.clear();
+ g_chainman.BlockIndex().clear();
}
};
static CMainCleanup instance_of_cmaincleanup;
+
+Optional<uint256> ChainstateManager::SnapshotBlockhash() const {
+ if (m_active_chainstate != nullptr) {
+ // If a snapshot chainstate exists, it will always be our active.
+ return m_active_chainstate->m_from_snapshot_blockhash;
+ }
+ return {};
+}
+
+std::vector<CChainState*> ChainstateManager::GetAll()
+{
+ std::vector<CChainState*> out;
+
+ if (!IsSnapshotValidated() && m_ibd_chainstate) {
+ out.push_back(m_ibd_chainstate.get());
+ }
+
+ if (m_snapshot_chainstate) {
+ out.push_back(m_snapshot_chainstate.get());
+ }
+
+ return out;
+}
+
+CChainState& ChainstateManager::InitializeChainstate(const uint256& snapshot_blockhash)
+{
+ bool is_snapshot = !snapshot_blockhash.IsNull();
+ std::unique_ptr<CChainState>& to_modify =
+ is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate;
+
+ if (to_modify) {
+ throw std::logic_error("should not be overwriting a chainstate");
+ }
+
+ to_modify.reset(new CChainState(m_blockman, snapshot_blockhash));
+
+ // Snapshot chainstates and initial IBD chaintates always become active.
+ if (is_snapshot || (!is_snapshot && !m_active_chainstate)) {
+ LogPrintf("Switching active chainstate to %s\n", to_modify->ToString());
+ m_active_chainstate = to_modify.get();
+ } else {
+ throw std::logic_error("unexpected chainstate activation");
+ }
+
+ return *to_modify;
+}
+
+CChain& ChainstateManager::ActiveChain() const
+{
+ assert(m_active_chainstate);
+ return m_active_chainstate->m_chain;
+}
+
+bool ChainstateManager::IsSnapshotActive() const
+{
+ return m_snapshot_chainstate && m_active_chainstate == m_snapshot_chainstate.get();
+}
+
+CChainState& ChainstateManager::ValidatedChainstate() const
+{
+ if (m_snapshot_chainstate && IsSnapshotValidated()) {
+ return *m_snapshot_chainstate.get();
+ }
+ assert(m_ibd_chainstate);
+ return *m_ibd_chainstate.get();
+}
+
+bool ChainstateManager::IsBackgroundIBD(CChainState* chainstate) const
+{
+ return (m_snapshot_chainstate && chainstate == m_ibd_chainstate.get());
+}
+
+void ChainstateManager::Unload()
+{
+ for (CChainState* chainstate : this->GetAll()) {
+ chainstate->m_chain.SetTip(nullptr);
+ chainstate->UnloadBlockIndex();
+ }
+
+ m_blockman.Unload();
+}
+
+void ChainstateManager::Reset()
+{
+ m_ibd_chainstate.reset();
+ m_snapshot_chainstate.reset();
+ m_active_chainstate = nullptr;
+ m_snapshot_validated = false;
+}
diff --git a/src/validation.h b/src/validation.h
index a5335edc43..0169362768 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -14,6 +14,7 @@
#include <coins.h>
#include <crypto/common.h> // for ReadLE64
#include <fs.h>
+#include <optional.h>
#include <policy/feerate.h>
#include <protocol.h> // For CMessageHeader::MessageStartChars
#include <script/script_error.h>
@@ -59,57 +60,15 @@ static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 101;
static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25;
/** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */
static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101;
-/**
- * An extra transaction can be added to a package, as long as it only has one
- * ancestor and is no larger than this. Not really any reason to make this
- * configurable as it doesn't materially change DoS parameters.
- */
-static const unsigned int EXTRA_DESCENDANT_TX_SIZE_LIMIT = 10000;
/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 336;
-/** Maximum kilobytes for transactions to store for processing during reorg */
-static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE = 20000;
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
-/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
-static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
-/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
-static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
-
/** Maximum number of dedicated script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 15;
/** -par default (number of script-checking threads, 0 = auto) */
static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
-/** Number of blocks that can be requested at any given time from a single peer. */
-static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
-/** Timeout in seconds during which a peer must stall block download progress before being disconnected. */
-static const unsigned int BLOCK_STALLING_TIMEOUT = 2;
-/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
- * less than this number, we reached its tip. Changing this value is a protocol upgrade. */
-static const unsigned int MAX_HEADERS_RESULTS = 2000;
-/** Maximum depth of blocks we're willing to serve as compact blocks to peers
- * when requested. For older blocks, a regular BLOCK response will be sent. */
-static const int MAX_CMPCTBLOCK_DEPTH = 5;
-/** Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for. */
-static const int MAX_BLOCKTXN_DEPTH = 10;
-/** Size of the "block download window": how far ahead of our current height do we fetch?
- * Larger windows tolerate larger download speed differences between peer, but increase the potential
- * degree of disordering of blocks on disk (which make reindexing and pruning harder). We'll probably
- * want to make this a per-peer adaptive value at some point. */
-static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
-/** Time to wait (in seconds) between writing blocks/block index to disk. */
-static const unsigned int DATABASE_WRITE_INTERVAL = 60 * 60;
-/** Time to wait (in seconds) between flushing chainstate to disk. */
-static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60;
-/** Block download timeout base, expressed in millionths of the block interval (i.e. 10 min) */
-static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000;
-/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
-static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000;
-
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
-/** Maximum age of our tip in seconds for us to be considered current for fee estimation */
-static const int64_t MAX_FEE_ESTIMATION_TIP_AGE = 3 * 60 * 60;
-
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
static const char* const DEFAULT_BLOCKFILTERINDEX = "0";
@@ -118,15 +77,23 @@ static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
static const bool DEFAULT_PERSIST_MEMPOOL = true;
/** Default for using fee filter */
static const bool DEFAULT_FEEFILTER = true;
-
-/** Maximum number of headers to announce when relaying blocks with headers message.*/
-static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
-
-/** Maximum number of unconnecting headers announcements before DoS score */
-static const int MAX_UNCONNECTING_HEADERS = 10;
-
/** Default for -stopatheight */
static const int DEFAULT_STOPATHEIGHT = 0;
+/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ::ChainActive().Tip() will not be pruned. */
+static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
+static const signed int DEFAULT_CHECKBLOCKS = 6;
+static const unsigned int DEFAULT_CHECKLEVEL = 3;
+// Require that user allocate at least 550 MiB for block & undo files (blk???.dat and rev???.dat)
+// At 1MB per block, 288 blocks = 288MB.
+// Add 15% for Undo data = 331MB
+// Add 20% for Orphan block rate = 397MB
+// We want the low water mark after pruning to be at least 397 MB and since we prune in
+// full block file chunks, we need the high water mark which triggers the prune to be
+// one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB
+// Setting the target to >= 550 MiB will make it likely we can respect the target.
+static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
+/** Minimum size of a witness commitment structure. Defined in BIP 141. **/
+static constexpr size_t MINIMUM_WITNESS_COMMITMENT{38};
struct BlockHasher
{
@@ -174,23 +141,6 @@ extern bool fHavePruned;
extern bool fPruneMode;
/** Number of MiB of block files that we're trying to stay below. */
extern uint64_t nPruneTarget;
-/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ::ChainActive().Tip() will not be pruned. */
-static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
-/** Minimum blocks required to signal NODE_NETWORK_LIMITED */
-static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
-
-static const signed int DEFAULT_CHECKBLOCKS = 6;
-static const unsigned int DEFAULT_CHECKLEVEL = 3;
-
-// Require that user allocate at least 550 MiB for block & undo files (blk???.dat and rev???.dat)
-// At 1MB per block, 288 blocks = 288MB.
-// Add 15% for Undo data = 331MB
-// Add 20% for Orphan block rate = 397MB
-// We want the low water mark after pruning to be at least 397 MB and since we prune in
-// full block file chunks, we need the high water mark which triggers the prune to be
-// one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB
-// Setting the target to >= 550 MiB will make it likely we can respect the target.
-static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
/**
* Process an incoming block. This only returns after the best known valid
@@ -379,9 +329,6 @@ bool TestBlockValidity(BlockValidationState& state, const CChainParams& chainpar
* Note that transaction witness validation rules are always enforced when P2SH is enforced. */
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
-/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */
-bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);
-
/** Compute at which vout of the block's coinbase transaction the witness commitment occurs, or -1 if not found */
int GetWitnessCommitmentIndex(const CBlock& block);
@@ -539,6 +486,9 @@ enum class CoinsCacheSizeState
OK = 0
};
+// Defined below, but needed for `friend` usage in CChainState.
+class ChainstateManager;
+
/**
* CChainState stores and provides an API to update our local knowledge of the
* current best chain.
@@ -591,8 +541,7 @@ private:
std::unique_ptr<CoinsViews> m_coins_views;
public:
- CChainState(BlockManager& blockman) : m_blockman(blockman) {}
- CChainState();
+ explicit CChainState(BlockManager& blockman, uint256 from_snapshot_blockhash = uint256());
/**
* Initialize the CoinsViews UTXO set database management data structures. The in-memory
@@ -621,6 +570,13 @@ public:
CChain m_chain;
/**
+ * The blockhash which is the base of the snapshot this chainstate was created from.
+ *
+ * IsNull() if this chainstate was not created from a snapshot.
+ */
+ const uint256 m_from_snapshot_blockhash{};
+
+ /**
* The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and
* as good as our current tip or better. Entries may be failed, though, and pruning nodes may be
* missing the data for the block.
@@ -741,6 +697,8 @@ public:
size_t max_coins_cache_size_bytes,
size_t max_mempool_size_bytes) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+ std::string ToString() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+
private:
bool ActivateBestChainStep(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::mempool.cs);
bool ConnectTip(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions& disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::mempool.cs);
@@ -753,6 +711,8 @@ private:
//! Mark a block as not having block data
void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ friend ChainstateManager;
};
/** Mark a block as precious and reorganize.
@@ -768,6 +728,150 @@ bool InvalidateBlock(BlockValidationState& state, const CChainParams& chainparam
/** Remove invalidity status from a block and its descendants. */
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+/**
+ * Provides an interface for creating and interacting with one or two
+ * chainstates: an IBD chainstate generated by downloading blocks, and
+ * an optional snapshot chainstate loaded from a UTXO snapshot. Managed
+ * chainstates can be maintained at different heights simultaneously.
+ *
+ * This class provides abstractions that allow the retrieval of the current
+ * most-work chainstate ("Active") as well as chainstates which may be in
+ * background use to validate UTXO snapshots.
+ *
+ * Definitions:
+ *
+ * *IBD chainstate*: a chainstate whose current state has been "fully"
+ * validated by the initial block download process.
+ *
+ * *Snapshot chainstate*: a chainstate populated by loading in an
+ * assumeutxo UTXO snapshot.
+ *
+ * *Active chainstate*: the chainstate containing the current most-work
+ * chain. Consulted by most parts of the system (net_processing,
+ * wallet) as a reflection of the current chain and UTXO set.
+ * This may either be an IBD chainstate or a snapshot chainstate.
+ *
+ * *Background IBD chainstate*: an IBD chainstate for which the
+ * IBD process is happening in the background while use of the
+ * active (snapshot) chainstate allows the rest of the system to function.
+ *
+ * *Validated chainstate*: the most-work chainstate which has been validated
+ * locally via initial block download. This will be the snapshot chainstate
+ * if a snapshot was loaded and all blocks up to the snapshot starting point
+ * have been downloaded and validated (via background validation), otherwise
+ * it will be the IBD chainstate.
+ */
+class ChainstateManager
+{
+private:
+ //! The chainstate used under normal operation (i.e. "regular" IBD) or, if
+ //! a snapshot is in use, for background validation.
+ //!
+ //! Its contents (including on-disk data) will be deleted *upon shutdown*
+ //! after background validation of the snapshot has completed. We do not
+ //! free the chainstate contents immediately after it finishes validation
+ //! to cautiously avoid a case where some other part of the system is still
+ //! using this pointer (e.g. net_processing).
+ //!
+ //! Once this pointer is set to a corresponding chainstate, it will not
+ //! be reset until init.cpp:Shutdown(). This means it is safe to acquire
+ //! the contents of this pointer with ::cs_main held, release the lock,
+ //! and then use the reference without concern of it being deconstructed.
+ //!
+ //! This is especially important when, e.g., calling ActivateBestChain()
+ //! on all chainstates because we are not able to hold ::cs_main going into
+ //! that call.
+ std::unique_ptr<CChainState> m_ibd_chainstate;
+
+ //! A chainstate initialized on the basis of a UTXO snapshot. If this is
+ //! non-null, it is always our active chainstate.
+ //!
+ //! Once this pointer is set to a corresponding chainstate, it will not
+ //! be reset until init.cpp:Shutdown(). This means it is safe to acquire
+ //! the contents of this pointer with ::cs_main held, release the lock,
+ //! and then use the reference without concern of it being deconstructed.
+ //!
+ //! This is especially important when, e.g., calling ActivateBestChain()
+ //! on all chainstates because we are not able to hold ::cs_main going into
+ //! that call.
+ std::unique_ptr<CChainState> m_snapshot_chainstate;
+
+ //! Points to either the ibd or snapshot chainstate; indicates our
+ //! most-work chain.
+ //!
+ //! Once this pointer is set to a corresponding chainstate, it will not
+ //! be reset until init.cpp:Shutdown(). This means it is safe to acquire
+ //! the contents of this pointer with ::cs_main held, release the lock,
+ //! and then use the reference without concern of it being deconstructed.
+ //!
+ //! This is especially important when, e.g., calling ActivateBestChain()
+ //! on all chainstates because we are not able to hold ::cs_main going into
+ //! that call.
+ CChainState* m_active_chainstate{nullptr};
+
+ //! If true, the assumed-valid chainstate has been fully validated
+ //! by the background validation chainstate.
+ bool m_snapshot_validated{false};
+
+ // For access to m_active_chainstate.
+ friend CChainState& ChainstateActive();
+ friend CChain& ChainActive();
+
+public:
+ //! A single BlockManager instance is shared across each constructed
+ //! chainstate to avoid duplicating block metadata.
+ BlockManager m_blockman GUARDED_BY(::cs_main);
+
+ //! Instantiate a new chainstate and assign it based upon whether it is
+ //! from a snapshot.
+ //!
+ //! @param[in] snapshot_blockhash If given, signify that this chainstate
+ //! is based on a snapshot.
+ CChainState& InitializeChainstate(const uint256& snapshot_blockhash = uint256())
+ EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+
+ //! Get all chainstates currently being used.
+ std::vector<CChainState*> GetAll();
+
+ //! The most-work chain.
+ CChain& ActiveChain() const;
+ int ActiveHeight() const { return ActiveChain().Height(); }
+ CBlockIndex* ActiveTip() const { return ActiveChain().Tip(); }
+
+ BlockMap& BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
+ {
+ return m_blockman.m_block_index;
+ }
+
+ bool IsSnapshotActive() const;
+
+ Optional<uint256> SnapshotBlockhash() const;
+
+ //! Is there a snapshot in use and has it been fully validated?
+ bool IsSnapshotValidated() const { return m_snapshot_validated; }
+
+ //! @returns true if this chainstate is being used to validate an active
+ //! snapshot in the background.
+ bool IsBackgroundIBD(CChainState* chainstate) const;
+
+ //! Return the most-work chainstate that has been fully validated.
+ //!
+ //! During background validation of a snapshot, this is the IBD chain. After
+ //! background validation has completed, this is the snapshot chain.
+ CChainState& ValidatedChainstate() const;
+
+ CChain& ValidatedChain() const { return ValidatedChainstate().m_chain; }
+ CBlockIndex* ValidatedTip() const { return ValidatedChain().Tip(); }
+
+ //! Unload block index and chain data before shutdown.
+ void Unload() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+
+ //! Clear (deconstruct) chainstate data.
+ void Reset();
+};
+
+extern ChainstateManager g_chainman GUARDED_BY(::cs_main);
+
/** @returns the most-work valid chainstate. */
CChainState& ChainstateActive();
@@ -777,11 +881,6 @@ CChain& ChainActive();
/** @returns the global block index map. */
BlockMap& BlockIndex();
-// Most often ::ChainstateActive() should be used instead of this, but some code
-// may not be able to assume that this has been initialized yet and so must use it
-// directly, e.g. init.cpp.
-extern std::unique_ptr<CChainState> g_chainstate;
-
/** Global variable that points to the active block tree (protected by cs_main) */
extern std::unique_ptr<CBlockTreeDB> pblocktree;
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 0f513c065f..11000774c0 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -11,42 +11,80 @@
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <scheduler.h>
-#include <util/validation.h>
#include <future>
#include <unordered_map>
#include <utility>
-#include <boost/signals2/signal.hpp>
-
-struct ValidationInterfaceConnections {
- boost::signals2::scoped_connection UpdatedBlockTip;
- boost::signals2::scoped_connection TransactionAddedToMempool;
- boost::signals2::scoped_connection BlockConnected;
- boost::signals2::scoped_connection BlockDisconnected;
- boost::signals2::scoped_connection TransactionRemovedFromMempool;
- boost::signals2::scoped_connection ChainStateFlushed;
- boost::signals2::scoped_connection BlockChecked;
- boost::signals2::scoped_connection NewPoWValidBlock;
-};
-
+//! The MainSignalsInstance manages a list of shared_ptr<CValidationInterface>
+//! callbacks.
+//!
+//! A std::unordered_map is used to track what callbacks are currently
+//! registered, and a std::list is to used to store the callbacks that are
+//! currently registered as well as any callbacks that are just unregistered
+//! and about to be deleted when they are done executing.
struct MainSignalsInstance {
- boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
- boost::signals2::signal<void (const CTransactionRef &)> TransactionAddedToMempool;
- boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected;
- boost::signals2::signal<void (const std::shared_ptr<const CBlock>&, const CBlockIndex* pindex)> BlockDisconnected;
- boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
- boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed;
- boost::signals2::signal<void (const CBlock&, const BlockValidationState&)> BlockChecked;
- boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
-
+private:
+ Mutex m_mutex;
+ //! List entries consist of a callback pointer and reference count. The
+ //! count is equal to the number of current executions of that entry, plus 1
+ //! if it's registered. It cannot be 0 because that would imply it is
+ //! unregistered and also not being executed (so shouldn't exist).
+ struct ListEntry { std::shared_ptr<CValidationInterface> callbacks; int count = 1; };
+ std::list<ListEntry> m_list GUARDED_BY(m_mutex);
+ std::unordered_map<CValidationInterface*, std::list<ListEntry>::iterator> m_map GUARDED_BY(m_mutex);
+
+public:
// We are not allowed to assume the scheduler only runs in one thread,
// but must ensure all callbacks happen in-order, so we end up creating
// our own queue here :(
SingleThreadedSchedulerClient m_schedulerClient;
- std::unordered_map<CValidationInterface*, ValidationInterfaceConnections> m_connMainSignals;
explicit MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {}
+
+ void Register(std::shared_ptr<CValidationInterface> callbacks)
+ {
+ LOCK(m_mutex);
+ auto inserted = m_map.emplace(callbacks.get(), m_list.end());
+ if (inserted.second) inserted.first->second = m_list.emplace(m_list.end());
+ inserted.first->second->callbacks = std::move(callbacks);
+ }
+
+ void Unregister(CValidationInterface* callbacks)
+ {
+ LOCK(m_mutex);
+ auto it = m_map.find(callbacks);
+ if (it != m_map.end()) {
+ if (!--it->second->count) m_list.erase(it->second);
+ m_map.erase(it);
+ }
+ }
+
+ //! Clear unregisters every previously registered callback, erasing every
+ //! map entry. After this call, the list may still contain callbacks that
+ //! are currently executing, but it will be cleared when they are done
+ //! executing.
+ void Clear()
+ {
+ LOCK(m_mutex);
+ for (const auto& entry : m_map) {
+ if (!--entry.second->count) m_list.erase(entry.second);
+ }
+ m_map.clear();
+ }
+
+ template<typename F> void Iterate(F&& f)
+ {
+ WAIT_LOCK(m_mutex, lock);
+ for (auto it = m_list.begin(); it != m_list.end();) {
+ ++it->count;
+ {
+ REVERSE_LOCK(lock);
+ f(*it->callbacks);
+ }
+ it = --it->count ? std::next(it) : m_list.erase(it);
+ }
+ }
};
static CMainSignals g_signals;
@@ -76,21 +114,27 @@ CMainSignals& GetMainSignals()
return g_signals;
}
-void RegisterValidationInterface(CValidationInterface* pwalletIn) {
- ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn];
- conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
- conns.TransactionAddedToMempool = g_signals.m_internals->TransactionAddedToMempool.connect(std::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, std::placeholders::_1));
- conns.BlockConnected = g_signals.m_internals->BlockConnected.connect(std::bind(&CValidationInterface::BlockConnected, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
- conns.BlockDisconnected = g_signals.m_internals->BlockDisconnected.connect(std::bind(&CValidationInterface::BlockDisconnected, pwalletIn, std::placeholders::_1, std::placeholders::_2));
- conns.TransactionRemovedFromMempool = g_signals.m_internals->TransactionRemovedFromMempool.connect(std::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, std::placeholders::_1));
- conns.ChainStateFlushed = g_signals.m_internals->ChainStateFlushed.connect(std::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, std::placeholders::_1));
- conns.BlockChecked = g_signals.m_internals->BlockChecked.connect(std::bind(&CValidationInterface::BlockChecked, pwalletIn, std::placeholders::_1, std::placeholders::_2));
- conns.NewPoWValidBlock = g_signals.m_internals->NewPoWValidBlock.connect(std::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, std::placeholders::_1, std::placeholders::_2));
+void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> pwalletIn) {
+ // Each connection captures pwalletIn to ensure that each callback is
+ // executed before pwalletIn is destroyed. For more details see #18338.
+ g_signals.m_internals->Register(std::move(pwalletIn));
+}
+
+void RegisterValidationInterface(CValidationInterface* callbacks)
+{
+ // Create a shared_ptr with a no-op deleter - CValidationInterface lifecycle
+ // is managed by the caller.
+ RegisterSharedValidationInterface({callbacks, [](CValidationInterface*){}});
+}
+
+void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
+{
+ UnregisterValidationInterface(callbacks.get());
}
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
if (g_signals.m_internals) {
- g_signals.m_internals->m_connMainSignals.erase(pwalletIn);
+ g_signals.m_internals->Unregister(pwalletIn);
}
}
@@ -98,7 +142,7 @@ void UnregisterAllValidationInterfaces() {
if (!g_signals.m_internals) {
return;
}
- g_signals.m_internals->m_connMainSignals.clear();
+ g_signals.m_internals->Clear();
}
void CallFunctionInValidationInterfaceQueue(std::function<void ()> func) {
@@ -138,7 +182,7 @@ void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockInd
// in the same critical section where the chain is updated
auto event = [pindexNew, pindexFork, fInitialDownload, this] {
- m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
+ m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); });
};
ENQUEUE_AND_LOG_EVENT(event, "%s: new block hash=%s fork block hash=%s (in IBD=%s)", __func__,
pindexNew->GetBlockHash().ToString(),
@@ -148,7 +192,7 @@ void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockInd
void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) {
auto event = [ptx, this] {
- m_internals->TransactionAddedToMempool(ptx);
+ m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.TransactionAddedToMempool(ptx); });
};
ENQUEUE_AND_LOG_EVENT(event, "%s: txid=%s wtxid=%s", __func__,
ptx->GetHash().ToString(),
@@ -157,16 +201,16 @@ void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) {
void CMainSignals::TransactionRemovedFromMempool(const CTransactionRef &ptx) {
auto event = [ptx, this] {
- m_internals->TransactionRemovedFromMempool(ptx);
+ m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.TransactionRemovedFromMempool(ptx); });
};
ENQUEUE_AND_LOG_EVENT(event, "%s: txid=%s wtxid=%s", __func__,
ptx->GetHash().ToString(),
ptx->GetWitnessHash().ToString());
}
-void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>>& pvtxConflicted) {
- auto event = [pblock, pindex, pvtxConflicted, this] {
- m_internals->BlockConnected(pblock, pindex, *pvtxConflicted);
+void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex) {
+ auto event = [pblock, pindex, this] {
+ m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockConnected(pblock, pindex); });
};
ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s block height=%d", __func__,
pblock->GetHash().ToString(),
@@ -176,7 +220,7 @@ void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, c
void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex)
{
auto event = [pblock, pindex, this] {
- m_internals->BlockDisconnected(pblock, pindex);
+ m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockDisconnected(pblock, pindex); });
};
ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s block height=%d", __func__,
pblock->GetHash().ToString(),
@@ -185,7 +229,7 @@ void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock
void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
auto event = [locator, this] {
- m_internals->ChainStateFlushed(locator);
+ m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.ChainStateFlushed(locator); });
};
ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s", __func__,
locator.IsNull() ? "null" : locator.vHave.front().ToString());
@@ -193,11 +237,11 @@ void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
void CMainSignals::BlockChecked(const CBlock& block, const BlockValidationState& state) {
LOG_EVENT("%s: block hash=%s state=%s", __func__,
- block.GetHash().ToString(), FormatStateMessage(state));
- m_internals->BlockChecked(block, state);
+ block.GetHash().ToString(), state.ToString());
+ m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockChecked(block, state); });
}
void CMainSignals::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock> &block) {
LOG_EVENT("%s: block hash=%s", __func__, block->GetHash().ToString());
- m_internals->NewPoWValidBlock(pindex, block);
+ m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NewPoWValidBlock(pindex, block); });
}
diff --git a/src/validationinterface.h b/src/validationinterface.h
index ed6c560944..cb0204a555 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -30,6 +30,14 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn);
void UnregisterValidationInterface(CValidationInterface* pwalletIn);
/** Unregister all wallets from core */
void UnregisterAllValidationInterfaces();
+
+// Alternate registration functions that release a shared_ptr after the last
+// notification is sent. These are useful for race-free cleanup, since
+// unregistration is nonblocking and can return before the last notification is
+// processed.
+void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks);
+void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks);
+
/**
* Pushes a function to callback onto the notification queue, guaranteeing any
* callbacks generated prior to now are finished when the function is called.
@@ -92,10 +100,32 @@ protected:
/**
* Notifies listeners of a transaction leaving mempool.
*
- * This only fires for transactions which leave mempool because of expiry,
- * size limiting, reorg (changes in lock times/coinbase maturity), or
- * replacement. This does not include any transactions which are included
- * in BlockConnectedDisconnected either in block->vtx or in txnConflicted.
+ * This notification fires for transactions that are removed from the
+ * mempool for the following reasons:
+ *
+ * - EXPIRY (expired from mempool after -mempoolexpiry hours)
+ * - SIZELIMIT (removed in size limiting if the mempool exceeds -maxmempool megabytes)
+ * - REORG (removed during a reorg)
+ * - CONFLICT (removed because it conflicts with in-block transaction)
+ * - REPLACED (removed due to RBF replacement)
+ *
+ * This does not fire for transactions that are removed from the mempool
+ * because they have been included in a block. Any client that is interested
+ * in transactions removed from the mempool for inclusion in a block can learn
+ * about those transactions from the BlockConnected notification.
+ *
+ * Transactions that are removed from the mempool because they conflict
+ * with a transaction in the new block will have
+ * TransactionRemovedFromMempool events fired *before* the BlockConnected
+ * event is fired. If multiple blocks are connected in one step, then the
+ * ordering could be:
+ *
+ * - TransactionRemovedFromMempool(tx1 from block A)
+ * - TransactionRemovedFromMempool(tx2 from block A)
+ * - TransactionRemovedFromMempool(tx1 from block B)
+ * - TransactionRemovedFromMempool(tx2 from block B)
+ * - BlockConnected(A)
+ * - BlockConnected(B)
*
* Called on a background thread.
*/
@@ -106,7 +136,7 @@ protected:
*
* Called on a background thread.
*/
- virtual void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex, const std::vector<CTransactionRef> &txnConflicted) {}
+ virtual void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex) {}
/**
* Notifies listeners of a block being disconnected
*
@@ -141,9 +171,7 @@ protected:
* Notifies listeners that a block which builds directly on our current tip
* has been received and connected to the headers tree, though not validated yet */
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) {};
- friend void ::RegisterValidationInterface(CValidationInterface*);
- friend void ::UnregisterValidationInterface(CValidationInterface*);
- friend void ::UnregisterAllValidationInterfaces();
+ friend class CMainSignals;
};
struct MainSignalsInstance;
@@ -151,7 +179,7 @@ class CMainSignals {
private:
std::unique_ptr<MainSignalsInstance> m_internals;
- friend void ::RegisterValidationInterface(CValidationInterface*);
+ friend void ::RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface>);
friend void ::UnregisterValidationInterface(CValidationInterface*);
friend void ::UnregisterAllValidationInterfaces();
friend void ::CallFunctionInValidationInterfaceQueue(std::function<void ()> func);
@@ -170,7 +198,7 @@ public:
void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload);
void TransactionAddedToMempool(const CTransactionRef &);
void TransactionRemovedFromMempool(const CTransactionRef &);
- void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &);
+ void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex);
void BlockDisconnected(const std::shared_ptr<const CBlock> &, const CBlockIndex* pindex);
void ChainStateFlushed(const CBlockLocator &);
void BlockChecked(const CBlock&, const BlockValidationState&);
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index 5bbb2c0ad0..079a5d3d53 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -106,6 +106,9 @@ bool SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& target_v
best_selection = curr_selection;
best_selection.resize(utxo_pool.size());
best_waste = curr_waste;
+ if (best_waste == 0) {
+ break;
+ }
}
curr_waste -= (curr_value - actual_target); // Remove the excess value as we will be selecting different coins now
backtrack = true;
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 8b042162d8..67be4d85d2 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -756,7 +756,7 @@ bool BerkeleyBatch::Rewrite(BerkeleyDatabase& database, const char* pszSkip)
return fSuccess;
}
}
- MilliSleep(100);
+ UninterruptibleSleep(std::chrono::milliseconds{100});
}
}
@@ -850,7 +850,7 @@ bool BerkeleyDatabase::Rewrite(const char* pszSkip)
return BerkeleyBatch::Rewrite(*this, pszSkip);
}
-bool BerkeleyDatabase::Backup(const std::string& strDest)
+bool BerkeleyDatabase::Backup(const std::string& strDest) const
{
if (IsDummy()) {
return false;
@@ -887,7 +887,7 @@ bool BerkeleyDatabase::Backup(const std::string& strDest)
}
}
}
- MilliSleep(100);
+ UninterruptibleSleep(std::chrono::milliseconds{100});
}
}
diff --git a/src/wallet/db.h b/src/wallet/db.h
index abec3ae4e2..1c5f42abca 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -157,7 +157,7 @@ public:
/** Back up the entire database to a file.
*/
- bool Backup(const std::string& strDest);
+ bool Backup(const std::string& strDest) const;
/** Make sure all changes are flushed to disk.
*/
@@ -193,7 +193,7 @@ private:
* Only to be used at a low level, application should ideally not care
* about this.
*/
- bool IsDummy() { return env == nullptr; }
+ bool IsDummy() const { return env == nullptr; }
};
/** RAII class that provides access to a Berkeley database */
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index b93b9ef1bc..01fcb1680e 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -12,7 +12,6 @@
#include <util/moneystr.h>
#include <util/rbf.h>
#include <util/system.h>
-#include <util/validation.h>
//! Check whether transaction has descendant in wallet or mempool, or has been
//! mined, or conflicts with a mined transaction. Return a feebumper::Result.
@@ -61,7 +60,7 @@ static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWallet
static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) {
// check that fee rate is higher than mempool's minimum fee
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
- // This may occur if the user set FeeRate, TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
+ // This may occur if the user set fee_rate or paytxfee too low, if fallbackfee is too low, or, perhaps,
// in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a
// moment earlier. In this case, we report an error to the user, who may adjust the fee.
CFeeRate minMempoolFeeRate = wallet.chain().mempoolMinFee();
@@ -141,7 +140,6 @@ namespace feebumper {
bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid)
{
- auto locked_chain = wallet.chain().lock();
LOCK(wallet.cs_wallet);
const CWalletTx* wtx = wallet.GetWalletTx(txid);
if (wtx == nullptr) return false;
@@ -151,139 +149,12 @@ bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid)
return res == feebumper::Result::OK;
}
-Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors,
- CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
-{
- new_fee = total_fee;
-
- auto locked_chain = wallet->chain().lock();
- LOCK(wallet->cs_wallet);
- errors.clear();
- auto it = wallet->mapWallet.find(txid);
- if (it == wallet->mapWallet.end()) {
- errors.push_back("Invalid or non-wallet transaction id");
- return Result::INVALID_ADDRESS_OR_KEY;
- }
- const CWalletTx& wtx = it->second;
-
- Result result = PreconditionChecks(*wallet, wtx, errors);
- if (result != Result::OK) {
- return result;
- }
-
- // figure out which output was change
- // if there was no change output or multiple change outputs, fail
- int nOutput = -1;
- for (size_t i = 0; i < wtx.tx->vout.size(); ++i) {
- if (wallet->IsChange(wtx.tx->vout[i])) {
- if (nOutput != -1) {
- errors.push_back("Transaction has multiple change outputs");
- return Result::WALLET_ERROR;
- }
- nOutput = i;
- }
- }
- if (nOutput == -1) {
- errors.push_back("Transaction does not have a change output");
- return Result::WALLET_ERROR;
- }
-
- // Calculate the expected size of the new transaction.
- int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
- const int64_t maxNewTxSize = CalculateMaximumSignedTxSize(*wtx.tx, wallet);
- if (maxNewTxSize < 0) {
- errors.push_back("Transaction contains inputs that cannot be signed");
- return Result::INVALID_ADDRESS_OR_KEY;
- }
-
- // calculate the old fee and fee-rate
- isminefilter filter = wallet->GetLegacyScriptPubKeyMan() && wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
- old_fee = wtx.GetDebit(filter) - wtx.tx->GetValueOut();
- CFeeRate nOldFeeRate(old_fee, txSize);
- // The wallet uses a conservative WALLET_INCREMENTAL_RELAY_FEE value to
- // future proof against changes to network wide policy for incremental relay
- // fee that our node may not be aware of.
- CFeeRate nodeIncrementalRelayFee = wallet->chain().relayIncrementalFee();
- CFeeRate walletIncrementalRelayFee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
- if (nodeIncrementalRelayFee > walletIncrementalRelayFee) {
- walletIncrementalRelayFee = nodeIncrementalRelayFee;
- }
-
- CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + nodeIncrementalRelayFee.GetFee(maxNewTxSize);
- if (total_fee < minTotalFee) {
- errors.push_back(strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)",
- FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(nodeIncrementalRelayFee.GetFee(maxNewTxSize))));
- return Result::INVALID_PARAMETER;
- }
- CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize);
- if (total_fee < requiredFee) {
- errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)",
- FormatMoney(requiredFee)));
- return Result::INVALID_PARAMETER;
- }
-
- // Check that in all cases the new fee doesn't violate maxTxFee
- const CAmount max_tx_fee = wallet->m_default_max_tx_fee;
- if (new_fee > max_tx_fee) {
- errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)",
- FormatMoney(new_fee), FormatMoney(max_tx_fee)));
- return Result::WALLET_ERROR;
- }
-
- // check that fee rate is higher than mempool's minimum fee
- // (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
- // This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
- // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a
- // moment earlier. In this case, we report an error to the user, who may use total_fee to make an adjustment.
- CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee();
- CFeeRate nNewFeeRate = CFeeRate(total_fee, maxNewTxSize);
- if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) {
- errors.push_back(strprintf(
- "New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- "
- "the totalFee value should be at least %s to add transaction",
- FormatMoney(nNewFeeRate.GetFeePerK()),
- FormatMoney(minMempoolFeeRate.GetFeePerK()),
- FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize))));
- return Result::WALLET_ERROR;
- }
-
- // Now modify the output to increase the fee.
- // If the output is not large enough to pay the fee, fail.
- CAmount nDelta = new_fee - old_fee;
- assert(nDelta > 0);
- mtx = CMutableTransaction{*wtx.tx};
- CTxOut* poutput = &(mtx.vout[nOutput]);
- if (poutput->nValue < nDelta) {
- errors.push_back("Change output is too small to bump the fee");
- return Result::WALLET_ERROR;
- }
-
- // If the output would become dust, discard it (converting the dust to fee)
- poutput->nValue -= nDelta;
- if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(*wallet))) {
- wallet->WalletLogPrintf("Bumping fee and discarding dust output\n");
- new_fee += poutput->nValue;
- mtx.vout.erase(mtx.vout.begin() + nOutput);
- }
-
- // Mark new tx not replaceable, if requested.
- if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet->m_signal_rbf)) {
- for (auto& input : mtx.vin) {
- if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe;
- }
- }
-
- return Result::OK;
-}
-
-
Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors,
CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
{
// We are going to modify coin control later, copy to re-use
CCoinControl new_coin_control(coin_control);
- auto locked_chain = wallet.chain().lock();
LOCK(wallet.cs_wallet);
errors.clear();
auto it = wallet.mapWallet.find(txid);
@@ -346,7 +217,7 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
CAmount fee_ret;
int change_pos_in_out = -1; // No requested location for change
std::string fail_reason;
- if (!wallet.CreateTransaction(*locked_chain, recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) {
+ if (!wallet.CreateTransaction(recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) {
errors.push_back("Unable to create transaction: " + fail_reason);
return Result::WALLET_ERROR;
}
@@ -367,14 +238,12 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
}
bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx) {
- auto locked_chain = wallet.chain().lock();
LOCK(wallet.cs_wallet);
return wallet.SignTransaction(mtx);
}
Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid)
{
- auto locked_chain = wallet.chain().lock();
LOCK(wallet.cs_wallet);
if (!errors.empty()) {
return Result::MISC_ERROR;
diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h
index 9357397606..fc038ae731 100644
--- a/src/wallet/feebumper.h
+++ b/src/wallet/feebumper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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.
@@ -28,16 +28,6 @@ enum class Result
//! Return whether transaction can be bumped.
bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid);
-//! Create bumpfee transaction based on total amount.
-Result CreateTotalBumpTransaction(const CWallet* wallet,
- const uint256& txid,
- const CCoinControl& coin_control,
- CAmount total_fee,
- std::vector<std::string>& errors,
- CAmount& old_fee,
- CAmount& new_fee,
- CMutableTransaction& mtx);
-
//! Create bumpfee transaction based on feerate estimates.
Result CreateRateBumpTransaction(CWallet& wallet,
const uint256& txid,
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 2ebc9aba39..8688f3df5e 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -57,12 +57,11 @@ void WalletInit::AddWalletOptions() const
gArgs.AddArg("-salvagewallet", "Attempt to recover private keys from a corrupt wallet on startup", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
gArgs.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
gArgs.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);
- gArgs.AddArg("-upgradewallet", "Upgrade wallet to latest format on startup", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
gArgs.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);
gArgs.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
gArgs.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
- gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
+ gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes. %s in cmd is replaced by TxID and %w is replaced by wallet name. %w is not currently implemented on windows. On systems where %w is supported, it should NOT be quoted because this would break shell escaping used to invoke the command.", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#endif
gArgs.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
gArgs.AddArg("-zapwallettxes=<mode>", "Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup"
@@ -116,12 +115,6 @@ bool WalletInit::ParameterInteraction() const
}
}
- if (is_multiwallet) {
- if (gArgs.GetBoolArg("-upgradewallet", false)) {
- return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet"));
- }
- }
-
if (gArgs.GetBoolArg("-sysperms", false))
return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
index 071befaebf..0afd2dfcf0 100644
--- a/src/wallet/load.cpp
+++ b/src/wallet/load.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -66,19 +66,23 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal
bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
{
- for (const std::string& walletFile : wallet_files) {
- std::string error;
- std::vector<std::string> warnings;
- std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile), error, warnings);
- if (!warnings.empty()) chain.initWarning(Join(warnings, "\n"));
- if (!pwallet) {
- chain.initError(error);
- return false;
+ try {
+ for (const std::string& walletFile : wallet_files) {
+ std::string error;
+ std::vector<std::string> warnings;
+ std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile), error, warnings);
+ if (!warnings.empty()) chain.initWarning(Join(warnings, "\n"));
+ if (!pwallet) {
+ chain.initError(error);
+ return false;
+ }
+ AddWallet(pwallet);
}
- AddWallet(pwallet);
+ return true;
+ } catch (const std::runtime_error& e) {
+ chain.initError(e.what());
+ return false;
}
-
- return true;
}
void StartWallets(CScheduler& scheduler)
@@ -88,8 +92,8 @@ void StartWallets(CScheduler& scheduler)
}
// Schedule periodic wallet flushes and tx rebroadcasts
- scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
- scheduler.scheduleEvery(MaybeResendWalletTxs, 1000);
+ scheduler.scheduleEvery(MaybeCompactWalletDB, std::chrono::milliseconds{500});
+ scheduler.scheduleEvery(MaybeResendWalletTxs, std::chrono::milliseconds{1000});
}
void FlushWallets()
diff --git a/src/wallet/psbtwallet.cpp b/src/wallet/psbtwallet.cpp
deleted file mode 100644
index d995fb06d4..0000000000
--- a/src/wallet/psbtwallet.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2009-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 <wallet/psbtwallet.h>
-
-TransactionError FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs)
-{
- LOCK(pwallet->cs_wallet);
- // Get all of the previous transactions
- complete = true;
- for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
- const CTxIn& txin = psbtx.tx->vin[i];
- PSBTInput& input = psbtx.inputs.at(i);
-
- if (PSBTInputSigned(input)) {
- continue;
- }
-
- // Verify input looks sane. This will check that we have at most one uxto, witness or non-witness.
- if (!input.IsSane()) {
- return TransactionError::INVALID_PSBT;
- }
-
- // If we have no utxo, grab it from the wallet.
- if (!input.non_witness_utxo && input.witness_utxo.IsNull()) {
- const uint256& txhash = txin.prevout.hash;
- const auto it = pwallet->mapWallet.find(txhash);
- if (it != pwallet->mapWallet.end()) {
- const CWalletTx& wtx = it->second;
- // We only need the non_witness_utxo, which is a superset of the witness_utxo.
- // The signing code will switch to the smaller witness_utxo if this is ok.
- input.non_witness_utxo = wtx.tx;
- }
- }
-
- // Get the Sighash type
- if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
- return TransactionError::SIGHASH_MISMATCH;
- }
-
- // Get the scriptPubKey to know which SigningProvider to use
- CScript script;
- if (!input.witness_utxo.IsNull()) {
- script = input.witness_utxo.scriptPubKey;
- } else if (input.non_witness_utxo) {
- if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
- return TransactionError::MISSING_INPUTS;
- }
- script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey;
- } else {
- // There's no UTXO so we can just skip this now
- complete = false;
- continue;
- }
- SignatureData sigdata;
- input.FillSignatureData(sigdata);
- std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(script, sigdata);
- if (!provider) {
- complete = false;
- continue;
- }
-
- complete &= SignPSBTInput(HidingSigningProvider(provider.get(), !sign, !bip32derivs), psbtx, i, sighash_type);
- }
-
- // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
- for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
- const CTxOut& out = psbtx.tx->vout.at(i);
- std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(out.scriptPubKey);
- if (provider) {
- UpdatePSBTOutput(HidingSigningProvider(provider.get(), true, !bip32derivs), psbtx, i);
- }
- }
-
- return TransactionError::OK;
-}
diff --git a/src/wallet/psbtwallet.h b/src/wallet/psbtwallet.h
deleted file mode 100644
index b35a0a58d1..0000000000
--- a/src/wallet/psbtwallet.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2009-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.
-
-#ifndef BITCOIN_WALLET_PSBTWALLET_H
-#define BITCOIN_WALLET_PSBTWALLET_H
-
-#include <psbt.h>
-#include <wallet/wallet.h>
-
-/**
- * Fills out a PSBT with information from the wallet. Fills in UTXOs if we have
- * them. Tries to sign if sign=true. Sets `complete` if the PSBT is now complete
- * (i.e. has all required signatures or signature-parts, and is ready to
- * finalize.) Sets `error` and returns false if something goes wrong.
- *
- * @param[in] pwallet pointer to a wallet
- * @param[in] psbtx PartiallySignedTransaction to fill in
- * @param[out] complete indicates whether the PSBT is now complete
- * @param[in] sighash_type the sighash type to use when signing (if PSBT does not specify)
- * @param[in] sign whether to sign or not
- * @param[in] bip32derivs whether to fill in bip32 derivation information if available
- * return error
- */
-NODISCARD TransactionError FillPSBT(const CWallet* pwallet,
- PartiallySignedTransaction& psbtx,
- bool& complete,
- int sighash_type = 1 /* SIGHASH_ALL */,
- bool sign = true,
- bool bip32derivs = false);
-
-#endif // BITCOIN_WALLET_PSBTWALLET_H
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index b730d4a4dd..c863d22530 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -28,6 +28,8 @@
+using interfaces::FoundBlock;
+
std::string static EncodeDumpString(const std::string &str) {
std::stringstream ret;
for (const unsigned char c : str) {
@@ -54,18 +56,19 @@ static std::string DecodeDumpString(const std::string &str) {
return ret.str();
}
-static bool GetWalletAddressesForKey(LegacyScriptPubKeyMan* spk_man, CWallet* const pwallet, const CKeyID& keyid, std::string& strAddr, std::string& strLabel) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
+static bool GetWalletAddressesForKey(LegacyScriptPubKeyMan* spk_man, const CWallet* const pwallet, const CKeyID& keyid, std::string& strAddr, std::string& strLabel) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
bool fLabelFound = false;
CKey key;
spk_man->GetKey(keyid, key);
for (const auto& dest : GetAllDestinationsForKey(key.GetPubKey())) {
- if (pwallet->mapAddressBook.count(dest)) {
+ const auto* address_book_entry = pwallet->FindAddressBookEntry(dest);
+ if (address_book_entry) {
if (!strAddr.empty()) {
strAddr += ",";
}
strAddr += EncodeDestination(dest);
- strLabel = EncodeDumpString(pwallet->mapAddressBook[dest].name);
+ strLabel = EncodeDumpString(address_book_entry->GetLabel());
fLabelFound = true;
}
}
@@ -106,7 +109,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
{"label", RPCArg::Type::STR, /* default */ "current label if address exists, otherwise \"\"", "An optional label"},
{"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
"\nDump a private key\n"
+ HelpExampleCli("dumpprivkey", "\"myaddress\"") +
@@ -127,10 +130,9 @@ UniValue importprivkey(const JSONRPCRequest& request)
EnsureLegacyScriptPubKeyMan(*wallet, true);
- WalletRescanReserver reserver(pwallet);
+ WalletRescanReserver reserver(*pwallet);
bool fRescan = true;
{
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -168,7 +170,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
// label all new addresses, and label existing addresses if a
// label was passed.
for (const auto& dest : GetAllDestinationsForKey(pubkey)) {
- if (!request.params[1].isNull() || pwallet->mapAddressBook.count(dest) == 0) {
+ if (!request.params[1].isNull() || !pwallet->FindAddressBookEntry(dest)) {
pwallet->SetAddressBook(dest, strLabel, "receive");
}
}
@@ -203,7 +205,7 @@ UniValue abortrescan(const JSONRPCRequest& request)
"\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n"
"Note: Use \"getwalletinfo\" to query the scanning progress.\n",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::BOOL, "", "Whether the abort was successful"},
RPCExamples{
"\nImport a private key\n"
+ HelpExampleCli("importprivkey", "\"mykey\"") +
@@ -242,7 +244,7 @@ UniValue importaddress(const JSONRPCRequest& request)
{"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"},
{"p2sh", RPCArg::Type::BOOL, /* default */ "false", "Add the P2SH version of the script as well"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
"\nImport an address with rescan\n"
+ HelpExampleCli("importaddress", "\"myaddress\"") +
@@ -271,7 +273,7 @@ UniValue importaddress(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled when blocks are pruned");
}
- WalletRescanReserver reserver(pwallet);
+ WalletRescanReserver reserver(*pwallet);
if (fRescan && !reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}
@@ -282,7 +284,6 @@ UniValue importaddress(const JSONRPCRequest& request)
fP2SH = request.params[3].get_bool();
{
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
CTxDestination dest = DecodeDestination(request.params[0].get_str());
@@ -314,7 +315,6 @@ UniValue importaddress(const JSONRPCRequest& request)
{
RescanWallet(*pwallet, reserver);
{
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
pwallet->ReacceptWalletTransactions();
}
@@ -337,7 +337,7 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
{"rawtransaction", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A raw transaction in hex funding an already-existing address in wallet"},
{"txoutproof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex output from gettxoutproof that contains the transaction"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{""},
}.Check(request);
@@ -358,9 +358,9 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Something wrong with merkleblock");
}
- auto locked_chain = pwallet->chain().lock();
- Optional<int> height = locked_chain->getBlockHeight(merkleBlock.header.GetHash());
- if (height == nullopt) {
+ LOCK(pwallet->cs_wallet);
+ int height;
+ if (!pwallet->chain().findAncestorByHash(pwallet->GetLastBlockHash(), merkleBlock.header.GetHash(), FoundBlock().height(height))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
}
@@ -371,11 +371,9 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
unsigned int txnIndex = vIndex[it - vMatch.begin()];
- CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, *height, merkleBlock.header.GetHash(), txnIndex);
+ CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, height, merkleBlock.header.GetHash(), txnIndex);
wtx.m_confirm = confirm;
- LOCK(pwallet->cs_wallet);
-
if (pwallet->IsMine(*wtx.tx)) {
pwallet->AddToWallet(wtx, false);
return NullUniValue;
@@ -397,7 +395,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
{
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded id of the transaction you are deleting"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
"\nAs a JSON-RPC call\n"
@@ -405,7 +403,6 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
},
}.Check(request);
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
uint256 hash(ParseHashV(request.params[0], "txid"));
@@ -443,7 +440,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
{"label", RPCArg::Type::STR, /* default */ "\"\"", "An optional label"},
{"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
"\nImport a public key with rescan\n"
+ HelpExampleCli("importpubkey", "\"mypubkey\"") +
@@ -472,7 +469,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled when blocks are pruned");
}
- WalletRescanReserver reserver(pwallet);
+ WalletRescanReserver reserver(*pwallet);
if (fRescan && !reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}
@@ -485,7 +482,6 @@ UniValue importpubkey(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
{
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
std::set<CScript> script_pub_keys;
@@ -503,7 +499,6 @@ UniValue importpubkey(const JSONRPCRequest& request)
{
RescanWallet(*pwallet, reserver);
{
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
pwallet->ReacceptWalletTransactions();
}
@@ -527,7 +522,7 @@ UniValue importwallet(const JSONRPCRequest& request)
{
{"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet file"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
"\nDump the wallet\n"
+ HelpExampleCli("dumpwallet", "\"test\"") +
@@ -547,7 +542,7 @@ UniValue importwallet(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled when blocks are pruned");
}
- WalletRescanReserver reserver(pwallet);
+ WalletRescanReserver reserver(*pwallet);
if (!reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}
@@ -555,7 +550,6 @@ UniValue importwallet(const JSONRPCRequest& request)
int64_t nTimeBegin = 0;
bool fGood = true;
{
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -565,8 +559,7 @@ UniValue importwallet(const JSONRPCRequest& request)
if (!file.is_open()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
}
- Optional<int> tip_height = locked_chain->getHeight();
- nTimeBegin = tip_height ? locked_chain->getBlockTime(*tip_height) : 0;
+ CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(nTimeBegin)));
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
file.seekg(0, file.beg);
@@ -676,7 +669,7 @@ UniValue importwallet(const JSONRPCRequest& request)
UniValue dumpprivkey(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -688,7 +681,7 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for the private key"},
},
RPCResult{
- "\"key\" (string) The private key\n"
+ RPCResult::Type::STR, "key", "The private key"
},
RPCExamples{
HelpExampleCli("dumpprivkey", "\"myaddress\"")
@@ -699,7 +692,6 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*wallet);
- auto locked_chain = pwallet->chain().lock();
LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
EnsureWalletIsUnlocked(pwallet);
@@ -723,9 +715,8 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
UniValue dumpwallet(const JSONRPCRequest& request)
{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
+ std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet.get(), request.fHelp)) {
return NullUniValue;
}
@@ -735,12 +726,13 @@ UniValue dumpwallet(const JSONRPCRequest& request)
"Note that if your wallet contains keys which are not derived from your HD seed (e.g. imported keys), these are not covered by\n"
"only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n",
{
- {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The filename with path (either absolute or relative to bitcoind)"},
+ {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The filename with path (absolute path recommended)"},
},
RPCResult{
- "{ (json object)\n"
- " \"filename\" : { (string) The filename with full absolute path\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "filename", "The filename with full absolute path"},
+ }
},
RPCExamples{
HelpExampleCli("dumpwallet", "\"test\"")
@@ -748,12 +740,16 @@ UniValue dumpwallet(const JSONRPCRequest& request)
},
}.Check(request);
- LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*wallet);
+ CWallet& wallet = *pwallet;
+ LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(wallet);
+
+ // 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
+ wallet.BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
- EnsureWalletIsUnlocked(pwallet);
+ EnsureWalletIsUnlocked(&wallet);
fs::path filepath = request.params[0].get_str();
filepath = fs::absolute(filepath);
@@ -774,7 +770,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
std::map<CKeyID, int64_t> mapKeyBirth;
const std::map<CKeyID, int64_t>& mapKeyPool = spk_man.GetAllReserveKeys();
- pwallet->GetKeyBirthTimes(*locked_chain, mapKeyBirth);
+ pwallet->GetKeyBirthTimes(mapKeyBirth);
std::set<CScriptID> scripts = spk_man.GetCScripts();
@@ -789,9 +785,10 @@ UniValue dumpwallet(const JSONRPCRequest& request)
// produce output
file << strprintf("# Wallet dump created by Bitcoin %s\n", CLIENT_BUILD);
file << strprintf("# * Created on %s\n", FormatISO8601DateTime(GetTime()));
- const Optional<int> tip_height = locked_chain->getHeight();
- file << strprintf("# * Best block at time of backup was %i (%s),\n", tip_height.get_value_or(-1), tip_height ? locked_chain->getBlockHash(*tip_height).ToString() : "(missing block hash)");
- file << strprintf("# mined on %s\n", tip_height ? FormatISO8601DateTime(locked_chain->getBlockTime(*tip_height)) : "(missing block time)");
+ file << strprintf("# * Best block at time of backup was %i (%s),\n", wallet.GetLastBlockHeight(), wallet.GetLastBlockHash().ToString());
+ int64_t block_time = 0;
+ CHECK_NONFATAL(wallet.chain().findBlock(wallet.GetLastBlockHash(), FoundBlock().time(block_time)));
+ file << strprintf("# mined on %s\n", FormatISO8601DateTime(block_time));
file << "\n";
// add the base58check encoded extended master if the wallet uses HD
@@ -814,8 +811,8 @@ UniValue dumpwallet(const JSONRPCRequest& request)
CKey key;
if (spk_man.GetKey(keyid, key)) {
file << strprintf("%s %s ", EncodeSecret(key), strTime);
- if (GetWalletAddressesForKey(&spk_man, pwallet, keyid, strAddr, strLabel)) {
- file << strprintf("label=%s", strLabel);
+ if (GetWalletAddressesForKey(&spk_man, &wallet, keyid, strAddr, strLabel)) {
+ file << strprintf("label=%s", strLabel);
} else if (keyid == seed_id) {
file << "hdseed=1";
} else if (mapKeyPool.count(keyid)) {
@@ -1321,8 +1318,21 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
"\"options\""},
},
RPCResult{
- "\nResponse is an array with the same size as the input that has the execution result :\n"
- " [{\"success\": true}, {\"success\": true, \"warnings\": [\"Ignoring irrelevant private key\"]}, {\"success\": false, \"error\": {\"code\": -1, \"message\": \"Internal Server Error\"}}, ...]\n"
+ RPCResult::Type::ARR, "", "Response is an array with the same size as the input that has the execution result",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "success", ""},
+ {RPCResult::Type::ARR, "warnings", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR, "", ""},
+ }},
+ {RPCResult::Type::OBJ, "error", /* optional */ true, "",
+ {
+ {RPCResult::Type::ELISION, "", "JSONRPC error"},
+ }},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
@@ -1349,7 +1359,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
}
}
- WalletRescanReserver reserver(pwallet);
+ WalletRescanReserver reserver(*pwallet);
if (fRescan && !reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}
@@ -1359,25 +1369,17 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
int64_t nLowestTimestamp = 0;
UniValue response(UniValue::VARR);
{
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
// Verify all timestamps are present before importing any keys.
- const Optional<int> tip_height = locked_chain->getHeight();
- now = tip_height ? locked_chain->getBlockMedianTimePast(*tip_height) : 0;
+ CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(nLowestTimestamp).mtpTime(now)));
for (const UniValue& data : requests.getValues()) {
GetImportTimestamp(data, now);
}
const int64_t minimumTimestamp = 1;
- if (fRescan && tip_height) {
- nLowestTimestamp = locked_chain->getBlockTime(*tip_height);
- } else {
- fRescan = false;
- }
-
for (const UniValue& data : requests.getValues()) {
const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp);
const UniValue result = ProcessImport(pwallet, data, timestamp);
@@ -1401,7 +1403,6 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
if (fRescan && fRunScan && requests.size()) {
int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */);
{
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
pwallet->ReacceptWalletTransactions();
}
@@ -1445,3 +1446,295 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
return response;
}
+
+static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
+{
+ UniValue warnings(UniValue::VARR);
+ UniValue result(UniValue::VOBJ);
+
+ try {
+ if (!data.exists("desc")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Descriptor not found.");
+ }
+
+ const std::string& descriptor = data["desc"].get_str();
+ const bool active = data.exists("active") ? data["active"].get_bool() : false;
+ const bool internal = data.exists("internal") ? data["internal"].get_bool() : false;
+ const std::string& label = data.exists("label") ? data["label"].get_str() : "";
+
+ // Parse descriptor string
+ FlatSigningProvider keys;
+ std::string error;
+ auto parsed_desc = Parse(descriptor, keys, error, /* require_checksum = */ true);
+ if (!parsed_desc) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
+ }
+
+ // Range check
+ int64_t range_start = 0, range_end = 1, next_index = 0;
+ if (!parsed_desc->IsRange() && data.exists("range")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for an un-ranged descriptor");
+ } else if (parsed_desc->IsRange()) {
+ if (data.exists("range")) {
+ auto range = ParseDescriptorRange(data["range"]);
+ range_start = range.first;
+ range_end = range.second + 1; // Specified range end is inclusive, but we need range end as exclusive
+ } else {
+ warnings.push_back("Range not given, using default keypool range");
+ range_start = 0;
+ range_end = gArgs.GetArg("-keypool", DEFAULT_KEYPOOL_SIZE);
+ }
+ next_index = range_start;
+
+ if (data.exists("next_index")) {
+ next_index = data["next_index"].get_int64();
+ // bound checks
+ if (next_index < range_start || next_index >= range_end) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "next_index is out of range");
+ }
+ }
+ }
+
+ // Active descriptors must be ranged
+ if (active && !parsed_desc->IsRange()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Active descriptors must be ranged");
+ }
+
+ // Ranged descriptors should not have a label
+ if (data.exists("range") && data.exists("label")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptors should not have a label");
+ }
+
+ // Internal addresses should not have a label either
+ if (internal && data.exists("label")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal addresses should not have a label");
+ }
+
+ // Combo descriptor check
+ if (active && !parsed_desc->IsSingleType()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Combo descriptors cannot be set to active");
+ }
+
+ // If the wallet disabled private keys, abort if private keys exist
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.keys.empty()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
+ }
+
+ // 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);
+ parsed_desc->ExpandPrivate(0, keys, expand_keys);
+
+ // Check if all private keys are provided
+ bool have_all_privkeys = !expand_keys.keys.empty();
+ for (const auto& entry : expand_keys.origins) {
+ const CKeyID& key_id = entry.first;
+ CKey key;
+ if (!expand_keys.GetKey(key_id, key)) {
+ have_all_privkeys = false;
+ break;
+ }
+ }
+
+ // If private keys are enabled, check some things.
+ if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ if (keys.keys.empty()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import descriptor without private keys to a wallet with private keys enabled");
+ }
+ if (!have_all_privkeys) {
+ warnings.push_back("Not all private keys provided. Some wallet functionality may return unexpected errors");
+ }
+ }
+
+ WalletDescriptor w_desc(std::move(parsed_desc), timestamp, range_start, range_end, next_index);
+
+ // Check if the wallet already contains the descriptor
+ auto existing_spk_manager = pwallet->GetDescriptorScriptPubKeyMan(w_desc);
+ if (existing_spk_manager) {
+ LOCK(existing_spk_manager->cs_desc_man);
+ if (range_start > existing_spk_manager->GetWalletDescriptor().range_start) {
+ throw JSONRPCError(RPC_INVALID_PARAMS, strprintf("range_start can only decrease; current range = [%d,%d]", existing_spk_manager->GetWalletDescriptor().range_start, existing_spk_manager->GetWalletDescriptor().range_end));
+ }
+ }
+
+ // Add descriptor to the wallet
+ auto spk_manager = pwallet->AddWalletDescriptor(w_desc, keys, label);
+ if (spk_manager == nullptr) {
+ throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Could not add descriptor '%s'", descriptor));
+ }
+
+ // Set descriptor as active if necessary
+ if (active) {
+ if (!w_desc.descriptor->GetOutputType()) {
+ warnings.push_back("Unknown output type, cannot set descriptor to active.");
+ } else {
+ pwallet->SetActiveScriptPubKeyMan(spk_manager->GetID(), *w_desc.descriptor->GetOutputType(), internal);
+ }
+ }
+
+ result.pushKV("success", UniValue(true));
+ } catch (const UniValue& e) {
+ result.pushKV("success", UniValue(false));
+ result.pushKV("error", e);
+ } catch (...) {
+ result.pushKV("success", UniValue(false));
+
+ result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, "Missing required fields"));
+ }
+ if (warnings.size()) result.pushKV("warnings", warnings);
+ return result;
+}
+
+UniValue importdescriptors(const JSONRPCRequest& main_request) {
+ // Acquire the wallet
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(main_request);
+ CWallet* const pwallet = wallet.get();
+ if (!EnsureWalletIsAvailable(pwallet, main_request.fHelp)) {
+ return NullUniValue;
+ }
+
+ RPCHelpMan{"importdescriptors",
+ "\nImport descriptors. This will trigger a rescan of the blockchain based on the earliest timestamp of all descriptors being imported. Requires a new wallet backup.\n"
+ "\nNote: This call can take over an hour to complete if using an early timestamp; during that time, other rpc calls\n"
+ "may report that the imported keys, addresses or scripts exist but related transactions are still missing.\n",
+ {
+ {"requests", RPCArg::Type::ARR, RPCArg::Optional::NO, "Data to be imported",
+ {
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "Descriptor to import."},
+ {"active", RPCArg::Type::BOOL, /* default */ "false", "Set this descriptor to be the active descriptor for the corresponding output type/externality"},
+ {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED, "If a ranged descriptor is used, this specifies the end or the range (in the form [begin,end]) to import"},
+ {"next_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If a ranged descriptor is set to active, this specifies the next index to generate addresses from"},
+ {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Time from which to start rescanning the blockchain for this descriptor, in " + UNIX_EPOCH_TIME + "\n"
+ " Use the string \"now\" to substitute the current synced blockchain time.\n"
+ " \"now\" can be specified to bypass scanning, for outputs which are known to never have been used, and\n"
+ " 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest timestamp\n"
+ " of all descriptors being imported will be scanned.",
+ /* oneline_description */ "", {"timestamp | \"now\"", "integer / string"}
+ },
+ {"internal", RPCArg::Type::BOOL, /* default */ "false", "Whether matching outputs should be treated as not incoming payments (e.g. change)"},
+ {"label", RPCArg::Type::STR, /* default */ "''", "Label to assign to the address, only allowed with internal=false"},
+ },
+ },
+ },
+ "\"requests\""},
+ },
+ RPCResult{
+ RPCResult::Type::ARR, "", "Response is an array with the same size as the input that has the execution result",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "success", ""},
+ {RPCResult::Type::ARR, "warnings", /* optional */ true, "",
+ {
+ {RPCResult::Type::STR, "", ""},
+ }},
+ {RPCResult::Type::OBJ, "error", /* optional */ true, "",
+ {
+ {RPCResult::Type::ELISION, "", "JSONRPC error"},
+ }},
+ }},
+ }
+ },
+ RPCExamples{
+ HelpExampleCli("importdescriptors", "'[{ \"desc\": \"<my descriptor>\", \"timestamp\":1455191478, \"internal\": true }, "
+ "{ \"desc\": \"<my desccriptor 2>\", \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
+ HelpExampleCli("importdescriptors", "'[{ \"desc\": \"<my descriptor>\", \"timestamp\":1455191478, \"active\": true, \"range\": [0,100], \"label\": \"<my bech32 wallet>\" }]'")
+ },
+ }.Check(main_request);
+
+ // Make sure wallet is a descriptor wallet
+ if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "importdescriptors is not available for non-descriptor wallets");
+ }
+
+ RPCTypeCheck(main_request.params, {UniValue::VARR, UniValue::VOBJ});
+
+ WalletRescanReserver reserver(*pwallet);
+ if (!reserver.reserve()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
+ }
+
+ const UniValue& requests = main_request.params[0];
+ const int64_t minimum_timestamp = 1;
+ int64_t now = 0;
+ int64_t lowest_timestamp = 0;
+ bool rescan = false;
+ UniValue response(UniValue::VARR);
+ {
+ LOCK(pwallet->cs_wallet);
+ EnsureWalletIsUnlocked(pwallet);
+
+ CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(lowest_timestamp).mtpTime(now)));
+
+ // Get all timestamps and extract the lowest timestamp
+ for (const UniValue& request : requests.getValues()) {
+ // This throws an error if "timestamp" doesn't exist
+ const int64_t timestamp = std::max(GetImportTimestamp(request, now), minimum_timestamp);
+ const UniValue result = ProcessDescriptorImport(pwallet, request, timestamp);
+ response.push_back(result);
+
+ if (lowest_timestamp > timestamp ) {
+ lowest_timestamp = timestamp;
+ }
+
+ // If we know the chain tip, and at least one request was successful then allow rescan
+ if (!rescan && result["success"].get_bool()) {
+ rescan = true;
+ }
+ }
+ pwallet->ConnectScriptPubKeyManNotifiers();
+ }
+
+ // Rescan the blockchain using the lowest timestamp
+ if (rescan) {
+ int64_t scanned_time = pwallet->RescanFromTime(lowest_timestamp, reserver, true /* update */);
+ {
+ LOCK(pwallet->cs_wallet);
+ pwallet->ReacceptWalletTransactions();
+ }
+
+ if (pwallet->IsAbortingRescan()) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
+ }
+
+ if (scanned_time > lowest_timestamp) {
+ std::vector<UniValue> results = response.getValues();
+ response.clear();
+ response.setArray();
+
+ // Compose the response
+ for (unsigned int i = 0; i < requests.size(); ++i) {
+ const UniValue& request = requests.getValues().at(i);
+
+ // If the descriptor timestamp is within the successfully scanned
+ // range, or if the import result already has an error set, let
+ // the result stand unmodified. Otherwise replace the result
+ // with an error message.
+ if (scanned_time <= GetImportTimestamp(request, now) || results.at(i).exists("error")) {
+ response.push_back(results.at(i));
+ } else {
+ UniValue result = UniValue(UniValue::VOBJ);
+ result.pushKV("success", UniValue(false));
+ result.pushKV(
+ "error",
+ JSONRPCError(
+ RPC_MISC_ERROR,
+ strprintf("Rescan failed for descriptor with timestamp %d. There was an error reading a "
+ "block from time %d, which is after or within %d seconds of key creation, and "
+ "could contain transactions pertaining to the desc. As a result, transactions "
+ "and coins using this desc may not appear in the wallet. This error could be "
+ "caused by pruning or data corruption (see bitcoind log for details) and could "
+ "be dealt with by downloading and rescanning the relevant blocks (see -reindex "
+ "and -rescan options).",
+ GetImportTimestamp(request, now), scanned_time - TIMESTAMP_WINDOW - 1, TIMESTAMP_WINDOW)));
+ response.push_back(std::move(result));
+ }
+ }
+ }
+ }
+
+ return response;
+}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index ab0819a821..91162d575d 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -19,14 +19,14 @@
#include <script/sign.h>
#include <util/bip32.h>
#include <util/fees.h>
+#include <util/message.h> // For MessageSign()
#include <util/moneystr.h>
#include <util/string.h>
#include <util/system.h>
#include <util/url.h>
-#include <util/validation.h>
+#include <util/vector.h>
#include <wallet/coincontrol.h>
#include <wallet/feebumper.h>
-#include <wallet/psbtwallet.h>
#include <wallet/rpcwallet.h>
#include <wallet/wallet.h>
#include <wallet/walletdb.h>
@@ -37,9 +37,12 @@
#include <univalue.h>
+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 inline bool GetAvoidReuseFlag(CWallet * const pwallet, const UniValue& param) {
+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();
@@ -77,9 +80,9 @@ bool HaveKey(const SigningProvider& wallet, const CKey& key)
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name)
{
- if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
+ if (URL_DECODE && request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
// wallet endpoint was used
- wallet_name = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
+ wallet_name = URL_DECODE(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
return true;
}
return false;
@@ -98,13 +101,6 @@ std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& reques
return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr;
}
-std::string HelpRequiringPassphrase(const CWallet* pwallet)
-{
- return pwallet && pwallet->IsCrypted()
- ? "\nRequires wallet passphrase to be set with walletpassphrase call."
- : "";
-}
-
bool EnsureWalletIsAvailable(const CWallet* pwallet, bool avoidException)
{
if (pwallet) return true;
@@ -137,7 +133,7 @@ LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_cr
return *spk_man;
}
-static void WalletTxToJSON(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx, UniValue& entry)
+static void WalletTxToJSON(interfaces::Chain& chain, const CWalletTx& wtx, UniValue& entry)
{
int confirms = wtx.GetDepthInMainChain();
entry.pushKV("confirmations", confirms);
@@ -149,11 +145,10 @@ static void WalletTxToJSON(interfaces::Chain& chain, interfaces::Chain::Lock& lo
entry.pushKV("blockheight", wtx.m_confirm.block_height);
entry.pushKV("blockindex", wtx.m_confirm.nIndex);
int64_t block_time;
- bool found_block = chain.findBlock(wtx.m_confirm.hashBlock, nullptr /* block */, &block_time);
- CHECK_NONFATAL(found_block);
+ CHECK_NONFATAL(chain.findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(block_time)));
entry.pushKV("blocktime", block_time);
} else {
- entry.pushKV("trusted", wtx.IsTrusted(locked_chain));
+ entry.pushKV("trusted", wtx.IsTrusted());
}
uint256 hash = wtx.GetHash();
entry.pushKV("txid", hash.GetHex());
@@ -205,7 +200,7 @@ static UniValue getnewaddress(const JSONRPCRequest& request)
{"address_type", RPCArg::Type::STR, /* default */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
},
RPCResult{
- "\"address\" (string) The new bitcoin address\n"
+ RPCResult::Type::STR, "address", "The new bitcoin address"
},
RPCExamples{
HelpExampleCli("getnewaddress", "")
@@ -256,7 +251,7 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request)
{"address_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
},
RPCResult{
- "\"address\" (string) The address\n"
+ RPCResult::Type::STR, "address", "The address"
},
RPCExamples{
HelpExampleCli("getrawchangeaddress", "")
@@ -301,10 +296,10 @@ static UniValue setlabel(const JSONRPCRequest& request)
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to be associated with a label."},
{"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label to assign to the address."},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
- HelpExampleCli("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"")
- + HelpExampleRpc("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")
+ HelpExampleCli("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\" \"tabby\"")
+ + HelpExampleRpc("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\", \"tabby\"")
},
}.Check(request);
@@ -327,7 +322,7 @@ static UniValue setlabel(const JSONRPCRequest& request)
}
-static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue)
+static CTransactionRef SendMoney(CWallet* const pwallet, const CTxDestination& address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue)
{
CAmount curBalance = pwallet->GetBalance(0, coin_control.m_avoid_address_reuse).m_mine_trusted;
@@ -342,14 +337,14 @@ static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet
CScript scriptPubKey = GetScriptForDestination(address);
// Create and send the transaction
- CAmount nFeeRequired;
+ CAmount nFeeRequired = 0;
std::string strError;
std::vector<CRecipient> vecSend;
int nChangePosRet = -1;
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
CTransactionRef tx;
- if (!pwallet->CreateTransaction(locked_chain, vecSend, tx, nFeeRequired, nChangePosRet, strError, coin_control)) {
+ if (!pwallet->CreateTransaction(vecSend, tx, nFeeRequired, nChangePosRet, strError, coin_control)) {
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
throw JSONRPCError(RPC_WALLET_ERROR, strError);
@@ -369,7 +364,7 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
RPCHelpMan{"sendtoaddress",
"\nSend an amount to a given address." +
- HelpRequiringPassphrase(pwallet) + "\n",
+ HELP_REQUIRING_PASSPHRASE,
{
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to send to."},
{"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The amount in " + CURRENCY_UNIT + " to send. eg 0.1"},
@@ -390,13 +385,13 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
" dirty if they have previously been used in a transaction."},
},
RPCResult{
- "\"txid\" (string) The transaction id.\n"
+ RPCResult::Type::STR_HEX, "txid", "The transaction id."
},
RPCExamples{
- HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
- + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
- + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
- + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
+ 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")
+ + HelpExampleRpc("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 0.1, \"donation\", \"seans outpost\"")
},
}.Check(request);
@@ -404,7 +399,6 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
CTxDestination dest = DecodeDestination(request.params[0].get_str());
@@ -450,14 +444,14 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
- CTransactionRef tx = SendMoney(*locked_chain, pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue));
+ CTransactionRef tx = SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue));
return tx->GetHash().GetHex();
}
static UniValue listaddressgroupings(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -469,17 +463,18 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
"in past transactions\n",
{},
RPCResult{
- "[\n"
- " [\n"
- " [\n"
- " \"address\", (string) The bitcoin address\n"
- " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n"
- " \"label\" (string, optional) The label\n"
- " ]\n"
- " ,...\n"
- " ]\n"
- " ,...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::STR, "address", "The bitcoin address"},
+ {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
+ {RPCResult::Type::STR, "label", /* optional */ true, "The label"},
+ }},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("listaddressgroupings", "")
@@ -491,11 +486,10 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
UniValue jsonGroupings(UniValue::VARR);
- std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances(*locked_chain);
+ std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
for (const std::set<CTxDestination>& grouping : pwallet->GetAddressGroupings()) {
UniValue jsonGrouping(UniValue::VARR);
for (const CTxDestination& address : grouping)
@@ -504,8 +498,9 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
addressInfo.push_back(EncodeDestination(address));
addressInfo.push_back(ValueFromAmount(balances[address]));
{
- if (pwallet->mapAddressBook.find(address) != pwallet->mapAddressBook.end()) {
- addressInfo.push_back(pwallet->mapAddressBook.find(address)->second.name);
+ const auto* address_book_entry = pwallet->FindAddressBookEntry(address);
+ if (address_book_entry) {
+ addressInfo.push_back(address_book_entry->GetLabel());
}
}
jsonGrouping.push_back(addressInfo);
@@ -518,7 +513,7 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
static UniValue signmessage(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -526,13 +521,13 @@ static UniValue signmessage(const JSONRPCRequest& request)
RPCHelpMan{"signmessage",
"\nSign a message with the private key of an address" +
- HelpRequiringPassphrase(pwallet) + "\n",
+ HELP_REQUIRING_PASSPHRASE,
{
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the private key."},
{"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
},
RPCResult{
- "\"signature\" (string) The signature of the message encoded in base 64\n"
+ RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
},
RPCExamples{
"\nUnlock the wallet for 30 seconds\n"
@@ -546,7 +541,6 @@ static UniValue signmessage(const JSONRPCRequest& request)
},
}.Check(request);
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -564,33 +558,67 @@ static UniValue signmessage(const JSONRPCRequest& request)
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
}
- CScript script_pub_key = GetScriptForDestination(*pkhash);
- std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(script_pub_key);
- if (!provider) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
+ std::string signature;
+ SigningResult err = pwallet->SignMessage(strMessage, *pkhash, signature);
+ if (err == SigningResult::SIGNING_FAILED) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, SigningResultString(err));
+ } else if (err != SigningResult::OK){
+ throw JSONRPCError(RPC_WALLET_ERROR, SigningResultString(err));
}
- CKey key;
- CKeyID keyID(*pkhash);
- if (!provider->GetKey(keyID, key)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
+ return signature;
+}
+
+static CAmount GetReceived(const CWallet& wallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
+{
+ std::set<CTxDestination> address_set;
+
+ if (by_label) {
+ // Get the set of addresses assigned to label
+ std::string label = LabelFromValue(params[0]);
+ address_set = wallet.GetLabelAddresses(label);
+ } else {
+ // Get the address
+ CTxDestination dest = DecodeDestination(params[0].get_str());
+ if (!IsValidDestination(dest)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+ }
+ CScript script_pub_key = GetScriptForDestination(dest);
+ if (!wallet.IsMine(script_pub_key)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
+ }
+ address_set.insert(dest);
}
- CHashWriter ss(SER_GETHASH, 0);
- ss << strMessageMagic;
- ss << strMessage;
+ // Minimum confirmations
+ int min_depth = 1;
+ if (!params[1].isNull())
+ min_depth = params[1].get_int();
- std::vector<unsigned char> vchSig;
- if (!key.SignCompact(ss.GetHash(), vchSig))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
+ // Tally
+ CAmount amount = 0;
+ for (const std::pair<const uint256, CWalletTx>& wtx_pair : wallet.mapWallet) {
+ const CWalletTx& wtx = wtx_pair.second;
+ if (wtx.IsCoinBase() || !wallet.chain().checkFinalTx(*wtx.tx) || wtx.GetDepthInMainChain() < min_depth) {
+ continue;
+ }
+
+ for (const CTxOut& txout : wtx.tx->vout) {
+ CTxDestination address;
+ if (ExtractDestination(txout.scriptPubKey, address) && wallet.IsMine(address) && address_set.count(address)) {
+ amount += txout.nValue;
+ }
+ }
+ }
- return EncodeBase64(vchSig.data(), vchSig.size());
+ return amount;
}
+
static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -603,17 +631,17 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
{"minconf", RPCArg::Type::NUM, /* default */ "1", "Only include transactions confirmed at least this many times."},
},
RPCResult{
- "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
+ RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received at this address."
},
RPCExamples{
"\nThe amount from transactions with at least 1 confirmation\n"
- + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") +
+ + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
"\nThe amount including unconfirmed transactions, zero confirmations\n"
- + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 0") +
+ + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0") +
"\nThe amount with at least 6 confirmations\n"
- + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 6") +
+ + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 6") +
"\nAs a JSON-RPC call\n"
- + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")
+ + HelpExampleRpc("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 6")
},
}.Check(request);
@@ -621,46 +649,16 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
- // Bitcoin address
- CTxDestination dest = DecodeDestination(request.params[0].get_str());
- if (!IsValidDestination(dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
- }
- CScript scriptPubKey = GetScriptForDestination(dest);
- if (!pwallet->IsMine(scriptPubKey)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
- }
-
- // Minimum confirmations
- int nMinDepth = 1;
- if (!request.params[1].isNull())
- nMinDepth = request.params[1].get_int();
-
- // Tally
- CAmount nAmount = 0;
- for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
- const CWalletTx& wtx = pairWtx.second;
- if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) {
- continue;
- }
-
- for (const CTxOut& txout : wtx.tx->vout)
- if (txout.scriptPubKey == scriptPubKey)
- if (wtx.GetDepthInMainChain() >= nMinDepth)
- nAmount += txout.nValue;
- }
-
- return ValueFromAmount(nAmount);
+ return ValueFromAmount(GetReceived(*pwallet, request.params, /* by_label */ false));
}
static UniValue getreceivedbylabel(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -673,7 +671,7 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
{"minconf", RPCArg::Type::NUM, /* default */ "1", "Only include transactions confirmed at least this many times."},
},
RPCResult{
- "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this label.\n"
+ RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received for this label."
},
RPCExamples{
"\nAmount received by the default label with at least 1 confirmation\n"
@@ -691,44 +689,16 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
- // Minimum confirmations
- int nMinDepth = 1;
- if (!request.params[1].isNull())
- nMinDepth = request.params[1].get_int();
-
- // Get the set of pub keys assigned to label
- std::string label = LabelFromValue(request.params[0]);
- std::set<CTxDestination> setAddress = pwallet->GetLabelAddresses(label);
-
- // Tally
- CAmount nAmount = 0;
- for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
- const CWalletTx& wtx = pairWtx.second;
- if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) {
- continue;
- }
-
- for (const CTxOut& txout : wtx.tx->vout)
- {
- CTxDestination address;
- if (ExtractDestination(txout.scriptPubKey, address) && pwallet->IsMine(address) && setAddress.count(address)) {
- if (wtx.GetDepthInMainChain() >= nMinDepth)
- nAmount += txout.nValue;
- }
- }
- }
-
- return ValueFromAmount(nAmount);
+ return ValueFromAmount(GetReceived(*pwallet, request.params, /* by_label */ true));
}
static UniValue getbalance(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -745,12 +715,12 @@ static UniValue getbalance(const JSONRPCRequest& request)
{"avoid_reuse", RPCArg::Type::BOOL, /* default */ "true", "(only available if avoid_reuse wallet flag is set) Do not include balance in dirty outputs; addresses are considered dirty if they have previously been used in a transaction."},
},
RPCResult{
- "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this wallet.\n"
+ RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received for this wallet."
},
RPCExamples{
- "\nThe total amount in the wallet with 1 or more confirmations\n"
+ "\nThe total amount in the wallet with 0 or more confirmations\n"
+ HelpExampleCli("getbalance", "") +
- "\nThe total amount in the wallet at least 6 blocks confirmed\n"
+ "\nThe total amount in the wallet with at least 6 confirmations\n"
+ HelpExampleCli("getbalance", "\"*\" 6") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getbalance", "\"*\", 6")
@@ -761,7 +731,6 @@ static UniValue getbalance(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
const UniValue& dummy_value = request.params[0];
@@ -786,7 +755,7 @@ static UniValue getbalance(const JSONRPCRequest& request)
static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -795,7 +764,7 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
RPCHelpMan{"getunconfirmedbalance",
"DEPRECATED\nIdentical to getbalances().mine.untrusted_pending\n",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::NUM, "", "The balance"},
RPCExamples{""},
}.Check(request);
@@ -803,7 +772,6 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
return ValueFromAmount(pwallet->GetBalance().m_mine_untrusted_pending);
@@ -821,17 +789,17 @@ static UniValue sendmany(const JSONRPCRequest& request)
RPCHelpMan{"sendmany",
"\nSend multiple times. Amounts are double-precision floating point numbers." +
- HelpRequiringPassphrase(pwallet) + "\n",
+ HELP_REQUIRING_PASSPHRASE,
{
{"dummy", RPCArg::Type::STR, RPCArg::Optional::NO, "Must be set to \"\" for backwards compatibility.", "\"\""},
- {"amounts", RPCArg::Type::OBJ, RPCArg::Optional::NO, "A json object with addresses and amounts",
+ {"amounts", RPCArg::Type::OBJ, RPCArg::Optional::NO, "The addresses and amounts",
{
{"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"},
},
},
{"minconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Ignored dummy value"},
{"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment"},
- {"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array with addresses.\n"
+ {"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The addresses.\n"
" The fee will be equally deducted from the amount of each selected address.\n"
" Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
" If no addresses are specified here, the sender pays the fee.",
@@ -847,18 +815,18 @@ static UniValue sendmany(const JSONRPCRequest& request)
" \"CONSERVATIVE\""},
},
RPCResult{
- "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
- " the number of addresses.\n"
+ RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of\n"
+ "the number of addresses."
},
RPCExamples{
"\nSend two amounts to two different addresses:\n"
- + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
+ + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\"") +
"\nSend two amounts to two different addresses setting the confirmation and comment:\n"
- + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
+ + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\" 6 \"testing\"") +
"\nSend two amounts to two different addresses, subtract fee from amount:\n"
- + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
+ + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\" 1 \"\" \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") +
"\nAs a JSON-RPC call\n"
- + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"")
+ + HelpExampleRpc("sendmany", "\"\", {\"" + EXAMPLE_ADDRESS[0] + "\":0.01,\"" + EXAMPLE_ADDRESS[1] + "\":0.02}, 6, \"testing\"")
},
}.Check(request);
@@ -866,7 +834,6 @@ static UniValue sendmany(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
@@ -938,7 +905,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
int nChangePosRet = -1;
std::string strFailReason;
CTransactionRef tx;
- bool fCreated = pwallet->CreateTransaction(*locked_chain, vecSend, tx, nFeeRequired, nChangePosRet, strFailReason, coin_control);
+ bool fCreated = pwallet->CreateTransaction(vecSend, tx, nFeeRequired, nChangePosRet, strFailReason, coin_control);
if (!fCreated)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */);
@@ -962,7 +929,7 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
"If 'label' is specified, assign address to that label.\n",
{
{"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys or addresses."},
- {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of bitcoin addresses or hex-encoded public keys",
+ {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The bitcoin addresses or hex-encoded public keys",
{
{"key", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address or hex-encoded public key"},
},
@@ -971,22 +938,23 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
{"address_type", RPCArg::Type::STR, /* default */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
},
RPCResult{
- "{\n"
- " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
- " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "address", "The value of the new multisig address"},
+ {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script"},
+ {RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"},
+ }
},
RPCExamples{
"\nAdd a multisig address from 2 addresses\n"
- + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
+ + HelpExampleCli("addmultisigaddress", "2 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") +
"\nAs a JSON-RPC call\n"
- + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
+ + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
},
}.Check(request);
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet);
- auto locked_chain = pwallet->chain().lock();
LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
std::string label;
@@ -1018,9 +986,13 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, spk_man, inner);
pwallet->SetAddressBook(dest, label, "send");
+ // Make the descriptor
+ std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), spk_man);
+
UniValue result(UniValue::VOBJ);
result.pushKV("address", EncodeDestination(dest));
result.pushKV("redeemScript", HexStr(inner.begin(), inner.end()));
+ result.pushKV("descriptor", descriptor->ToString());
return result;
}
@@ -1035,7 +1007,7 @@ struct tallyitem
}
};
-static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
+static UniValue ListReceived(const CWallet* const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
// Minimum confirmations
int nMinDepth = 1;
@@ -1068,7 +1040,7 @@ static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * co
for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
const CWalletTx& wtx = pairWtx.second;
- if (wtx.IsCoinBase() || !locked_chain.checkFinalTx(*wtx.tx)) {
+ if (wtx.IsCoinBase() || !pwallet->chain().checkFinalTx(*wtx.tx)) {
continue;
}
@@ -1103,13 +1075,13 @@ static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * co
UniValue ret(UniValue::VARR);
std::map<std::string, tallyitem> label_tally;
- // Create mapAddressBook iterator
+ // Create m_address_book iterator
// If we aren't filtering, go from begin() to end()
- auto start = pwallet->mapAddressBook.begin();
- auto end = pwallet->mapAddressBook.end();
+ auto start = pwallet->m_address_book.begin();
+ auto end = pwallet->m_address_book.end();
// If we are filtering, find() the applicable entry
if (has_filtered_address) {
- start = pwallet->mapAddressBook.find(filtered_address);
+ start = pwallet->m_address_book.find(filtered_address);
if (start != end) {
end = std::next(start);
}
@@ -1117,8 +1089,9 @@ static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * co
for (auto item_it = start; item_it != end; ++item_it)
{
+ if (item_it->second.IsChange()) continue;
const CTxDestination& address = item_it->first;
- const std::string& label = item_it->second.name;
+ const std::string& label = item_it->second.GetLabel();
auto it = mapTally.find(address);
if (it == mapTally.end() && !fIncludeEmpty)
continue;
@@ -1184,7 +1157,7 @@ static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * co
static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -1199,26 +1172,27 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
{"address_filter", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If present, only return information on this address."},
},
RPCResult{
- "[\n"
- " {\n"
- " \"involvesWatchonly\" : true, (bool) Only returns true if imported addresses were involved in transaction.\n"
- " \"address\" : \"receivingaddress\", (string) The receiving address\n"
- " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
- " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
- " \"label\" : \"label\", (string) The label of the receiving address. The default label is \"\".\n"
- " \"txids\": [\n"
- " \"txid\", (string) The ids of transactions received with the address \n"
- " ...\n"
- " ]\n"
- " }\n"
- " ,...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction"},
+ {RPCResult::Type::STR, "address", "The receiving address"},
+ {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received by the address"},
+ {RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"},
+ {RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""},
+ {RPCResult::Type::ARR, "txids", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The ids of transactions received with the address"},
+ }},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("listreceivedbyaddress", "")
+ HelpExampleCli("listreceivedbyaddress", "6 true")
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true")
- + HelpExampleRpc("listreceivedbyaddress", "6, true, true, \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"")
+ + HelpExampleRpc("listreceivedbyaddress", "6, true, true, \"" + EXAMPLE_ADDRESS[0] + "\"")
},
}.Check(request);
@@ -1226,16 +1200,15 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
- return ListReceived(*locked_chain, pwallet, request.params, false);
+ return ListReceived(pwallet, request.params, false);
}
static UniValue listreceivedbylabel(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -1249,15 +1222,16 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request)
{"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Whether to include watch-only addresses (see 'importaddress')"},
},
RPCResult{
- "[\n"
- " {\n"
- " \"involvesWatchonly\" : true, (bool) Only returns true if imported addresses were involved in transaction.\n"
- " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this label\n"
- " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
- " \"label\" : \"label\" (string) The label of the receiving address. The default label is \"\".\n"
- " }\n"
- " ,...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction"},
+ {RPCResult::Type::STR_AMOUNT, "amount", "The total amount received by addresses with this label"},
+ {RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"},
+ {RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("listreceivedbylabel", "")
@@ -1270,10 +1244,9 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
- return ListReceived(*locked_chain, pwallet, request.params, true);
+ return ListReceived(pwallet, request.params, true);
}
static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
@@ -1294,7 +1267,7 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
* @param filter_ismine The "is mine" filter flags.
* @param filter_label Optional label string to filter incoming transactions.
*/
-static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
+static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
CAmount nFee;
std::list<COutputEntry> listReceived;
@@ -1316,13 +1289,14 @@ static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* con
MaybePushAddress(entry, s.destination);
entry.pushKV("category", "send");
entry.pushKV("amount", ValueFromAmount(-s.amount));
- if (pwallet->mapAddressBook.count(s.destination)) {
- entry.pushKV("label", pwallet->mapAddressBook[s.destination].name);
+ const auto* address_book_entry = pwallet->FindAddressBookEntry(s.destination);
+ if (address_book_entry) {
+ entry.pushKV("label", address_book_entry->GetLabel());
}
entry.pushKV("vout", s.vout);
entry.pushKV("fee", ValueFromAmount(-nFee));
if (fLong)
- WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry);
+ WalletTxToJSON(pwallet->chain(), wtx, entry);
entry.pushKV("abandoned", wtx.isAbandoned());
ret.push_back(entry);
}
@@ -1333,8 +1307,9 @@ static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* con
for (const COutputEntry& r : listReceived)
{
std::string label;
- if (pwallet->mapAddressBook.count(r.destination)) {
- label = pwallet->mapAddressBook[r.destination].name;
+ const auto* address_book_entry = pwallet->FindAddressBookEntry(r.destination);
+ if (address_book_entry) {
+ label = address_book_entry->GetLabel();
}
if (filter_label && label != *filter_label) {
continue;
@@ -1358,43 +1333,43 @@ static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* con
entry.pushKV("category", "receive");
}
entry.pushKV("amount", ValueFromAmount(r.amount));
- if (pwallet->mapAddressBook.count(r.destination)) {
+ if (address_book_entry) {
entry.pushKV("label", label);
}
entry.pushKV("vout", r.vout);
if (fLong)
- WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry);
+ WalletTxToJSON(pwallet->chain(), wtx, entry);
ret.push_back(entry);
}
}
}
-static const std::string TransactionDescriptionString()
+static const std::vector<RPCResult> TransactionDescriptionString()
{
- return " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Negative confirmations means the\n"
- " transaction conflicted that many blocks ago.\n"
- " \"generated\": xxx, (bool) Only present if transaction only input is a coinbase one.\n"
- " \"trusted\": xxx, (bool) Only present if we consider transaction to be trusted and so safe to spend from.\n"
- " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction.\n"
- " \"blockheight\": n, (numeric) The block height containing the transaction.\n"
- " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it.\n"
- " \"blocktime\": xxx, (numeric) The block time expressed in " + UNIX_EPOCH_TIME + ".\n"
- " \"txid\": \"transactionid\", (string) The transaction id.\n"
- " \"walletconflicts\": [ (array) Conflicting transaction ids.\n"
- " \"txid\", (string) The transaction id.\n"
- " ...\n"
- " ],\n"
- " \"time\": xxx, (numeric) The transaction time expressed in " + UNIX_EPOCH_TIME + ".\n"
- " \"timereceived\": xxx, (numeric) The time received expressed in " + UNIX_EPOCH_TIME + ".\n"
- " \"comment\": \"...\", (string) If a comment is associated with the transaction, only present if not empty.\n"
- " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
- " may be unknown for unconfirmed transactions not in the mempool\n";
+ return{{RPCResult::Type::NUM, "confirmations", "The number of confirmations for the transaction. Negative confirmations means the\n"
+ "transaction conflicted that many blocks ago."},
+ {RPCResult::Type::BOOL, "generated", "Only present if transaction only input is a coinbase one."},
+ {RPCResult::Type::BOOL, "trusted", "Only present if we consider transaction to be trusted and so safe to spend from."},
+ {RPCResult::Type::STR_HEX, "blockhash", "The block hash containing the transaction."},
+ {RPCResult::Type::NUM, "blockheight", "The block height containing the transaction."},
+ {RPCResult::Type::NUM, "blockindex", "The index of the transaction in the block that includes it."},
+ {RPCResult::Type::NUM_TIME, "blocktime", "The block time expressed in " + UNIX_EPOCH_TIME + "."},
+ {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
+ {RPCResult::Type::ARR, "walletconflicts", "Conflicting transaction ids.",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
+ }},
+ {RPCResult::Type::NUM_TIME, "time", "The transaction time expressed in " + UNIX_EPOCH_TIME + "."},
+ {RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."},
+ {RPCResult::Type::STR, "comment", "If a comment is associated with the transaction, only present if not empty."},
+ {RPCResult::Type::STR, "bip125-replaceable", "(\"yes|no|unknown\") Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
+ "may be unknown for unconfirmed transactions not in the mempool"}};
}
UniValue listtransactions(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -1404,34 +1379,38 @@ UniValue listtransactions(const JSONRPCRequest& request)
"\nIf a label name is provided, this will return only incoming transactions paying to addresses with the specified label.\n"
"\nReturns up to 'count' most recent transactions skipping the first 'from' transactions.\n",
{
- {"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, should be a valid label name to return only incoming transactions\n"
- " with the specified label, or \"*\" to disable filtering and return all transactions."},
+ {"label|dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, should be a valid label name to return only incoming transactions\n"
+ "with the specified label, or \"*\" to disable filtering and return all transactions."},
{"count", RPCArg::Type::NUM, /* default */ "10", "The number of transactions to return"},
{"skip", RPCArg::Type::NUM, /* default */ "0", "The number of transactions to skip"},
{"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Include transactions to watch-only addresses (see 'importaddress')"},
},
RPCResult{
- "[\n"
- " {\n"
- " \"involvesWatchonly\": xxx, (bool) Only returns true if imported addresses were involved in transaction.\n"
- " \"address\":\"address\", (string) The bitcoin address of the transaction.\n"
- " \"category\": (string) The transaction category.\n"
- " \"send\" Transactions sent.\n"
- " \"receive\" Non-coinbase transactions received.\n"
- " \"generate\" Coinbase transactions received with more than 100 confirmations.\n"
- " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
- " \"orphan\" Orphaned coinbase transactions received.\n"
- " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
- " for all other categories\n"
- " \"label\": \"label\", (string) A comment for the address/transaction, if any\n"
- " \"vout\": n, (numeric) the vout value\n"
- " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
- " 'send' category of transactions.\n"
- + TransactionDescriptionString()
- + " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
- " 'send' category of transactions.\n"
- " }\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
+ {
+ {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."},
+ {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
+ {RPCResult::Type::STR, "category", "The transaction category.\n"
+ "\"send\" Transactions sent.\n"
+ "\"receive\" Non-coinbase transactions received.\n"
+ "\"generate\" Coinbase transactions received with more than 100 confirmations.\n"
+ "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
+ "\"orphan\" Orphaned coinbase transactions received."},
+ {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
+ "for all other categories"},
+ {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"},
+ {RPCResult::Type::NUM, "vout", "the vout value"},
+ {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
+ "'send' category of transactions."},
+ },
+ TransactionDescriptionString()),
+ {
+ {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
+ "'send' category of transactions."},
+ })},
+ }
},
RPCExamples{
"\nList the most recent 10 transactions in the systems\n"
@@ -1474,7 +1453,6 @@ UniValue listtransactions(const JSONRPCRequest& request)
UniValue ret(UniValue::VARR);
{
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
const CWallet::TxItems & txOrdered = pwallet->wtxOrdered;
@@ -1483,7 +1461,7 @@ UniValue listtransactions(const JSONRPCRequest& request)
for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second;
- ListTransactions(*locked_chain, pwallet, *pwtx, 0, true, ret, filter, filter_label);
+ ListTransactions(pwallet, *pwtx, 0, true, ret, filter, filter_label);
if ((int)ret.size() >= (nCount+nFrom)) break;
}
}
@@ -1495,29 +1473,16 @@ UniValue listtransactions(const JSONRPCRequest& request)
if ((nFrom + nCount) > (int)ret.size())
nCount = ret.size() - nFrom;
- std::vector<UniValue> arrTmp = ret.getValues();
-
- std::vector<UniValue>::iterator first = arrTmp.begin();
- std::advance(first, nFrom);
- std::vector<UniValue>::iterator last = arrTmp.begin();
- std::advance(last, nFrom+nCount);
-
- if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
- if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
-
- std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
-
- ret.clear();
- ret.setArray();
- ret.push_backV(arrTmp);
-
- return ret;
+ const std::vector<UniValue>& txs = ret.getValues();
+ UniValue result{UniValue::VARR};
+ result.push_backV({ txs.rend() - nFrom - nCount, txs.rend() - nFrom }); // Return oldest to newest
+ return result;
}
static UniValue listsinceblock(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -1535,32 +1500,39 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
" (not guaranteed to work on pruned nodes)"},
},
RPCResult{
- "{\n"
- " \"transactions\": [\n"
- " \"involvesWatchonly\": xxx, (bool) Only returns true if imported addresses were involved in transaction.\n"
- " \"address\":\"address\", (string) The bitcoin address of the transaction.\n"
- " \"category\": (string) The transaction category.\n"
- " \"send\" Transactions sent.\n"
- " \"receive\" Non-coinbase transactions received.\n"
- " \"generate\" Coinbase transactions received with more than 100 confirmations.\n"
- " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
- " \"orphan\" Orphaned coinbase transactions received.\n"
- " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
- " for all other categories\n"
- " \"vout\" : n, (numeric) the vout value\n"
- " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n"
- + TransactionDescriptionString()
- + " \"abandoned\": xxx, (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions.\n"
- " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
- " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
- " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
- " ],\n"
- " \"removed\": [\n"
- " <structure is the same as \"transactions\" above, only present if include_removed=true>\n"
- " Note: transactions that were re-added in the active chain will appear as-is in this array, and may thus have a positive confirmation count.\n"
- " ],\n"
- " \"lastblock\": \"lastblockhash\" (string) The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::ARR, "transactions", "",
+ {
+ {RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
+ {
+ {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."},
+ {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
+ {RPCResult::Type::STR, "category", "The transaction category.\n"
+ "\"send\" Transactions sent.\n"
+ "\"receive\" Non-coinbase transactions received.\n"
+ "\"generate\" Coinbase transactions received with more than 100 confirmations.\n"
+ "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
+ "\"orphan\" Orphaned coinbase transactions received."},
+ {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
+ "for all other categories"},
+ {RPCResult::Type::NUM, "vout", "the vout value"},
+ {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
+ "'send' category of transactions."},
+ },
+ TransactionDescriptionString()),
+ {
+ {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
+ "'send' category of transactions."},
+ {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"},
+ {RPCResult::Type::STR, "to", "If a comment to is associated with the transaction."},
+ })},
+ }},
+ {RPCResult::Type::ARR, "removed", "<structure is the same as \"transactions\" above, only present if include_removed=true>\n"
+ "Note: transactions that were re-added in the active chain will appear as-is in this array, and may thus have a positive confirmation count."
+ , {{RPCResult::Type::ELISION, "", ""},}},
+ {RPCResult::Type::STR_HEX, "lastblock", "The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones"},
+ }
},
RPCExamples{
HelpExampleCli("listsinceblock", "")
@@ -1573,7 +1545,6 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
// The way the 'height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
@@ -1585,8 +1556,9 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
uint256 blockId;
if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
blockId = ParseHashV(request.params[0], "blockhash");
- height = locked_chain->findFork(blockId, &altheight);
- if (!height) {
+ height.emplace();
+ altheight.emplace();
+ if (!pwallet->chain().findCommonAncestor(blockId, pwallet->GetLastBlockHash(), /* ancestor out */ FoundBlock().height(*height), /* blockId out */ FoundBlock().height(*altheight))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
}
@@ -1605,8 +1577,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
- const Optional<int> tip_height = locked_chain->getHeight();
- int depth = tip_height && height ? (1 + *tip_height - *height) : -1;
+ int depth = height ? pwallet->GetLastBlockHeight() + 1 - *height : -1;
UniValue transactions(UniValue::VARR);
@@ -1614,7 +1585,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
CWalletTx tx = pairWtx.second;
if (depth == -1 || abs(tx.GetDepthInMainChain()) < depth) {
- ListTransactions(*locked_chain, pwallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
+ ListTransactions(pwallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
}
}
@@ -1623,7 +1594,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
UniValue removed(UniValue::VARR);
while (include_removed && altheight && *altheight > *height) {
CBlock block;
- if (!pwallet->chain().findBlock(blockId, &block) || block.IsNull()) {
+ if (!pwallet->chain().findBlock(blockId, FoundBlock().data(block)) || block.IsNull()) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
}
for (const CTransactionRef& tx : block.vtx) {
@@ -1631,15 +1602,15 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
if (it != pwallet->mapWallet.end()) {
// We want all transactions regardless of confirmation count to appear here,
// even negative confirmation ones, hence the big negative.
- ListTransactions(*locked_chain, pwallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
+ ListTransactions(pwallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
}
}
blockId = block.hashPrevBlock;
--*altheight;
}
- int last_height = tip_height ? *tip_height + 1 - target_confirms : -1;
- uint256 lastblock = last_height >= 0 ? locked_chain->getBlockHash(last_height) : uint256();
+ uint256 lastblock;
+ CHECK_NONFATAL(pwallet->chain().findAncestorByHeight(pwallet->GetLastBlockHash(), pwallet->GetLastBlockHeight() + 1 - target_confirms, FoundBlock().hash(lastblock)));
UniValue ret(UniValue::VOBJ);
ret.pushKV("transactions", transactions);
@@ -1652,7 +1623,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
static UniValue gettransaction(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -1668,35 +1639,41 @@ static UniValue gettransaction(const JSONRPCRequest& request)
"Whether to include a `decoded` field containing the decoded transaction (equivalent to RPC decoderawtransaction)"},
},
RPCResult{
- "{\n"
- " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
- " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
- " 'send' category of transactions.\n"
- + TransactionDescriptionString()
- + " \"details\" : [\n"
- " {\n"
- " \"involvesWatchonly\": xxx, (bool) Only returns true if imported addresses were involved in transaction.\n"
- " \"address\" : \"address\", (string) The bitcoin address involved in the transaction\n"
- " \"category\" : (string) The transaction category.\n"
- " \"send\" Transactions sent.\n"
- " \"receive\" Non-coinbase transactions received.\n"
- " \"generate\" Coinbase transactions received with more than 100 confirmations.\n"
- " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
- " \"orphan\" Orphaned coinbase transactions received.\n"
- " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n"
- " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
- " \"vout\" : n, (numeric) the vout value\n"
- " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
- " 'send' category of transactions.\n"
- " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
- " 'send' category of transactions.\n"
- " }\n"
- " ,...\n"
- " ],\n"
- " \"hex\" : \"data\" (string) Raw data for transaction\n"
- " \"decoded\" : transaction (json object) Optional, the decoded transaction (only present when `verbose` is passed), equivalent to the\n"
- " RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed.\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
+ {
+ {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
+ {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
+ "'send' category of transactions."},
+ },
+ TransactionDescriptionString()),
+ {
+ {RPCResult::Type::ARR, "details", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."},
+ {RPCResult::Type::STR, "address", "The bitcoin address involved in the transaction."},
+ {RPCResult::Type::STR, "category", "The transaction category.\n"
+ "\"send\" Transactions sent.\n"
+ "\"receive\" Non-coinbase transactions received.\n"
+ "\"generate\" Coinbase transactions received with more than 100 confirmations.\n"
+ "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
+ "\"orphan\" Orphaned coinbase transactions received."},
+ {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
+ {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"},
+ {RPCResult::Type::NUM, "vout", "the vout value"},
+ {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
+ "'send' category of transactions."},
+ {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
+ "'send' category of transactions."},
+ }},
+ }},
+ {RPCResult::Type::STR_HEX, "hex", "Raw data for transaction"},
+ {RPCResult::Type::OBJ, "decoded", "Optional, the decoded transaction (only present when `verbose` is passed)",
+ {
+ {RPCResult::Type::ELISION, "", "Equivalent to the RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed."},
+ }},
+ })
},
RPCExamples{
HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
@@ -1710,7 +1687,6 @@ static UniValue gettransaction(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
uint256 hash(ParseHashV(request.params[0], "txid"));
@@ -1739,10 +1715,10 @@ static UniValue gettransaction(const JSONRPCRequest& request)
if (wtx.IsFromMe(filter))
entry.pushKV("fee", ValueFromAmount(nFee));
- WalletTxToJSON(pwallet->chain(), *locked_chain, wtx, entry);
+ WalletTxToJSON(pwallet->chain(), wtx, entry);
UniValue details(UniValue::VARR);
- ListTransactions(*locked_chain, pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */);
+ ListTransactions(pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */);
entry.pushKV("details", details);
std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
@@ -1775,7 +1751,7 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
{
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
@@ -1786,7 +1762,6 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
uint256 hash(ParseHashV(request.params[0], "txid"));
@@ -1805,7 +1780,7 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
static UniValue backupwallet(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -1816,7 +1791,7 @@ static UniValue backupwallet(const JSONRPCRequest& request)
{
{"destination", RPCArg::Type::STR, RPCArg::Optional::NO, "The destination directory or file"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("backupwallet", "\"backup.dat\"")
+ HelpExampleRpc("backupwallet", "\"backup.dat\"")
@@ -1827,7 +1802,6 @@ static UniValue backupwallet(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
std::string strDest = request.params[0].get_str();
@@ -1850,22 +1824,21 @@ static UniValue keypoolrefill(const JSONRPCRequest& request)
RPCHelpMan{"keypoolrefill",
"\nFills the keypool."+
- HelpRequiringPassphrase(pwallet) + "\n",
+ HELP_REQUIRING_PASSPHRASE,
{
{"newsize", RPCArg::Type::NUM, /* default */ "100", "The new keypool size"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("keypoolrefill", "")
+ HelpExampleRpc("keypoolrefill", "")
},
}.Check(request);
- if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ if (pwallet->IsLegacy() && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
}
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
// 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
@@ -1906,7 +1879,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
{"passphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet passphrase"},
{"timeout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The time to keep the decryption key in seconds; capped at 100000000 (~3 years)."},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
"\nUnlock the wallet for 60 seconds\n"
+ HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
@@ -1917,44 +1890,51 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
},
}.Check(request);
- auto locked_chain = pwallet->chain().lock();
- LOCK(pwallet->cs_wallet);
-
- if (!pwallet->IsCrypted()) {
- throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
- }
+ int64_t nSleepTime;
+ {
+ LOCK(pwallet->cs_wallet);
- // Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed
- SecureString strWalletPass;
- strWalletPass.reserve(100);
- // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
- // Alternately, find a way to make request.params[0] mlock()'d to begin with.
- strWalletPass = request.params[0].get_str().c_str();
+ if (!pwallet->IsCrypted()) {
+ throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
+ }
- // Get the timeout
- int64_t nSleepTime = request.params[1].get_int64();
- // Timeout cannot be negative, otherwise it will relock immediately
- if (nSleepTime < 0) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");
- }
- // Clamp timeout
- constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug?
- if (nSleepTime > MAX_SLEEP_TIME) {
- nSleepTime = MAX_SLEEP_TIME;
- }
+ // Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed
+ SecureString strWalletPass;
+ strWalletPass.reserve(100);
+ // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
+ // Alternately, find a way to make request.params[0] mlock()'d to begin with.
+ strWalletPass = request.params[0].get_str().c_str();
+
+ // Get the timeout
+ nSleepTime = request.params[1].get_int64();
+ // Timeout cannot be negative, otherwise it will relock immediately
+ if (nSleepTime < 0) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");
+ }
+ // Clamp timeout
+ constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug?
+ if (nSleepTime > MAX_SLEEP_TIME) {
+ nSleepTime = MAX_SLEEP_TIME;
+ }
- if (strWalletPass.empty()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
- }
+ if (strWalletPass.empty()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
+ }
- if (!pwallet->Unlock(strWalletPass)) {
- throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
- }
+ if (!pwallet->Unlock(strWalletPass)) {
+ throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
+ }
- pwallet->TopUpKeyPool();
+ pwallet->TopUpKeyPool();
- pwallet->nRelockTime = GetTime() + nSleepTime;
+ pwallet->nRelockTime = GetTime() + nSleepTime;
+ }
+ // rpcRunLater must be called without cs_wallet held otherwise a deadlock
+ // can occur. The deadlock would happen when RPCRunLater removes the
+ // previous timer (and waits for the callback to finish if already running)
+ // and the callback locks cs_wallet.
+ AssertLockNotHeld(wallet->cs_wallet);
// Keep a weak pointer to the wallet so that it is possible to unload the
// wallet before the following callback is called. If a valid shared pointer
// is acquired in the callback then the wallet is still loaded.
@@ -1986,14 +1966,13 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request)
{"oldpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The current passphrase"},
{"newpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The new passphrase"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
+ HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
},
}.Check(request);
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
if (!pwallet->IsCrypted()) {
@@ -2036,12 +2015,12 @@ static UniValue walletlock(const JSONRPCRequest& request)
"After calling this method, you will need to call walletpassphrase again\n"
"before being able to call any methods which require the wallet to be unlocked.\n",
{},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
"\nSet the passphrase for 2 minutes to perform a transaction\n"
+ HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
"\nPerform a send (requires passphrase set)\n"
- + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
+ + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 1.0") +
"\nClear the passphrase since we are done before 2 minutes is up\n"
+ HelpExampleCli("walletlock", "") +
"\nAs a JSON-RPC call\n"
@@ -2049,7 +2028,6 @@ static UniValue walletlock(const JSONRPCRequest& request)
},
}.Check(request);
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
if (!pwallet->IsCrypted()) {
@@ -2081,7 +2059,7 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
{
{"passphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long."},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::STR, "", "A string with further instructions"},
RPCExamples{
"\nEncrypt your wallet\n"
+ HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
@@ -2096,7 +2074,6 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
},
}.Check(request);
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
@@ -2143,7 +2120,7 @@ static UniValue lockunspent(const JSONRPCRequest& request)
"Also see the listunspent call\n",
{
{"unlock", RPCArg::Type::BOOL, RPCArg::Optional::NO, "Whether to unlock (true) or lock (false) the specified transactions"},
- {"transactions", RPCArg::Type::ARR, /* default */ "empty array", "A json array of objects. Each object the txid (string) vout (numeric).",
+ {"transactions", RPCArg::Type::ARR, /* default */ "empty array", "The transaction outputs and within each, the txid (string) vout (numeric).",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -2155,7 +2132,7 @@ static UniValue lockunspent(const JSONRPCRequest& request)
},
},
RPCResult{
- "true|false (boolean) Whether the command was successful or not\n"
+ RPCResult::Type::BOOL, "", "Whether the command was successful or not"
},
RPCExamples{
"\nList the unspent transactions\n"
@@ -2175,7 +2152,6 @@ static UniValue lockunspent(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
RPCTypeCheckArgument(request.params[0], UniValue::VBOOL);
@@ -2254,7 +2230,7 @@ static UniValue lockunspent(const JSONRPCRequest& request)
static UniValue listlockunspent(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -2265,13 +2241,14 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
"See the lockunspent call to lock and unlock transactions for spending.\n",
{},
RPCResult{
- "[\n"
- " {\n"
- " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
- " \"vout\" : n (numeric) The vout value\n"
- " }\n"
- " ,...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The transaction id locked"},
+ {RPCResult::Type::NUM, "vout", "The vout value"},
+ }},
+ }
},
RPCExamples{
"\nList the unspent transactions\n"
@@ -2287,7 +2264,6 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
},
}.Check(request);
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
std::vector<COutPoint> vOutpts;
@@ -2316,12 +2292,13 @@ static UniValue settxfee(const JSONRPCRequest& request)
}
RPCHelpMan{"settxfee",
- "\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n",
+ "\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"},
},
RPCResult{
- "true|false (boolean) Returns true if successful\n"
+ RPCResult::Type::BOOL, "", "Returns true if successful"
},
RPCExamples{
HelpExampleCli("settxfee", "0.00001")
@@ -2329,17 +2306,19 @@ static UniValue settxfee(const JSONRPCRequest& request)
},
}.Check(request);
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
CAmount nAmount = AmountFromValue(request.params[0]);
CFeeRate tx_fee_rate(nAmount, 1000);
+ CFeeRate max_tx_fee_rate(pwallet->m_default_max_tx_fee, 1000);
if (tx_fee_rate == CFeeRate(0)) {
// automatic selection
} else if (tx_fee_rate < pwallet->chain().relayMinFee()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", pwallet->chain().relayMinFee().ToString()));
} else if (tx_fee_rate < pwallet->m_min_fee) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than wallet min fee (%s)", pwallet->m_min_fee.ToString()));
+ } else if (tx_fee_rate > max_tx_fee_rate) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be more than wallet max tx fee (%s)", max_tx_fee_rate.ToString()));
}
pwallet->m_pay_tx_fee = tx_fee_rate;
@@ -2359,19 +2338,23 @@ static UniValue getbalances(const JSONRPCRequest& request)
"Returns an object with all balances in " + CURRENCY_UNIT + ".\n",
{},
RPCResult{
- "{\n"
- " \"mine\": { (object) balances from outputs that the wallet can sign\n"
- " \"trusted\": xxx (numeric) trusted balance (outputs created by the wallet or confirmed outputs)\n"
- " \"untrusted_pending\": xxx (numeric) untrusted pending balance (outputs created by others that are in the mempool)\n"
- " \"immature\": xxx (numeric) balance from immature coinbase outputs\n"
- " \"used\": xxx (numeric) (only present if avoid_reuse is set) balance from coins sent to addresses that were previously spent from (potentially privacy violating)\n"
- " },\n"
- " \"watchonly\": { (object) watchonly balances (not present if wallet does not watch anything)\n"
- " \"trusted\": xxx (numeric) trusted balance (outputs created by the wallet or confirmed outputs)\n"
- " \"untrusted_pending\": xxx (numeric) untrusted pending balance (outputs created by others that are in the mempool)\n"
- " \"immature\": xxx (numeric) balance from immature coinbase outputs\n"
- " },\n"
- "}\n"},
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ, "mine", "balances from outputs that the wallet can sign",
+ {
+ {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
+ {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
+ {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
+ {RPCResult::Type::STR_AMOUNT, "used", "(only present if avoid_reuse is set) balance from coins sent to addresses that were previously spent from (potentially privacy violating)"},
+ }},
+ {RPCResult::Type::OBJ, "watchonly", "watchonly balances (not present if wallet does not watch anything)",
+ {
+ {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
+ {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
+ {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
+ }},
+ }
+ },
RPCExamples{
HelpExampleCli("getbalances", "") +
HelpExampleRpc("getbalances", "")},
@@ -2381,11 +2364,8 @@ static UniValue getbalances(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
wallet.BlockUntilSyncedToCurrentChain();
- auto locked_chain = wallet.chain().lock();
LOCK(wallet.cs_wallet);
- UniValue obj(UniValue::VOBJ);
-
const auto bal = wallet.GetBalance();
UniValue balances{UniValue::VOBJ};
{
@@ -2415,7 +2395,7 @@ static UniValue getbalances(const JSONRPCRequest& request)
static UniValue getwalletinfo(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -2425,27 +2405,30 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
"Returns an object containing various wallet state info.\n",
{},
RPCResult{
- "{\n"
- " \"walletname\": xxxxx, (string) the wallet name\n"
- " \"walletversion\": xxxxx, (numeric) the wallet version\n"
- " \"balance\": xxxxxxx, (numeric) DEPRECATED. Identical to getbalances().mine.trusted\n"
- " \"unconfirmed_balance\": xxx, (numeric) DEPRECATED. Identical to getbalances().mine.untrusted_pending\n"
- " \"immature_balance\": xxxxxx, (numeric) DEPRECATED. Identical to getbalances().mine.immature\n"
- " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
- " \"keypoololdest\": xxxxxx, (numeric) the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool\n"
- " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated (only counts external keys)\n"
- " \"keypoolsize_hd_internal\": xxxx, (numeric) 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)\n"
- " \"unlocked_until\": ttt, (numeric) the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
- " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
- " \"hdseedid\": \"<hash160>\" (string, optional) the Hash160 of the HD seed (only present when HD is enabled)\n"
- " \"private_keys_enabled\": true|false (boolean) false if privatekeys are disabled for this wallet (enforced watch-only wallet)\n"
- " \"avoid_reuse\": true|false (boolean) whether this wallet tracks clean/dirty coins in terms of reuse\n"
- " \"scanning\": (json object) current scanning details, or false if no scan is in progress\n"
- " {\n"
- " \"duration\" : xxxx (numeric) elapsed seconds since scan start\n"
- " \"progress\" : x.xxxx, (numeric) scanning progress percentage [0.0, 1.0]\n"
- " }\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {
+ {RPCResult::Type::STR, "walletname", "the wallet name"},
+ {RPCResult::Type::NUM, "walletversion", "the wallet version"},
+ {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"},
+ {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
+ {RPCResult::Type::NUM_TIME, "keypoololdest", "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only."},
+ {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", "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked"},
+ {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB"},
+ {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"},
+ {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
+ {
+ {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"},
+ {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
+ }},
+ {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for scriptPubKey management"},
+ }},
},
RPCExamples{
HelpExampleCli("getwalletinfo", "")
@@ -2457,20 +2440,22 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
UniValue obj(UniValue::VOBJ);
size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
const auto bal = pwallet->GetBalance();
+ int64_t kp_oldest = pwallet->GetOldestKeyPoolTime();
obj.pushKV("walletname", pwallet->GetName());
obj.pushKV("walletversion", pwallet->GetVersion());
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));
obj.pushKV("txcount", (int)pwallet->mapWallet.size());
- obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
+ if (kp_oldest > 0) {
+ obj.pushKV("keypoololdest", kp_oldest);
+ }
obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan();
@@ -2498,6 +2483,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
} else {
obj.pushKV("scanning", false);
}
+ obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
return obj;
}
@@ -2507,14 +2493,16 @@ static UniValue listwalletdir(const JSONRPCRequest& request)
"Returns a list of wallets in the wallet directory.\n",
{},
RPCResult{
- "{\n"
- " \"wallets\" : [ (json array of objects)\n"
- " {\n"
- " \"name\" : \"name\" (string) The wallet name\n"
- " }\n"
- " ,...\n"
- " ]\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::ARR, "wallets", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "name", "The wallet name"},
+ }},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("listwalletdir", "")
@@ -2541,10 +2529,10 @@ static UniValue listwallets(const JSONRPCRequest& request)
"For full information on the wallet, use \"getwalletinfo\"\n",
{},
RPCResult{
- "[ (json array of strings)\n"
- " \"walletname\" (string) the wallet name\n"
- " ...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::STR, "walletname", "the wallet name"},
+ }
},
RPCExamples{
HelpExampleCli("listwallets", "")
@@ -2572,15 +2560,16 @@ static UniValue loadwallet(const JSONRPCRequest& request)
RPCHelpMan{"loadwallet",
"\nLoads a wallet from a wallet file or directory."
"\nNote that all wallet command-line options used when starting bitcoind will be"
- "\napplied to the new wallet (eg -zapwallettxes, upgradewallet, rescan, etc).\n",
+ "\napplied to the new wallet (eg -zapwallettxes, rescan, etc).\n",
{
{"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet directory or .dat file."},
},
RPCResult{
- "{\n"
- " \"name\" : <wallet_name>, (string) The wallet name if loaded successfully.\n"
- " \"warning\" : <warning>, (string) Warning message if wallet was not loaded cleanly.\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
+ {RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."},
+ }
},
RPCExamples{
HelpExampleCli("loadwallet", "\"test.dat\"")
@@ -2632,11 +2621,12 @@ static UniValue setwalletflag(const JSONRPCRequest& request)
{"value", RPCArg::Type::BOOL, /* default */ "true", "The new state."},
},
RPCResult{
- "{\n"
- " \"flag_name\": string (string) The name of the flag that was modified\n"
- " \"flag_state\": bool (bool) The new state of the flag\n"
- " \"warnings\": string (string) Any warnings associated with the change\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
+ {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
+ {RPCResult::Type::STR, "warnings", "Any warnings associated with the change"},
+ }
},
RPCExamples{
HelpExampleCli("setwalletflag", "avoid_reuse")
@@ -2690,12 +2680,14 @@ static UniValue createwallet(const JSONRPCRequest& request)
{"blank", RPCArg::Type::BOOL, /* default */ "false", "Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed."},
{"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
{"avoid_reuse", RPCArg::Type::BOOL, /* default */ "false", "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
+ {"descriptors", RPCArg::Type::BOOL, /* default */ "false", "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation"},
},
RPCResult{
- "{\n"
- " \"name\" : <wallet_name>, (string) The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path.\n"
- " \"warning\" : <warning>, (string) Warning message if wallet was not loaded cleanly.\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "name", "The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path."},
+ {RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."},
+ }
},
RPCExamples{
HelpExampleCli("createwallet", "\"testwallet\"")
@@ -2725,6 +2717,9 @@ static UniValue createwallet(const JSONRPCRequest& request)
if (!request.params[4].isNull() && request.params[4].get_bool()) {
flags |= WALLET_FLAG_AVOID_REUSE;
}
+ if (!request.params[5].isNull() && request.params[5].get_bool()) {
+ flags |= WALLET_FLAG_DESCRIPTORS;
+ }
std::string error;
std::shared_ptr<CWallet> wallet;
@@ -2754,7 +2749,7 @@ static UniValue unloadwallet(const JSONRPCRequest& request)
{
{"wallet_name", RPCArg::Type::STR, /* default */ "the wallet name from the RPC request", "The name of the wallet to unload."},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("unloadwallet", "wallet_name")
+ HelpExampleRpc("unloadwallet", "wallet_name")
@@ -2790,7 +2785,7 @@ static UniValue unloadwallet(const JSONRPCRequest& request)
static UniValue listunspent(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -2804,7 +2799,7 @@ static UniValue listunspent(const JSONRPCRequest& request)
{
{"minconf", RPCArg::Type::NUM, /* default */ "1", "The minimum confirmations to filter"},
{"maxconf", RPCArg::Type::NUM, /* default */ "9999999", "The maximum confirmations to filter"},
- {"addresses", RPCArg::Type::ARR, /* default */ "empty array", "A json array of bitcoin addresses to filter",
+ {"addresses", RPCArg::Type::ARR, /* default */ "empty array", "The bitcoin addresses to filter",
{
{"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address"},
},
@@ -2821,32 +2816,33 @@ static UniValue listunspent(const JSONRPCRequest& request)
"query_options"},
},
RPCResult{
- "[ (array of json object)\n"
- " {\n"
- " \"txid\" : \"txid\", (string) the transaction id \n"
- " \"vout\" : n, (numeric) the vout value\n"
- " \"address\" : \"address\", (string) the bitcoin address\n"
- " \"label\" : \"label\", (string) The associated label, or \"\" for the default label\n"
- " \"scriptPubKey\" : \"key\", (string) the script key\n"
- " \"amount\" : x.xxx, (numeric) the transaction output amount in " + CURRENCY_UNIT + "\n"
- " \"confirmations\" : n, (numeric) The number of confirmations\n"
- " \"redeemScript\" : \"script\" (string) The redeemScript if scriptPubKey is P2SH\n"
- " \"witnessScript\" : \"script\" (string) witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH\n"
- " \"spendable\" : xxx, (bool) Whether we have the private keys to spend this output\n"
- " \"solvable\" : xxx, (bool) Whether we know how to spend this output, ignoring the lack of keys\n"
- " \"reused\" : xxx, (bool) (only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)\n"
- " \"desc\" : xxx, (string, only when solvable) A descriptor for spending this output\n"
- " \"safe\" : xxx (bool) Whether this output is considered safe to spend. Unconfirmed transactions\n"
- " from outside keys and unconfirmed replacement transactions are considered unsafe\n"
- " and are not eligible for spending by fundrawtransaction and sendtoaddress.\n"
- " }\n"
- " ,...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "the transaction id"},
+ {RPCResult::Type::NUM, "vout", "the vout value"},
+ {RPCResult::Type::STR, "address", "the bitcoin address"},
+ {RPCResult::Type::STR, "label", "The associated label, or \"\" for the default label"},
+ {RPCResult::Type::STR, "scriptPubKey", "the script key"},
+ {RPCResult::Type::STR_AMOUNT, "amount", "the transaction output amount in " + CURRENCY_UNIT},
+ {RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
+ {RPCResult::Type::STR_HEX, "redeemScript", "The redeemScript if scriptPubKey is P2SH"},
+ {RPCResult::Type::STR, "witnessScript", "witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH"},
+ {RPCResult::Type::BOOL, "spendable", "Whether we have the private keys to spend this output"},
+ {RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
+ {RPCResult::Type::BOOL, "reused", "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"},
+ {RPCResult::Type::STR, "desc", "(only when solvable) A descriptor for spending this output"},
+ {RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
+ "from outside keys and unconfirmed replacement transactions are considered unsafe\n"
+ "and are not eligible for spending by fundrawtransaction and sendtoaddress."},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("listunspent", "")
- + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
- + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
+ + HelpExampleCli("listunspent", "6 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
+ + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
+ HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
+ HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
},
@@ -2918,9 +2914,8 @@ static UniValue listunspent(const JSONRPCRequest& request)
cctl.m_avoid_address_reuse = false;
cctl.m_min_depth = nMinDepth;
cctl.m_max_depth = nMaxDepth;
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
- pwallet->AvailableCoins(*locked_chain, vecOutputs, !include_unsafe, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount);
+ pwallet->AvailableCoins(vecOutputs, !include_unsafe, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount);
}
LOCK(pwallet->cs_wallet);
@@ -2931,7 +2926,7 @@ static UniValue listunspent(const JSONRPCRequest& request)
CTxDestination address;
const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
bool fValidAddress = ExtractDestination(scriptPubKey, address);
- bool reused = avoid_reuse && pwallet->IsUsedDestination(out.tx->GetHash(), out.i);
+ bool reused = avoid_reuse && pwallet->IsSpentKey(out.tx->GetHash(), out.i);
if (destinations.size() && (!fValidAddress || !destinations.count(address)))
continue;
@@ -2943,12 +2938,12 @@ static UniValue listunspent(const JSONRPCRequest& request)
if (fValidAddress) {
entry.pushKV("address", EncodeDestination(address));
- auto i = pwallet->mapAddressBook.find(address);
- if (i != pwallet->mapAddressBook.end()) {
- entry.pushKV("label", i->second.name);
+ const auto* address_book_entry = pwallet->FindAddressBookEntry(address);
+ if (address_book_entry) {
+ entry.pushKV("label", address_book_entry->GetLabel());
}
- std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(scriptPubKey);
+ std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
if (provider) {
if (scriptPubKey.IsPayToScriptHash()) {
const CScriptID& hash = CScriptID(boost::get<ScriptHash>(address));
@@ -2988,7 +2983,7 @@ static UniValue listunspent(const JSONRPCRequest& request)
entry.pushKV("spendable", out.fSpendable);
entry.pushKV("solvable", out.fSolvable);
if (out.fSolvable) {
- std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(scriptPubKey);
+ std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
if (provider) {
auto descriptor = InferDescriptor(scriptPubKey, *provider);
entry.pushKV("desc", descriptor->ToString());
@@ -3153,7 +3148,7 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
"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"},
- {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "A json array of integers.\n"
+ {"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"
" If no outputs are specified here, the sender pays the fee.",
@@ -3179,11 +3174,12 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
},
},
RPCResult{
- "{\n"
- " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
- " \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
- " \"changepos\": n (numeric) The position of the added change output, or -1\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "hex", "The resulting raw transaction (hex-encoded string)"},
+ {RPCResult::Type::STR_AMOUNT, "fee", "Fee in " + CURRENCY_UNIT + " the resulting transaction pays"},
+ {RPCResult::Type::NUM, "changepos", "The position of the added change output, or -1"},
+ }
},
RPCExamples{
"\nCreate a transaction with no inputs\n"
@@ -3222,7 +3218,7 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -3232,10 +3228,10 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
"\nSign inputs for raw transaction (serialized, hex-encoded).\n"
"The second optional argument (may be null) is an array of previous transaction outputs that\n"
"this transaction depends on but may not yet be in the block chain." +
- HelpRequiringPassphrase(pwallet) + "\n",
+ HELP_REQUIRING_PASSPHRASE,
{
{"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"},
- {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of previous dependent transaction outputs",
+ {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The previous dependent transaction outputs",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -3258,20 +3254,22 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
" \"SINGLE|ANYONECANPAY\""},
},
RPCResult{
- "{\n"
- " \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
- " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
- " \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n"
- " {\n"
- " \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n"
- " \"vout\" : n, (numeric) The index of the output to spent and used as input\n"
- " \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n"
- " \"sequence\" : n, (numeric) Script sequence number\n"
- " \"error\" : \"text\" (string) Verification or signing error related to the input\n"
- " }\n"
- " ,...\n"
- " ]\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"},
+ {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
+ {RPCResult::Type::ARR, "errors", "Script verification errors (if there are any)",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"},
+ {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"},
+ {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"},
+ {RPCResult::Type::NUM, "sequence", "Script sequence number"},
+ {RPCResult::Type::STR, "error", "Verification or signing error related to the input"},
+ }},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"")
@@ -3287,7 +3285,6 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
}
// Sign the transaction
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -3301,23 +3298,15 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
// Parse the prevtxs array
ParsePrevouts(request.params[1], nullptr, coins);
- std::set<std::shared_ptr<SigningProvider>> providers;
- for (const std::pair<COutPoint, Coin> coin_pair : coins) {
- std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(coin_pair.second.out.scriptPubKey);
- if (provider) {
- providers.insert(std::move(provider));
- }
- }
- if (providers.size() == 0) {
- // When there are no available providers, use a dummy SigningProvider so we can check if the tx is complete
- providers.insert(std::make_shared<SigningProvider>());
- }
+ int nHashType = ParseSighashString(request.params[2]);
+
+ // Script verification errors
+ std::map<int, std::string> input_errors;
+ bool complete = pwallet->SignTransaction(mtx, coins, nHashType, input_errors);
UniValue result(UniValue::VOBJ);
- for (std::shared_ptr<SigningProvider> provider : providers) {
- SignTransaction(mtx, provider.get(), coins, request.params[2], result);
- }
- return result;
+ SignTransactionResultToJSON(mtx, complete, coins, input_errors, result);
+ return result;
}
static UniValue bumpfee(const JSONRPCRequest& request)
@@ -3333,12 +3322,11 @@ static UniValue bumpfee(const JSONRPCRequest& request)
"\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\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"
- "If `totalFee` (DEPRECATED) is given, adding inputs is not supported, so there must be a single change output that is big enough or it will fail.\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"
"The user can specify a confirmation target for estimatesmartfee.\n"
- "Alternatively, the user can specify totalFee (DEPRECATED), or fee_rate (" + CURRENCY_UNIT + " per kB) for the new transaction .\n"
+ "Alternatively, the user can specify a fee_rate (" + CURRENCY_UNIT + " per kB) 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",
{
@@ -3346,13 +3334,9 @@ static UniValue bumpfee(const JSONRPCRequest& request)
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
{
{"confTarget", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
- {"totalFee", RPCArg::Type::NUM, /* default */ "fallback to 'confTarget'", "Total fee (NOT feerate) to pay, in satoshis. (DEPRECATED)\n"
- " In rare cases, the actual fee paid might be slightly higher than the specified\n"
- " totalFee if the tx change output has to be removed because it is too close to\n"
- " the dust threshold."},
- {"fee_rate", RPCArg::Type::NUM, /* default */ "fallback to 'confTarget'", "FeeRate (NOT total fee) to pay, in " + CURRENCY_UNIT + " per kB\n"
+ {"fee_rate", RPCArg::Type::NUM, /* default */ "fall back to 'confTarget'", "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 BTC per kB higher than the current transaction fee rate.\n"},
+ "Must be at least 0.0001 " + CURRENCY_UNIT + " per kB higher than the current transaction fee rate.\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"
@@ -3368,13 +3352,16 @@ static UniValue bumpfee(const JSONRPCRequest& request)
"options"},
},
RPCResult{
- "{\n"
- " \"psbt\": \"psbt\", (string) The base64-encoded unsigned PSBT of the new transaction. Only returned when wallet private keys are disabled.\n"
- " \"txid\": \"value\", (string) The id of the new transaction. Only returned when wallet private keys are enabled.\n"
- " \"origfee\": n, (numeric) The fee of the replaced transaction.\n"
- " \"fee\": n, (numeric) The fee of the new transaction.\n"
- " \"errors\": [ str... ] (json array of strings) Errors encountered during processing (may be empty).\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "", {
+ {RPCResult::Type::STR, "psbt", "The base64-encoded unsigned PSBT of the new transaction. Only returned when wallet private keys are disabled."},
+ {RPCResult::Type::STR_HEX, "txid", "The id of the new transaction. Only returned when wallet private keys are enabled."},
+ {RPCResult::Type::STR_AMOUNT, "origfee", "The fee of the replaced transaction."},
+ {RPCResult::Type::STR_AMOUNT, "fee", "The fee of the new transaction."},
+ {RPCResult::Type::ARR, "errors", "Errors encountered during processing (may be empty).",
+ {
+ {RPCResult::Type::STR, "", ""},
+ }},
+ }
},
RPCExamples{
"\nBump the fee, get the new transaction\'s txid\n" +
@@ -3388,7 +3375,6 @@ static UniValue bumpfee(const JSONRPCRequest& request)
CCoinControl coin_control;
coin_control.fAllowWatchOnly = pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
// optional parameters
- CAmount totalFee = 0;
coin_control.m_signal_bip125_rbf = true;
if (!request.params[1].isNull()) {
@@ -3396,26 +3382,15 @@ static UniValue bumpfee(const JSONRPCRequest& request)
RPCTypeCheckObj(options,
{
{"confTarget", UniValueType(UniValue::VNUM)},
- {"totalFee", UniValueType(UniValue::VNUM)},
{"fee_rate", UniValueType(UniValue::VNUM)},
{"replaceable", UniValueType(UniValue::VBOOL)},
{"estimate_mode", UniValueType(UniValue::VSTR)},
},
true, true);
- if (options.exists("confTarget") && (options.exists("totalFee") || options.exists("fee_rate"))) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget can't be set with totalFee or fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
- } else if (options.exists("fee_rate") && options.exists("totalFee")) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "fee_rate can't be set along with totalFee.");
+ if (options.exists("confTarget") && options.exists("fee_rate")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
} else if (options.exists("confTarget")) { // TODO: alias this to conf_target
coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"], pwallet->chain().estimateMaxBlocks());
- } else if (options.exists("totalFee")) {
- if (!pwallet->chain().rpcEnableDeprecated("totalFee")) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "totalFee argument has been deprecated and will be removed in 0.20. Please use -deprecatedrpc=totalFee to continue using this argument until removal.");
- }
- totalFee = options["totalFee"].get_int64();
- if (totalFee <= 0) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid totalFee %s (must be greater than 0)", FormatMoney(totalFee)));
- }
} else if (options.exists("fee_rate")) {
CFeeRate fee_rate(AmountFromValue(options["fee_rate"]));
if (fee_rate <= CFeeRate(0)) {
@@ -3438,7 +3413,6 @@ static UniValue bumpfee(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -3448,13 +3422,8 @@ static UniValue bumpfee(const JSONRPCRequest& request)
CAmount new_fee;
CMutableTransaction mtx;
feebumper::Result res;
- if (totalFee > 0) {
- // Targeting total fee bump. Requires a change output of sufficient size.
- res = feebumper::CreateTotalBumpTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx);
- } else {
- // Targeting feerate bump.
- res = feebumper::CreateRateBumpTransaction(*pwallet, hash, coin_control, errors, old_fee, new_fee, mtx);
- }
+ // Targeting feerate bump.
+ res = feebumper::CreateRateBumpTransaction(*pwallet, hash, coin_control, errors, old_fee, new_fee, mtx);
if (res != feebumper::Result::OK) {
switch(res) {
case feebumper::Result::INVALID_ADDRESS_OR_KEY:
@@ -3493,7 +3462,7 @@ static UniValue bumpfee(const JSONRPCRequest& request)
} else {
PartiallySignedTransaction psbtx(mtx);
bool complete = false;
- const TransactionError err = FillPSBT(pwallet, psbtx, complete, SIGHASH_ALL, false /* sign */, true /* bip32derivs */);
+ const TransactionError err = pwallet->FillPSBT(psbtx, complete, SIGHASH_ALL, false /* sign */, true /* bip32derivs */);
CHECK_NONFATAL(err == TransactionError::OK);
CHECK_NONFATAL(!complete);
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
@@ -3529,10 +3498,11 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
{"stop_height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "the last block height that should be scanned. If none is provided it will rescan up to the tip at return time of this call."},
},
RPCResult{
- "{\n"
- " \"start_height\" (numeric) The block height where the rescan started (the requested height or 0)\n"
- " \"stop_height\" (numeric) The height of the last rescanned block. May be null in rare cases if there was a reorg and the call didn't scan any blocks because they were already scanned in the background.\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::NUM, "start_height", "The block height where the rescan started (the requested height or 0)"},
+ {RPCResult::Type::NUM, "stop_height", "The height of the last rescanned block. May be null in rare cases if there was a reorg and the call didn't scan any blocks because they were already scanned in the background."},
+ }
},
RPCExamples{
HelpExampleCli("rescanblockchain", "100000 120000")
@@ -3540,55 +3510,44 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
},
}.Check(request);
- WalletRescanReserver reserver(pwallet);
+ WalletRescanReserver reserver(*pwallet);
if (!reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}
int start_height = 0;
- uint256 start_block, stop_block;
+ Optional<int> stop_height;
+ uint256 start_block;
{
- auto locked_chain = pwallet->chain().lock();
- Optional<int> tip_height = locked_chain->getHeight();
+ LOCK(pwallet->cs_wallet);
+ int tip_height = pwallet->GetLastBlockHeight();
if (!request.params[0].isNull()) {
start_height = request.params[0].get_int();
- if (start_height < 0 || !tip_height || start_height > *tip_height) {
+ if (start_height < 0 || start_height > tip_height) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
}
}
- Optional<int> stop_height;
if (!request.params[1].isNull()) {
stop_height = request.params[1].get_int();
- if (*stop_height < 0 || !tip_height || *stop_height > *tip_height) {
+ if (*stop_height < 0 || *stop_height > tip_height) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
- }
- else if (*stop_height < start_height) {
+ } else if (*stop_height < start_height) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater than start_height");
}
}
// We can't rescan beyond non-pruned blocks, stop and throw an error
- if (locked_chain->findPruned(start_height, stop_height)) {
+ if (!pwallet->chain().hasBlocks(pwallet->GetLastBlockHash(), start_height, stop_height)) {
throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
}
- if (tip_height) {
- start_block = locked_chain->getBlockHash(start_height);
- // If called with a stop_height, set the stop_height here to
- // trigger a rescan to that height.
- // If called without a stop height, leave stop_height as null here
- // so rescan continues to the tip (even if the tip advances during
- // rescan).
- if (stop_height) {
- stop_block = locked_chain->getBlockHash(*stop_height);
- }
- }
+ CHECK_NONFATAL(pwallet->chain().findAncestorByHeight(pwallet->GetLastBlockHash(), start_height, FoundBlock().hash(start_block)));
}
CWallet::ScanResult result =
- pwallet->ScanForWalletTransactions(start_block, stop_block, reserver, true /* fUpdate */);
+ pwallet->ScanForWalletTransactions(start_block, start_height, stop_height, reserver, true /* fUpdate */);
switch (result.status) {
case CWallet::ScanResult::SUCCESS:
break;
@@ -3696,14 +3655,14 @@ public:
UniValue operator()(const WitnessUnknown& id) const { return UniValue(UniValue::VOBJ); }
};
-static UniValue DescribeWalletAddress(CWallet* pwallet, const CTxDestination& dest)
+static UniValue DescribeWalletAddress(const CWallet* const pwallet, const CTxDestination& dest)
{
UniValue ret(UniValue::VOBJ);
UniValue detail = DescribeAddress(dest);
CScript script = GetScriptForDestination(dest);
std::unique_ptr<SigningProvider> provider = nullptr;
if (pwallet) {
- provider = pwallet->GetSigningProvider(script);
+ provider = pwallet->GetSolvingProvider(script);
}
ret.pushKVs(detail);
ret.pushKVs(boost::apply_visitor(DescribeWalletAddressVisitor(provider.get()), dest));
@@ -3715,7 +3674,7 @@ static UniValue AddressBookDataToJSON(const CAddressBookData& data, const bool v
{
UniValue ret(UniValue::VOBJ);
if (verbose) {
- ret.pushKV("name", data.name);
+ ret.pushKV("name", data.GetLabel());
}
ret.pushKV("purpose", data.purpose);
return ret;
@@ -3724,14 +3683,12 @@ static UniValue AddressBookDataToJSON(const CAddressBookData& data, const bool v
UniValue getaddressinfo(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
- const std::string example_address = "\"bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl\"";
-
RPCHelpMan{"getaddressinfo",
"\nReturn information about the given bitcoin address.\n"
"Some of the information will only be present if the address is in the active wallet.\n",
@@ -3739,53 +3696,56 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."},
},
RPCResult{
- "{\n"
- " \"address\" : \"address\", (string) The bitcoin address validated.\n"
- " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address.\n"
- " \"ismine\" : true|false, (boolean) If the address is yours.\n"
- " \"iswatchonly\" : true|false, (boolean) If the address is watchonly.\n"
- " \"solvable\" : true|false, (boolean) If we know how to spend coins sent to this address, ignoring the possible lack of private keys.\n"
- " \"desc\" : \"desc\", (string, optional) A descriptor for spending coins sent to this address (only when solvable).\n"
- " \"isscript\" : true|false, (boolean) If the key is a script.\n"
- " \"ischange\" : true|false, (boolean) If the address was used for change output.\n"
- " \"iswitness\" : true|false, (boolean) If the address is a witness address.\n"
- " \"witness_version\" : version (numeric, optional) The version number of the witness program.\n"
- " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program.\n"
- " \"script\" : \"type\" (string, optional) The output script type. Only if isscript is true and the redeemscript is known. Possible\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "address", "The bitcoin address validated."},
+ {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address."},
+ {RPCResult::Type::BOOL, "ismine", "If the address is yours."},
+ {RPCResult::Type::BOOL, "iswatchonly", "If the address is watchonly."},
+ {RPCResult::Type::BOOL, "solvable", "If we know how to spend coins sent to this address, ignoring the possible lack of private keys."},
+ {RPCResult::Type::STR, "desc", /* optional */ true, "A descriptor for spending coins sent to this address (only when solvable)."},
+ {RPCResult::Type::BOOL, "isscript", "If the key is a script."},
+ {RPCResult::Type::BOOL, "ischange", "If the address was used for change output."},
+ {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address."},
+ {RPCResult::Type::NUM, "witness_version", /* optional */ true, "The version number of the witness program."},
+ {RPCResult::Type::STR_HEX, "witness_program", /* optional */ true, "The hex value of the witness program."},
+ {RPCResult::Type::STR, "script", /* optional */ true, "The output script type. Only if isscript is true and the redeemscript is known. Possible\n"
" types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n"
- " witness_v0_scripthash, witness_unknown.\n"
- " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address.\n"
- " \"pubkeys\" (array, optional) Array of pubkeys associated with the known redeemscript (only if script is multisig).\n"
- " [\n"
- " \"pubkey\" (string)\n"
- " ,...\n"
- " ]\n"
- " \"sigsrequired\" : xxxxx (numeric, optional) The number of signatures required to spend multisig output (only if script is multisig).\n"
- " \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key for single-key addresses (possibly embedded in P2SH or P2WSH).\n"
- " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. Includes all\n"
+ "witness_v0_scripthash, witness_unknown."},
+ {RPCResult::Type::STR_HEX, "hex", /* optional */ true, "The redeemscript for the p2sh address."},
+ {RPCResult::Type::ARR, "pubkeys", /* optional */ true, "Array of pubkeys associated with the known redeemscript (only if script is multisig).",
+ {
+ {RPCResult::Type::STR, "pubkey", ""},
+ }},
+ {RPCResult::Type::NUM, "sigsrequired", /* optional */ true, "The number of signatures required to spend multisig output (only if script is multisig)."},
+ {RPCResult::Type::STR_HEX, "pubkey", /* optional */ true, "The hex value of the raw public key for single-key addresses (possibly embedded in P2SH or P2WSH)."},
+ {RPCResult::Type::OBJ, "embedded", /* optional */ true, "Information about the address embedded in P2SH or P2WSH, if relevant and known.",
+ {
+ {RPCResult::Type::ELISION, "", "Includes all\n"
" getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath,\n"
- " hdseedid) and relation to the wallet (ismine, iswatchonly).\n"
- " \"iscompressed\" : true|false, (boolean, optional) If the pubkey is compressed.\n"
- " \"label\" : \"label\" (string) DEPRECATED. The label associated with the address. Defaults to \"\". Replaced by the labels array below.\n"
- " \"timestamp\" : timestamp, (number, optional) The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + ".\n"
- " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath, if the key is HD and available.\n"
- " \"hdseedid\" : \"<hash160>\" (string, optional) The Hash160 of the HD seed.\n"
- " \"hdmasterfingerprint\" : \"<hash160>\" (string, optional) The fingerprint of the master key.\n"
- " \"labels\" (array) Array of labels associated with the address. Currently limited to one label but returned\n"
- " as an array to keep the API stable if multiple labels are enabled in the future.\n"
- " [\n"
- " \"label name\" (string) The label name. Defaults to \"\".\n"
- " DEPRECATED, will be removed in 0.21. To re-enable, launch bitcoind with `-deprecatedrpc=labelspurpose`:\n"
- " {\n"
- " \"name\" : \"label name\" (string) The label name. Defaults to \"\".\n"
- " \"purpose\" : \"purpose\" (string) The purpose of the associated address (send or receive).\n"
- " }\n"
- " ]\n"
- "}\n"
+ "hdseedid) and relation to the wallet (ismine, iswatchonly)."},
+ }},
+ {RPCResult::Type::BOOL, "iscompressed", /* optional */ true, "If the pubkey is compressed."},
+ {RPCResult::Type::STR, "label", "DEPRECATED. The label associated with the address. Defaults to \"\". Replaced by the labels array below."},
+ {RPCResult::Type::NUM_TIME, "timestamp", /* optional */ true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."},
+ {RPCResult::Type::STR, "hdkeypath", /* optional */ true, "The HD keypath, if the key is HD and available."},
+ {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true, "The Hash160 of the HD seed."},
+ {RPCResult::Type::STR_HEX, "hdmasterfingerprint", /* optional */ true, "The fingerprint of the master key."},
+ {RPCResult::Type::ARR, "labels", "Array of labels associated with the address. Currently limited to one label but returned\n"
+ "as an array to keep the API stable if multiple labels are enabled in the future.",
+ {
+ {RPCResult::Type::STR, "label name", "The label name. Defaults to \"\"."},
+ {RPCResult::Type::OBJ, "", "label data, DEPRECATED, will be removed in 0.21. To re-enable, launch bitcoind with `-deprecatedrpc=labelspurpose`",
+ {
+ {RPCResult::Type::STR, "name", "The label name. Defaults to \"\"."},
+ {RPCResult::Type::STR, "purpose", "The purpose of the associated address (send or receive)."},
+ }},
+ }},
+ }
},
RPCExamples{
- HelpExampleCli("getaddressinfo", example_address) +
- HelpExampleRpc("getaddressinfo", example_address)
+ HelpExampleCli("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
+ HelpExampleRpc("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"")
},
}.Check(request);
@@ -3804,7 +3764,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
CScript scriptPubKey = GetScriptForDestination(dest);
ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
- std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(scriptPubKey);
+ std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
isminetype mine = pwallet->IsMine(dest);
ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
@@ -3824,15 +3784,16 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
// DEPRECATED: Return label field if existing. Currently only one label can
// be associated with an address, so the label should be equivalent to the
// value of the name key/value pair in the labels array below.
- if ((pwallet->chain().rpcEnableDeprecated("label")) && (pwallet->mapAddressBook.count(dest))) {
- ret.pushKV("label", pwallet->mapAddressBook[dest].name);
+ const auto* address_book_entry = pwallet->FindAddressBookEntry(dest);
+ if (pwallet->chain().rpcEnableDeprecated("label") && address_book_entry) {
+ ret.pushKV("label", address_book_entry->GetLabel());
}
ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan(scriptPubKey);
if (spk_man) {
- if (const CKeyMetadata* meta = spk_man->GetMetadata(dest)) {
+ if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
ret.pushKV("timestamp", meta->nCreateTime);
if (meta->has_key_origin) {
ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
@@ -3848,14 +3809,13 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
// stable if we allow multiple labels to be associated with an address in
// the future.
UniValue labels(UniValue::VARR);
- std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(dest);
- if (mi != pwallet->mapAddressBook.end()) {
+ if (address_book_entry) {
// DEPRECATED: The previous behavior of returning an array containing a
// JSON object of `name` and `purpose` key/value pairs is deprecated.
if (pwallet->chain().rpcEnableDeprecated("labelspurpose")) {
- labels.push_back(AddressBookDataToJSON(mi->second, true));
+ labels.push_back(AddressBookDataToJSON(*address_book_entry, true));
} else {
- labels.push_back(mi->second.name);
+ labels.push_back(address_book_entry->GetLabel());
}
}
ret.pushKV("labels", std::move(labels));
@@ -3866,7 +3826,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
static UniValue getaddressesbylabel(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -3878,11 +3838,13 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
{"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
},
RPCResult{
- "{ (json object with addresses as keys)\n"
- " \"address\": { (json object with information about address)\n"
- " \"purpose\": \"string\" (string) Purpose of address (\"send\" for sending address, \"receive\" for receiving address)\n"
- " },...\n"
- "}\n"
+ RPCResult::Type::OBJ_DYN, "", "json object with addresses as keys",
+ {
+ {RPCResult::Type::OBJ, "address", "json object with information about address",
+ {
+ {RPCResult::Type::STR, "purpose", "Purpose of address (\"send\" for sending address, \"receive\" for receiving address)"},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("getaddressesbylabel", "\"tabby\"")
@@ -3897,10 +3859,11 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
// Find all addresses that have the given label
UniValue ret(UniValue::VOBJ);
std::set<std::string> addresses;
- for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
- if (item.second.name == label) {
+ for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->m_address_book) {
+ if (item.second.IsChange()) continue;
+ if (item.second.GetLabel() == label) {
std::string address = EncodeDestination(item.first);
- // CWallet::mapAddressBook is not expected to contain duplicate
+ // CWallet::m_address_book is not expected to contain duplicate
// address strings, but build a separate set as a precaution just in
// case it does.
bool unique = addresses.emplace(address).second;
@@ -3923,7 +3886,7 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
static UniValue listlabels(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -3935,10 +3898,10 @@ static UniValue listlabels(const JSONRPCRequest& request)
{"purpose", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument."},
},
RPCResult{
- "[ (json array of string)\n"
- " \"label\", (string) Label name\n"
- " ...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::STR, "label", "Label name"},
+ }
},
RPCExamples{
"\nList all labels\n"
@@ -3961,9 +3924,10 @@ static UniValue listlabels(const JSONRPCRequest& request)
// Add to a set to sort by label name, then insert into Univalue array
std::set<std::string> label_set;
- for (const std::pair<const CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
+ for (const std::pair<const CTxDestination, CAddressBookData>& entry : pwallet->m_address_book) {
+ if (entry.second.IsChange()) continue;
if (purpose.empty() || entry.second.purpose == purpose) {
- label_set.insert(entry.second.name);
+ label_set.insert(entry.second.GetLabel());
}
}
@@ -3988,7 +3952,7 @@ UniValue sethdseed(const JSONRPCRequest& request)
"\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n"
"HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
"\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." +
- HelpRequiringPassphrase(pwallet) + "\n",
+ HELP_REQUIRING_PASSPHRASE,
{
{"newkeypool", RPCArg::Type::BOOL, /* default */ "true", "Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
" If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
@@ -3997,7 +3961,7 @@ UniValue sethdseed(const JSONRPCRequest& request)
{"seed", RPCArg::Type::STR, /* default */ "random seed", "The WIF private key to use as the new HD seed.\n"
" The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
},
- RPCResults{},
+ RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("sethdseed", "")
+ HelpExampleCli("sethdseed", "false")
@@ -4016,12 +3980,11 @@ UniValue sethdseed(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
}
- auto locked_chain = pwallet->chain().lock();
LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
// 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. Start with -upgradewallet in order to upgrade a non-HD wallet to 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");
}
EnsureWalletIsUnlocked(pwallet);
@@ -4056,7 +4019,7 @@ UniValue sethdseed(const JSONRPCRequest& request)
UniValue walletprocesspsbt(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
+ const CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -4065,7 +4028,7 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
RPCHelpMan{"walletprocesspsbt",
"\nUpdate a PSBT with input information from our wallet and then sign inputs\n"
"that we can sign for." +
- HelpRequiringPassphrase(pwallet) + "\n",
+ HELP_REQUIRING_PASSPHRASE,
{
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction base64 string"},
{"sign", RPCArg::Type::BOOL, /* default */ "true", "Also sign the transaction when updating"},
@@ -4076,14 +4039,14 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
" \"ALL|ANYONECANPAY\"\n"
" \"NONE|ANYONECANPAY\"\n"
" \"SINGLE|ANYONECANPAY\""},
- {"bip32derivs", RPCArg::Type::BOOL, /* default */ "false", "If true, includes the BIP 32 derivation paths for public keys if we know them"},
+ {"bip32derivs", RPCArg::Type::BOOL, /* default */ "true", "Include BIP 32 derivation paths for public keys if we know them"},
},
RPCResult{
- "{\n"
- " \"psbt\" : \"value\", (string) The base64-encoded partially signed transaction\n"
- " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
- " ]\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction"},
+ {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
+ }
},
RPCExamples{
HelpExampleCli("walletprocesspsbt", "\"psbt\"")
@@ -4104,9 +4067,9 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
// Fill transaction with our data and also sign
bool sign = request.params[1].isNull() ? true : request.params[1].get_bool();
- bool bip32derivs = request.params[3].isNull() ? false : request.params[3].get_bool();
+ bool bip32derivs = request.params[3].isNull() ? true : request.params[3].get_bool();
bool complete = true;
- const TransactionError err = FillPSBT(pwallet, psbtx, complete, nHashType, sign, bip32derivs);
+ const TransactionError err = pwallet->FillPSBT(psbtx, complete, nHashType, sign, bip32derivs);
if (err != TransactionError::OK) {
throw JSONRPCTransactionError(err);
}
@@ -4133,7 +4096,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
"\nCreates and funds a transaction in the Partially Signed Transaction format. Inputs will be added if supplied inputs are not enough\n"
"Implements the Creator and Updater roles.\n",
{
- {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects",
+ {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The inputs",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -4144,7 +4107,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
},
},
},
- {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n"
+ {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs (key-value pairs), where none of the keys are duplicated.\n"
"That is, each address can only appear once and there can only be one 'data' object.\n"
"For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
" accepted as second parameter.",
@@ -4170,7 +4133,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
{"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"},
- {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "A json array of integers.\n"
+ {"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"
" If no outputs are specified here, the sender pays the fee.",
@@ -4180,21 +4143,22 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
},
{"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 */ "Fallback to wallet's confirmation target", "Confirmation target (in blocks)"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "fall back to wallet's confirmation target (txconfirmtarget)", "Confirmation target (in blocks)"},
{"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
" \"UNSET\"\n"
" \"ECONOMICAL\"\n"
" \"CONSERVATIVE\""},
},
"options"},
- {"bip32derivs", RPCArg::Type::BOOL, /* default */ "false", "If true, includes the BIP 32 derivation paths for public keys if we know them"},
+ {"bip32derivs", RPCArg::Type::BOOL, /* default */ "true", "Include BIP 32 derivation paths for public keys if we know them"},
},
RPCResult{
- "{\n"
- " \"psbt\": \"value\", (string) The resulting raw transaction (base64-encoded string)\n"
- " \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
- " \"changepos\": n (numeric) The position of the added change output, or -1\n"
- "}\n"
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "psbt", "The resulting raw transaction (base64-encoded string)"},
+ {RPCResult::Type::STR_AMOUNT, "fee", "Fee in " + CURRENCY_UNIT + " the resulting transaction pays"},
+ {RPCResult::Type::NUM, "changepos", "The position of the added change output, or -1"},
+ }
},
RPCExamples{
"\nCreate a transaction with no inputs\n"
@@ -4226,9 +4190,9 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
PartiallySignedTransaction psbtx(rawTx);
// Fill transaction with out data but don't sign
- bool bip32derivs = request.params[4].isNull() ? false : request.params[4].get_bool();
+ bool bip32derivs = request.params[4].isNull() ? true : request.params[4].get_bool();
bool complete = true;
- const TransactionError err = FillPSBT(pwallet, psbtx, complete, 1, false, bip32derivs);
+ const TransactionError err = pwallet->FillPSBT(psbtx, complete, 1, false, bip32derivs);
if (err != TransactionError::OK) {
throw JSONRPCTransactionError(err);
}
@@ -4244,6 +4208,45 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
return result;
}
+static UniValue upgradewallet(const JSONRPCRequest& request)
+{
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
+ return NullUniValue;
+ }
+
+ RPCHelpMan{"upgradewallet",
+ "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified\n"
+ "New keys may be generated and a new wallet backup will need to be made.",
+ {
+ {"version", RPCArg::Type::NUM, /* default */ strprintf("%d", FEATURE_LATEST), "The version number to upgrade to. Default is the latest wallet version"}
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("upgradewallet", "169900")
+ + HelpExampleRpc("upgradewallet", "169900")
+ }
+ }.Check(request);
+
+ RPCTypeCheck(request.params, {UniValue::VNUM}, true);
+
+ EnsureWalletIsUnlocked(pwallet);
+
+ int version = 0;
+ if (!request.params[0].isNull()) {
+ version = request.params[0].get_int();
+ }
+
+ std::string error;
+ std::vector<std::string> warnings;
+ if (!pwallet->UpgradeWallet(version, error, warnings)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, error);
+ }
+ return error;
+}
+
UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
UniValue importprivkey(const JSONRPCRequest& request);
@@ -4254,7 +4257,10 @@ UniValue importwallet(const JSONRPCRequest& request);
UniValue importprunedfunds(const JSONRPCRequest& request);
UniValue removeprunedfunds(const JSONRPCRequest& request);
UniValue importmulti(const JSONRPCRequest& request);
+UniValue importdescriptors(const JSONRPCRequest& request);
+void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector<std::unique_ptr<interfaces::Handler>>& handlers)
+{
// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
@@ -4265,7 +4271,7 @@ static const CRPCCommand commands[] =
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label","address_type"} },
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
- { "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse"} },
+ { "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse", "descriptors"} },
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
{ "wallet", "dumpwallet", &dumpwallet, {"filename"} },
{ "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
@@ -4281,6 +4287,7 @@ static const CRPCCommand commands[] =
{ "wallet", "getbalances", &getbalances, {} },
{ "wallet", "getwalletinfo", &getwalletinfo, {} },
{ "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
+ { "wallet", "importdescriptors", &importdescriptors, {"requests"} },
{ "wallet", "importmulti", &importmulti, {"requests","options"} },
{ "wallet", "importprivkey", &importprivkey, {"privkey","label","rescan"} },
{ "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} },
@@ -4310,6 +4317,7 @@ static const CRPCCommand commands[] =
{ "wallet", "signmessage", &signmessage, {"address","message"} },
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
{ "wallet", "unloadwallet", &unloadwallet, {"wallet_name"} },
+ { "wallet", "upgradewallet", &upgradewallet, {"version"} },
{ "wallet", "walletcreatefundedpsbt", &walletcreatefundedpsbt, {"inputs","outputs","locktime","options","bip32derivs"} },
{ "wallet", "walletlock", &walletlock, {} },
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
@@ -4318,8 +4326,6 @@ static const CRPCCommand commands[] =
};
// clang-format on
-void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector<std::unique_ptr<interfaces::Handler>>& handlers)
-{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
handlers.emplace_back(chain.handleRpc(commands[vcidx]));
}
diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h
index 2813fa2bfc..8c149d455b 100644
--- a/src/wallet/rpcwallet.h
+++ b/src/wallet/rpcwallet.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -38,7 +38,6 @@ void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector<std::unique
*/
std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
-std::string HelpRequiringPassphrase(const CWallet*);
void EnsureWalletIsUnlocked(const CWallet*);
bool EnsureWalletIsAvailable(const CWallet*, bool avoidException);
LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_create = false);
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 4c9d88973e..ecb95d599d 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -1,12 +1,14 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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 <key_io.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/translation.h>
#include <wallet/scriptpubkeyman.h>
@@ -18,7 +20,7 @@ bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestinat
// Generate a new key that is added to wallet
CPubKey new_key;
if (!GetKeyFromPool(new_key, type)) {
- error = "Error: Keypool ran out, please call keypoolrefill first";
+ error = _("Error: Keypool ran out, please call keypoolrefill first").translated;
return false;
}
LearnRelatedScripts(new_key, type);
@@ -70,7 +72,15 @@ bool HaveKeys(const std::vector<valtype>& pubkeys, const LegacyScriptPubKeyMan&
return true;
}
-IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& scriptPubKey, IsMineSigVersion sigversion)
+//! Recursively solve script and return spendable/watchonly/invalid status.
+//!
+//! @param keystore legacy key and script store
+//! @param script script to solve
+//! @param sigversion script type (top-level / redeemscript / witnessscript)
+//! @param recurse_scripthash whether to recurse into nested p2sh and p2wsh
+//! scripts or simply treat any script that has been
+//! stored in the keystore as spendable
+IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& scriptPubKey, IsMineSigVersion sigversion, bool recurse_scripthash=true)
{
IsMineResult ret = IsMineResult::NO;
@@ -129,7 +139,7 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- ret = std::max(ret, IsMineInner(keystore, subscript, IsMineSigVersion::P2SH));
+ ret = std::max(ret, recurse_scripthash ? IsMineInner(keystore, subscript, IsMineSigVersion::P2SH) : IsMineResult::SPENDABLE);
}
break;
}
@@ -147,7 +157,7 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
CScriptID scriptID = CScriptID(hash);
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- ret = std::max(ret, IsMineInner(keystore, subscript, IsMineSigVersion::WITNESS_V0));
+ ret = std::max(ret, recurse_scripthash ? IsMineInner(keystore, subscript, IsMineSigVersion::WITNESS_V0) : IsMineResult::SPENDABLE);
}
break;
}
@@ -350,7 +360,7 @@ bool LegacyScriptPubKeyMan::IsHDEnabled() const
return !hdChain.seed_id.IsNull();
}
-bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal)
+bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal) const
{
LOCK(cs_KeyStore);
// Check if the keypool has keys
@@ -433,7 +443,7 @@ static int64_t GetOldestKeyTimeInPool(const std::set<int64_t>& setKeyPool, Walle
return keypool.nTime;
}
-int64_t LegacyScriptPubKeyMan::GetOldestKeyPoolTime()
+int64_t LegacyScriptPubKeyMan::GetOldestKeyPoolTime() const
{
LOCK(cs_KeyStore);
@@ -451,7 +461,7 @@ int64_t LegacyScriptPubKeyMan::GetOldestKeyPoolTime()
return oldestKey;
}
-size_t LegacyScriptPubKeyMan::KeypoolCountExternalKeys()
+size_t LegacyScriptPubKeyMan::KeypoolCountExternalKeys() const
{
LOCK(cs_KeyStore);
return setExternalKeyPool.size() + set_pre_split_keypool.size();
@@ -469,18 +479,18 @@ int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const
return nTimeFirstKey;
}
-std::unique_ptr<SigningProvider> LegacyScriptPubKeyMan::GetSigningProvider(const CScript& script) const
+std::unique_ptr<SigningProvider> LegacyScriptPubKeyMan::GetSolvingProvider(const CScript& script) const
{
return MakeUnique<LegacySigningProvider>(*this);
}
bool LegacyScriptPubKeyMan::CanProvide(const CScript& script, SignatureData& sigdata)
{
- if (IsMine(script) != ISMINE_NO) {
- // If it IsMine, we can always provide in some way
- return true;
- } else if (HaveCScript(CScriptID(script))) {
- // We can still provide some stuff if we have the script, but IsMine failed because we don't have keys
+ IsMineResult ismine = IsMineInner(*this, script, IsMineSigVersion::TOP, /* recurse_scripthash= */ false);
+ if (ismine == IsMineResult::SPENDABLE || ismine == IsMineResult::WATCH_ONLY) {
+ // If ismine, it means we recognize keys or script ids in the script, or
+ // are watching the script itself, and we can at least provide metadata
+ // or solving information, even if not able to sign fully.
return true;
} else {
// If, given the stuff in sigdata, we could make a valid sigature, then we can provide for this script
@@ -497,7 +507,68 @@ bool LegacyScriptPubKeyMan::CanProvide(const CScript& script, SignatureData& sig
}
}
-const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
+bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
+{
+ return ::SignTransaction(tx, this, coins, sighash, input_errors);
+}
+
+SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
+{
+ CKeyID key_id(pkhash);
+ CKey key;
+ if (!GetKey(key_id, key)) {
+ return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
+ }
+
+ if (MessageSign(key, message, str_sig)) {
+ return SigningResult::OK;
+ }
+ return SigningResult::SIGNING_FAILED;
+}
+
+TransactionError LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs) const
+{
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ const CTxIn& txin = psbtx.tx->vin[i];
+ PSBTInput& input = psbtx.inputs.at(i);
+
+ if (PSBTInputSigned(input)) {
+ continue;
+ }
+
+ // Verify input looks sane. This will check that we have at most one uxto, witness or non-witness.
+ if (!input.IsSane()) {
+ return TransactionError::INVALID_PSBT;
+ }
+
+ // Get the Sighash type
+ if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
+ return TransactionError::SIGHASH_MISMATCH;
+ }
+
+ // Check non_witness_utxo has specified prevout
+ if (input.non_witness_utxo) {
+ if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
+ return TransactionError::MISSING_INPUTS;
+ }
+ } else if (input.witness_utxo.IsNull()) {
+ // There's no UTXO so we can just skip this now
+ continue;
+ }
+ SignatureData sigdata;
+ input.FillSignatureData(sigdata);
+ SignPSBTInput(HidingSigningProvider(this, !sign, !bip32derivs), psbtx, i, sighash_type);
+ }
+
+ // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
+ for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
+ UpdatePSBTOutput(HidingSigningProvider(this, true, !bip32derivs), psbtx, i);
+ }
+
+ return TransactionError::OK;
+}
+
+std::unique_ptr<CKeyMetadata> LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
{
LOCK(cs_KeyStore);
@@ -505,14 +576,14 @@ const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& des
if (!key_id.IsNull()) {
auto it = mapKeyMetadata.find(key_id);
if (it != mapKeyMetadata.end()) {
- return &it->second;
+ return MakeUnique<CKeyMetadata>(it->second);
}
}
CScript scriptPubKey = GetScriptForDestination(dest);
auto it = m_script_metadata.find(CScriptID(scriptPubKey));
if (it != m_script_metadata.end()) {
- return &it->second;
+ return MakeUnique<CKeyMetadata>(it->second);
}
return nullptr;
@@ -919,7 +990,7 @@ void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata&
// example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
if (internal) {
chainChildKey.Derive(childKey, hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
- metadata.hdKeypath = "m/0'/1'/" + std::to_string(hdChain.nInternalChainCounter) + "'";
+ metadata.hdKeypath = "m/0'/1'/" + ToString(hdChain.nInternalChainCounter) + "'";
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
metadata.key_origin.path.push_back(1 | BIP32_HARDENED_KEY_LIMIT);
metadata.key_origin.path.push_back(hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
@@ -927,7 +998,7 @@ void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata&
}
else {
chainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
- metadata.hdKeypath = "m/0'/0'/" + std::to_string(hdChain.nExternalChainCounter) + "'";
+ metadata.hdKeypath = "m/0'/0'/" + ToString(hdChain.nExternalChainCounter) + "'";
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
metadata.key_origin.path.push_back(hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
@@ -965,7 +1036,7 @@ void LegacyScriptPubKeyMan::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime);
}
-bool LegacyScriptPubKeyMan::CanGenerateKeys()
+bool LegacyScriptPubKeyMan::CanGenerateKeys() const
{
// A wallet can generate keys if it has an HD seed (IsHDEnabled) or it is a non-HD wallet (pre FEATURE_HD)
LOCK(cs_KeyStore);
@@ -1426,3 +1497,668 @@ std::set<CKeyID> LegacyScriptPubKeyMan::GetKeys() const
}
return set_address;
}
+
+void LegacyScriptPubKeyMan::SetType(OutputType type, bool internal) {}
+
+bool DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error)
+{
+ // Returns true if this descriptor supports getting new addresses. Conditions where we may be unable to fetch them (e.g. locked) are caught later
+ if (!CanGetAddresses(m_internal)) {
+ error = "No addresses available";
+ return false;
+ }
+ {
+ LOCK(cs_desc_man);
+ assert(m_wallet_descriptor.descriptor->IsSingleType()); // This is a combo descriptor which should not be an active descriptor
+ if (type != m_address_type) {
+ throw std::runtime_error(std::string(__func__) + ": Types are inconsistent");
+ }
+
+ TopUp();
+
+ // Get the scriptPubKey from the descriptor
+ FlatSigningProvider out_keys;
+ std::vector<CScript> scripts_temp;
+ if (m_wallet_descriptor.range_end <= m_max_cached_index && !TopUp(1)) {
+ // We can't generate anymore keys
+ error = "Error: Keypool ran out, please call keypoolrefill first";
+ return false;
+ }
+ if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
+ // We can't generate anymore keys
+ error = "Error: Keypool ran out, please call keypoolrefill first";
+ return false;
+ }
+
+ Optional<OutputType> out_script_type = m_wallet_descriptor.descriptor->GetOutputType();
+ if (out_script_type && out_script_type == type) {
+ ExtractDestination(scripts_temp[0], dest);
+ } else {
+ throw std::runtime_error(std::string(__func__) + ": Types are inconsistent. Stored type does not match type of newly generated address");
+ }
+ m_wallet_descriptor.next_index++;
+ WalletBatch(m_storage.GetDatabase()).WriteDescriptor(GetID(), m_wallet_descriptor);
+ return true;
+ }
+}
+
+isminetype DescriptorScriptPubKeyMan::IsMine(const CScript& script) const
+{
+ LOCK(cs_desc_man);
+ if (m_map_script_pub_keys.count(script) > 0) {
+ return ISMINE_SPENDABLE;
+ }
+ return ISMINE_NO;
+}
+
+bool DescriptorScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys)
+{
+ LOCK(cs_desc_man);
+ if (!m_map_keys.empty()) {
+ return false;
+ }
+
+ bool keyPass = m_map_crypted_keys.empty(); // Always pass when there are no encrypted keys
+ bool keyFail = false;
+ for (const auto& mi : m_map_crypted_keys) {
+ const CPubKey &pubkey = mi.second.first;
+ const std::vector<unsigned char> &crypted_secret = mi.second.second;
+ CKey key;
+ if (!DecryptKey(master_key, crypted_secret, pubkey, key)) {
+ keyFail = true;
+ break;
+ }
+ keyPass = true;
+ if (m_decryption_thoroughly_checked)
+ break;
+ }
+ if (keyPass && keyFail) {
+ LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
+ throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
+ }
+ if (keyFail || (!keyPass && !accept_no_keys)) {
+ return false;
+ }
+ m_decryption_thoroughly_checked = true;
+ return true;
+}
+
+bool DescriptorScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch)
+{
+ LOCK(cs_desc_man);
+ if (!m_map_crypted_keys.empty()) {
+ return false;
+ }
+
+ for (const KeyMap::value_type& key_in : m_map_keys)
+ {
+ const CKey &key = key_in.second;
+ CPubKey pubkey = key.GetPubKey();
+ CKeyingMaterial secret(key.begin(), key.end());
+ std::vector<unsigned char> crypted_secret;
+ if (!EncryptSecret(master_key, secret, pubkey.GetHash(), crypted_secret)) {
+ return false;
+ }
+ m_map_crypted_keys[pubkey.GetID()] = make_pair(pubkey, crypted_secret);
+ batch->WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret);
+ }
+ m_map_keys.clear();
+ return true;
+}
+
+bool DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool)
+{
+ LOCK(cs_desc_man);
+ std::string error;
+ bool result = GetNewDestination(type, address, error);
+ index = m_wallet_descriptor.next_index - 1;
+ return result;
+}
+
+void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CTxDestination& addr)
+{
+ LOCK(cs_desc_man);
+ // Only return when the index was the most recent
+ if (m_wallet_descriptor.next_index - 1 == index) {
+ m_wallet_descriptor.next_index--;
+ }
+ WalletBatch(m_storage.GetDatabase()).WriteDescriptor(GetID(), m_wallet_descriptor);
+ NotifyCanGetAddressesChanged();
+}
+
+std::map<CKeyID, CKey> DescriptorScriptPubKeyMan::GetKeys() const
+{
+ AssertLockHeld(cs_desc_man);
+ if (m_storage.HasEncryptionKeys() && !m_storage.IsLocked()) {
+ KeyMap keys;
+ for (auto key_pair : m_map_crypted_keys) {
+ const CPubKey& pubkey = key_pair.second.first;
+ const std::vector<unsigned char>& crypted_secret = key_pair.second.second;
+ CKey key;
+ DecryptKey(m_storage.GetEncryptionKey(), crypted_secret, pubkey, key);
+ keys[pubkey.GetID()] = key;
+ }
+ return keys;
+ }
+ return m_map_keys;
+}
+
+bool DescriptorScriptPubKeyMan::TopUp(unsigned int size)
+{
+ LOCK(cs_desc_man);
+ unsigned int target_size;
+ if (size > 0) {
+ target_size = size;
+ } else {
+ target_size = std::max(gArgs.GetArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 1);
+ }
+
+ // Calculate the new range_end
+ int32_t new_range_end = std::max(m_wallet_descriptor.next_index + (int32_t)target_size, m_wallet_descriptor.range_end);
+
+ // If the descriptor is not ranged, we actually just want to fill the first cache item
+ if (!m_wallet_descriptor.descriptor->IsRange()) {
+ new_range_end = 1;
+ m_wallet_descriptor.range_end = 1;
+ m_wallet_descriptor.range_start = 0;
+ }
+
+ FlatSigningProvider provider;
+ provider.keys = GetKeys();
+
+ WalletBatch batch(m_storage.GetDatabase());
+ uint256 id = GetID();
+ for (int32_t i = m_max_cached_index + 1; i < new_range_end; ++i) {
+ FlatSigningProvider out_keys;
+ std::vector<CScript> scripts_temp;
+ DescriptorCache temp_cache;
+ // Maybe we have a cached xpub and we can expand from the cache first
+ if (!m_wallet_descriptor.descriptor->ExpandFromCache(i, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
+ if (!m_wallet_descriptor.descriptor->Expand(i, provider, scripts_temp, out_keys, &temp_cache)) return false;
+ }
+ // Add all of the scriptPubKeys to the scriptPubKey set
+ for (const CScript& script : scripts_temp) {
+ m_map_script_pub_keys[script] = i;
+ }
+ for (const auto& pk_pair : out_keys.pubkeys) {
+ const CPubKey& pubkey = pk_pair.second;
+ if (m_map_pubkeys.count(pubkey) != 0) {
+ // We don't need to give an error here.
+ // It doesn't matter which of many valid indexes the pubkey has, we just need an index where we can derive it and it's private key
+ continue;
+ }
+ m_map_pubkeys[pubkey] = i;
+ }
+ // Write the cache
+ for (const auto& parent_xpub_pair : temp_cache.GetCachedParentExtPubKeys()) {
+ CExtPubKey xpub;
+ if (m_wallet_descriptor.cache.GetCachedParentExtPubKey(parent_xpub_pair.first, xpub)) {
+ if (xpub != parent_xpub_pair.second) {
+ throw std::runtime_error(std::string(__func__) + ": New cached parent xpub does not match already cached parent xpub");
+ }
+ continue;
+ }
+ if (!batch.WriteDescriptorParentCache(parent_xpub_pair.second, id, parent_xpub_pair.first)) {
+ throw std::runtime_error(std::string(__func__) + ": writing cache item failed");
+ }
+ m_wallet_descriptor.cache.CacheParentExtPubKey(parent_xpub_pair.first, parent_xpub_pair.second);
+ }
+ for (const auto& derived_xpub_map_pair : temp_cache.GetCachedDerivedExtPubKeys()) {
+ for (const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
+ CExtPubKey xpub;
+ if (m_wallet_descriptor.cache.GetCachedDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, xpub)) {
+ if (xpub != derived_xpub_pair.second) {
+ throw std::runtime_error(std::string(__func__) + ": New cached derived xpub does not match already cached derived xpub");
+ }
+ continue;
+ }
+ if (!batch.WriteDescriptorDerivedCache(derived_xpub_pair.second, id, derived_xpub_map_pair.first, derived_xpub_pair.first)) {
+ throw std::runtime_error(std::string(__func__) + ": writing cache item failed");
+ }
+ m_wallet_descriptor.cache.CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
+ }
+ }
+ m_max_cached_index++;
+ }
+ m_wallet_descriptor.range_end = new_range_end;
+ batch.WriteDescriptor(GetID(), m_wallet_descriptor);
+
+ // By this point, the cache size should be the size of the entire range
+ assert(m_wallet_descriptor.range_end - 1 == m_max_cached_index);
+
+ NotifyCanGetAddressesChanged();
+ return true;
+}
+
+void DescriptorScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
+{
+ LOCK(cs_desc_man);
+ if (IsMine(script)) {
+ int32_t index = m_map_script_pub_keys[script];
+ if (index >= m_wallet_descriptor.next_index) {
+ WalletLogPrintf("%s: Detected a used keypool item at index %d, mark all keypool items up to this item as used\n", __func__, index);
+ m_wallet_descriptor.next_index = index + 1;
+ }
+ if (!TopUp()) {
+ WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
+ }
+ }
+}
+
+void DescriptorScriptPubKeyMan::AddDescriptorKey(const CKey& key, const CPubKey &pubkey)
+{
+ LOCK(cs_desc_man);
+ WalletBatch batch(m_storage.GetDatabase());
+ if (!AddDescriptorKeyWithDB(batch, key, pubkey)) {
+ throw std::runtime_error(std::string(__func__) + ": writing descriptor private key failed");
+ }
+}
+
+bool DescriptorScriptPubKeyMan::AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey)
+{
+ AssertLockHeld(cs_desc_man);
+ assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
+
+ if (m_storage.HasEncryptionKeys()) {
+ if (m_storage.IsLocked()) {
+ return false;
+ }
+
+ std::vector<unsigned char> crypted_secret;
+ CKeyingMaterial secret(key.begin(), key.end());
+ if (!EncryptSecret(m_storage.GetEncryptionKey(), secret, pubkey.GetHash(), crypted_secret)) {
+ return false;
+ }
+
+ m_map_crypted_keys[pubkey.GetID()] = make_pair(pubkey, crypted_secret);
+ return batch.WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret);
+ } else {
+ m_map_keys[pubkey.GetID()] = key;
+ return batch.WriteDescriptorKey(GetID(), pubkey, key.GetPrivKey());
+ }
+}
+
+bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_key)
+{
+ LOCK(cs_desc_man);
+ assert(m_storage.IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
+
+ // Ignore when there is already a descriptor
+ if (m_wallet_descriptor.descriptor) {
+ return false;
+ }
+
+ int64_t creation_time = GetTime();
+
+ std::string xpub = EncodeExtPubKey(master_key.Neuter());
+
+ // Build descriptor string
+ std::string desc_prefix;
+ std::string desc_suffix = "/*)";
+ switch (m_address_type) {
+ case OutputType::LEGACY: {
+ desc_prefix = "pkh(" + xpub + "/44'";
+ break;
+ }
+ case OutputType::P2SH_SEGWIT: {
+ desc_prefix = "sh(wpkh(" + xpub + "/49'";
+ desc_suffix += ")";
+ break;
+ }
+ case OutputType::BECH32: {
+ desc_prefix = "wpkh(" + xpub + "/84'";
+ break;
+ }
+ default: assert(false);
+ }
+
+ // Mainnet derives at 0', testnet and regtest derive at 1'
+ if (Params().IsTestChain()) {
+ desc_prefix += "/1'";
+ } else {
+ desc_prefix += "/0'";
+ }
+
+ std::string internal_path = m_internal ? "/1" : "/0";
+ std::string desc_str = desc_prefix + "/0'" + internal_path + desc_suffix;
+
+ // Make the descriptor
+ FlatSigningProvider keys;
+ std::string error;
+ std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, error, false);
+ WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
+ m_wallet_descriptor = w_desc;
+
+ // Store the master private key, and descriptor
+ WalletBatch batch(m_storage.GetDatabase());
+ if (!AddDescriptorKeyWithDB(batch, master_key.key, master_key.key.GetPubKey())) {
+ throw std::runtime_error(std::string(__func__) + ": writing descriptor master private key failed");
+ }
+ if (!batch.WriteDescriptor(GetID(), m_wallet_descriptor)) {
+ throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");
+ }
+
+ // TopUp
+ TopUp();
+
+ m_storage.UnsetBlankWalletFlag(batch);
+ return true;
+}
+
+bool DescriptorScriptPubKeyMan::IsHDEnabled() const
+{
+ LOCK(cs_desc_man);
+ return m_wallet_descriptor.descriptor->IsRange();
+}
+
+bool DescriptorScriptPubKeyMan::CanGetAddresses(bool internal) const
+{
+ // We can only give out addresses from descriptors that are single type (not combo), ranged,
+ // and either have cached keys or can generate more keys (ignoring encryption)
+ LOCK(cs_desc_man);
+ return m_wallet_descriptor.descriptor->IsSingleType() &&
+ m_wallet_descriptor.descriptor->IsRange() &&
+ (HavePrivateKeys() || m_wallet_descriptor.next_index < m_wallet_descriptor.range_end);
+}
+
+bool DescriptorScriptPubKeyMan::HavePrivateKeys() const
+{
+ LOCK(cs_desc_man);
+ return m_map_keys.size() > 0 || m_map_crypted_keys.size() > 0;
+}
+
+int64_t DescriptorScriptPubKeyMan::GetOldestKeyPoolTime() const
+{
+ // This is only used for getwalletinfo output and isn't relevant to descriptor wallets.
+ // The magic number 0 indicates that it shouldn't be displayed so that's what we return.
+ return 0;
+}
+
+size_t DescriptorScriptPubKeyMan::KeypoolCountExternalKeys() const
+{
+ if (m_internal) {
+ return 0;
+ }
+ return GetKeyPoolSize();
+}
+
+unsigned int DescriptorScriptPubKeyMan::GetKeyPoolSize() const
+{
+ LOCK(cs_desc_man);
+ return m_wallet_descriptor.range_end - m_wallet_descriptor.next_index;
+}
+
+int64_t DescriptorScriptPubKeyMan::GetTimeFirstKey() const
+{
+ LOCK(cs_desc_man);
+ return m_wallet_descriptor.creation_time;
+}
+
+std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(const CScript& script, bool include_private) const
+{
+ LOCK(cs_desc_man);
+
+ // Find the index of the script
+ auto it = m_map_script_pub_keys.find(script);
+ if (it == m_map_script_pub_keys.end()) {
+ return nullptr;
+ }
+ int32_t index = it->second;
+
+ return GetSigningProvider(index, include_private);
+}
+
+std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(const CPubKey& pubkey) const
+{
+ LOCK(cs_desc_man);
+
+ // Find index of the pubkey
+ auto it = m_map_pubkeys.find(pubkey);
+ if (it == m_map_pubkeys.end()) {
+ return nullptr;
+ }
+ int32_t index = it->second;
+
+ // Always try to get the signing provider with private keys. This function should only be called during signing anyways
+ return GetSigningProvider(index, true);
+}
+
+std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(int32_t index, bool include_private) const
+{
+ AssertLockHeld(cs_desc_man);
+ // Get the scripts, keys, and key origins for this script
+ std::unique_ptr<FlatSigningProvider> out_keys = MakeUnique<FlatSigningProvider>();
+ std::vector<CScript> scripts_temp;
+ if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;
+
+ if (HavePrivateKeys() && include_private) {
+ FlatSigningProvider master_provider;
+ master_provider.keys = GetKeys();
+ m_wallet_descriptor.descriptor->ExpandPrivate(index, master_provider, *out_keys);
+ }
+
+ return out_keys;
+}
+
+std::unique_ptr<SigningProvider> DescriptorScriptPubKeyMan::GetSolvingProvider(const CScript& script) const
+{
+ return GetSigningProvider(script, false);
+}
+
+bool DescriptorScriptPubKeyMan::CanProvide(const CScript& script, SignatureData& sigdata)
+{
+ return IsMine(script);
+}
+
+bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
+{
+ std::unique_ptr<FlatSigningProvider> keys = MakeUnique<FlatSigningProvider>();
+ for (const auto& coin_pair : coins) {
+ std::unique_ptr<FlatSigningProvider> coin_keys = GetSigningProvider(coin_pair.second.out.scriptPubKey, true);
+ if (!coin_keys) {
+ continue;
+ }
+ *keys = Merge(*keys, *coin_keys);
+ }
+
+ return ::SignTransaction(tx, keys.get(), coins, sighash, input_errors);
+}
+
+SigningResult DescriptorScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
+{
+ std::unique_ptr<FlatSigningProvider> keys = GetSigningProvider(GetScriptForDestination(pkhash), true);
+ if (!keys) {
+ return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
+ }
+
+ CKeyID key_id(pkhash);
+ CKey key;
+ if (!keys->GetKey(key_id, key)) {
+ return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
+ }
+
+ if (!MessageSign(key, message, str_sig)) {
+ return SigningResult::SIGNING_FAILED;
+ }
+ return SigningResult::OK;
+}
+
+TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs) const
+{
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ const CTxIn& txin = psbtx.tx->vin[i];
+ PSBTInput& input = psbtx.inputs.at(i);
+
+ if (PSBTInputSigned(input)) {
+ continue;
+ }
+
+ // Verify input looks sane. This will check that we have at most one uxto, witness or non-witness.
+ if (!input.IsSane()) {
+ return TransactionError::INVALID_PSBT;
+ }
+
+ // Get the Sighash type
+ if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
+ return TransactionError::SIGHASH_MISMATCH;
+ }
+
+ // Get the scriptPubKey to know which SigningProvider to use
+ CScript script;
+ if (!input.witness_utxo.IsNull()) {
+ script = input.witness_utxo.scriptPubKey;
+ } else if (input.non_witness_utxo) {
+ if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
+ return TransactionError::MISSING_INPUTS;
+ }
+ script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey;
+ } else {
+ // There's no UTXO so we can just skip this now
+ continue;
+ }
+ SignatureData sigdata;
+ input.FillSignatureData(sigdata);
+
+ std::unique_ptr<FlatSigningProvider> keys = MakeUnique<FlatSigningProvider>();
+ std::unique_ptr<FlatSigningProvider> script_keys = GetSigningProvider(script, sign);
+ if (script_keys) {
+ *keys = Merge(*keys, *script_keys);
+ } else {
+ // Maybe there are pubkeys listed that we can sign for
+ script_keys = MakeUnique<FlatSigningProvider>();
+ for (const auto& pk_pair : input.hd_keypaths) {
+ const CPubKey& pubkey = pk_pair.first;
+ std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(pubkey);
+ if (pk_keys) {
+ *keys = Merge(*keys, *pk_keys);
+ }
+ }
+ }
+
+ SignPSBTInput(HidingSigningProvider(keys.get(), !sign, !bip32derivs), psbtx, i, sighash_type);
+ }
+
+ // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
+ for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
+ std::unique_ptr<SigningProvider> keys = GetSolvingProvider(psbtx.tx->vout.at(i).scriptPubKey);
+ if (!keys) {
+ continue;
+ }
+ UpdatePSBTOutput(HidingSigningProvider(keys.get(), true, !bip32derivs), psbtx, i);
+ }
+
+ return TransactionError::OK;
+}
+
+std::unique_ptr<CKeyMetadata> DescriptorScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
+{
+ std::unique_ptr<SigningProvider> provider = GetSigningProvider(GetScriptForDestination(dest));
+ if (provider) {
+ KeyOriginInfo orig;
+ CKeyID key_id = GetKeyForDestination(*provider, dest);
+ if (provider->GetKeyOrigin(key_id, orig)) {
+ LOCK(cs_desc_man);
+ std::unique_ptr<CKeyMetadata> meta = MakeUnique<CKeyMetadata>();
+ meta->key_origin = orig;
+ meta->has_key_origin = true;
+ meta->nCreateTime = m_wallet_descriptor.creation_time;
+ return meta;
+ }
+ }
+ return nullptr;
+}
+
+uint256 DescriptorScriptPubKeyMan::GetID() const
+{
+ LOCK(cs_desc_man);
+ std::string desc_str = m_wallet_descriptor.descriptor->ToString();
+ uint256 id;
+ CSHA256().Write((unsigned char*)desc_str.data(), desc_str.size()).Finalize(id.begin());
+ return id;
+}
+
+void DescriptorScriptPubKeyMan::SetType(OutputType type, bool internal)
+{
+ this->m_address_type = type;
+ this->m_internal = internal;
+}
+
+void DescriptorScriptPubKeyMan::SetCache(const DescriptorCache& cache)
+{
+ LOCK(cs_desc_man);
+ m_wallet_descriptor.cache = cache;
+ for (int32_t i = m_wallet_descriptor.range_start; i < m_wallet_descriptor.range_end; ++i) {
+ FlatSigningProvider out_keys;
+ std::vector<CScript> scripts_temp;
+ if (!m_wallet_descriptor.descriptor->ExpandFromCache(i, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
+ throw std::runtime_error("Error: Unable to expand wallet descriptor from cache");
+ }
+ // Add all of the scriptPubKeys to the scriptPubKey set
+ for (const CScript& script : scripts_temp) {
+ if (m_map_script_pub_keys.count(script) != 0) {
+ throw std::runtime_error(strprintf("Error: Already loaded script at index %d as being at index %d", i, m_map_script_pub_keys[script]));
+ }
+ m_map_script_pub_keys[script] = i;
+ }
+ for (const auto& pk_pair : out_keys.pubkeys) {
+ const CPubKey& pubkey = pk_pair.second;
+ if (m_map_pubkeys.count(pubkey) != 0) {
+ // We don't need to give an error here.
+ // It doesn't matter which of many valid indexes the pubkey has, we just need an index where we can derive it and it's private key
+ continue;
+ }
+ m_map_pubkeys[pubkey] = i;
+ }
+ m_max_cached_index++;
+ }
+}
+
+bool DescriptorScriptPubKeyMan::AddKey(const CKeyID& key_id, const CKey& key)
+{
+ LOCK(cs_desc_man);
+ m_map_keys[key_id] = key;
+ return true;
+}
+
+bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key)
+{
+ LOCK(cs_desc_man);
+ if (!m_map_keys.empty()) {
+ return false;
+ }
+
+ m_map_crypted_keys[key_id] = make_pair(pubkey, crypted_key);
+ return true;
+}
+
+bool DescriptorScriptPubKeyMan::HasWalletDescriptor(const WalletDescriptor& desc) const
+{
+ LOCK(cs_desc_man);
+ return m_wallet_descriptor.descriptor != nullptr && desc.descriptor != nullptr && m_wallet_descriptor.descriptor->ToString() == desc.descriptor->ToString();
+}
+
+void DescriptorScriptPubKeyMan::WriteDescriptor()
+{
+ LOCK(cs_desc_man);
+ WalletBatch batch(m_storage.GetDatabase());
+ if (!batch.WriteDescriptor(GetID(), m_wallet_descriptor)) {
+ throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");
+ }
+}
+
+const WalletDescriptor DescriptorScriptPubKeyMan::GetWalletDescriptor() const
+{
+ return m_wallet_descriptor;
+}
+
+const std::vector<CScript> DescriptorScriptPubKeyMan::GetScriptPubKeys() const
+{
+ LOCK(cs_desc_man);
+ std::vector<CScript> script_pub_keys;
+ script_pub_keys.reserve(m_map_script_pub_keys.size());
+
+ for (auto const& script_pub_key: m_map_script_pub_keys) {
+ script_pub_keys.push_back(script_pub_key.first);
+ }
+ return script_pub_keys;
+}
diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h
index 7b1c023bc9..3117b13d35 100644
--- a/src/wallet/scriptpubkeyman.h
+++ b/src/wallet/scriptpubkeyman.h
@@ -5,8 +5,12 @@
#ifndef BITCOIN_WALLET_SCRIPTPUBKEYMAN_H
#define BITCOIN_WALLET_SCRIPTPUBKEYMAN_H
+#include <psbt.h>
+#include <script/descriptor.h>
#include <script/signingprovider.h>
#include <script/standard.h>
+#include <util/error.h>
+#include <util/message.h>
#include <wallet/crypter.h>
#include <wallet/ismine.h>
#include <wallet/walletdb.h>
@@ -184,7 +188,7 @@ public:
virtual bool IsHDEnabled() const { return false; }
/* Returns true if the wallet can give out new addresses. This means it has keys in the keypool or can generate new keys */
- virtual bool CanGetAddresses(bool internal = false) { return false; }
+ virtual bool CanGetAddresses(bool internal = false) const { return false; }
/** Upgrades the wallet to the specified version */
virtual bool Upgrade(int prev_version, std::string& error) { return false; }
@@ -194,24 +198,33 @@ public:
//! The action to do when the DB needs rewrite
virtual void RewriteDB() {}
- virtual int64_t GetOldestKeyPoolTime() { return GetTime(); }
+ virtual int64_t GetOldestKeyPoolTime() const { return GetTime(); }
- virtual size_t KeypoolCountExternalKeys() { return 0; }
+ virtual size_t KeypoolCountExternalKeys() const { return 0; }
virtual unsigned int GetKeyPoolSize() const { return 0; }
virtual int64_t GetTimeFirstKey() const { return 0; }
- virtual const CKeyMetadata* GetMetadata(const CTxDestination& dest) const { return nullptr; }
+ virtual std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const { return nullptr; }
- virtual std::unique_ptr<SigningProvider> GetSigningProvider(const CScript& script) const { return nullptr; }
+ virtual std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const { return nullptr; }
- /** Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSigningProvider) that, combined with
- * sigdata, can produce a valid signature.
+ /** Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSolvingProvider) that, combined with
+ * sigdata, can produce solving data.
*/
virtual bool CanProvide(const CScript& script, SignatureData& sigdata) { return false; }
+ /** Creates new signatures and adds them to the transaction. Returns whether all inputs were signed */
+ virtual bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const { return false; }
+ /** Sign a message with the given script */
+ virtual SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const { return SigningResult::SIGNING_FAILED; };
+ /** Adds script and derivation path information to a PSBT, and optionally signs it. */
+ virtual TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false) const { return TransactionError::INVALID_PSBT; }
+
virtual uint256 GetID() const { return uint256(); }
+ virtual void SetType(OutputType type, bool internal) {}
+
/** Prepends the wallet name in logging output to ease debugging in multi-wallet use cases */
template<typename... Params>
void WalletLogPrintf(std::string fmt, Params... parameters) const {
@@ -336,22 +349,28 @@ public:
void RewriteDB() override;
- int64_t GetOldestKeyPoolTime() override;
- size_t KeypoolCountExternalKeys() override;
+ int64_t GetOldestKeyPoolTime() const override;
+ size_t KeypoolCountExternalKeys() const override;
unsigned int GetKeyPoolSize() const override;
int64_t GetTimeFirstKey() const override;
- const CKeyMetadata* GetMetadata(const CTxDestination& dest) const override;
+ std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const override;
- bool CanGetAddresses(bool internal = false) override;
+ bool CanGetAddresses(bool internal = false) const override;
- std::unique_ptr<SigningProvider> GetSigningProvider(const CScript& script) const override;
+ std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const override;
bool CanProvide(const CScript& script, SignatureData& sigdata) override;
+ bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const override;
+ SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
+ TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false) const override;
+
uint256 GetID() const override;
+ void SetType(OutputType type, bool internal) override;
+
// Map from Key ID to key metadata.
std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_KeyStore);
@@ -410,7 +429,7 @@ public:
bool ImportScriptPubKeys(const std::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
/* Returns true if the wallet can generate new keys */
- bool CanGenerateKeys();
+ bool CanGenerateKeys() const;
/* Generates a new HD seed (will not be activated) */
CPubKey GenerateNewSeed();
@@ -447,7 +466,7 @@ public:
std::set<CKeyID> GetKeys() const override;
};
-/** Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr */
+/** Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr. Does not provide privkeys */
class LegacySigningProvider : public SigningProvider
{
private:
@@ -458,9 +477,116 @@ public:
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); }
bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const override { return m_spk_man.GetPubKey(address, pubkey); }
- bool GetKey(const CKeyID &address, CKey& key) const override { return m_spk_man.GetKey(address, key); }
- bool HaveKey(const CKeyID &address) const override { return m_spk_man.HaveKey(address); }
+ bool GetKey(const CKeyID &address, CKey& key) const override { return false; }
+ bool HaveKey(const CKeyID &address) const override { return false; }
bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override { return m_spk_man.GetKeyOrigin(keyid, info); }
};
+class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
+{
+private:
+ WalletDescriptor m_wallet_descriptor GUARDED_BY(cs_desc_man);
+
+ using ScriptPubKeyMap = std::map<CScript, int32_t>; // Map of scripts to descriptor range index
+ using PubKeyMap = std::map<CPubKey, int32_t>; // Map of pubkeys involved in scripts to descriptor range index
+ using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
+ using KeyMap = std::map<CKeyID, CKey>;
+
+ ScriptPubKeyMap m_map_script_pub_keys GUARDED_BY(cs_desc_man);
+ PubKeyMap m_map_pubkeys GUARDED_BY(cs_desc_man);
+ int32_t m_max_cached_index = -1;
+
+ OutputType m_address_type;
+ bool m_internal;
+
+ KeyMap m_map_keys GUARDED_BY(cs_desc_man);
+ CryptedKeyMap m_map_crypted_keys GUARDED_BY(cs_desc_man);
+
+ bool SetCrypted();
+
+ //! keeps track of whether Unlock has run a thorough check before
+ bool m_decryption_thoroughly_checked = false;
+
+ bool AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey);
+
+ KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
+
+ // Fetch the SigningProvider for the given script and optionally include private keys
+ std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CScript& script, bool include_private = false) const;
+ // Fetch the SigningProvider for the given pubkey and always include private keys. This should only be called by signing code.
+ std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CPubKey& pubkey) const;
+ // Fetch the SigningProvider for a given index and optionally include private keys. Called by the above functions.
+ std::unique_ptr<FlatSigningProvider> GetSigningProvider(int32_t index, bool include_private = false) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
+
+public:
+ DescriptorScriptPubKeyMan(WalletStorage& storage, WalletDescriptor& descriptor)
+ : ScriptPubKeyMan(storage),
+ m_wallet_descriptor(descriptor)
+ {}
+ DescriptorScriptPubKeyMan(WalletStorage& storage, OutputType address_type, bool internal)
+ : ScriptPubKeyMan(storage),
+ m_address_type(address_type), m_internal(internal)
+ {}
+
+ mutable RecursiveMutex cs_desc_man;
+
+ bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) override;
+ isminetype IsMine(const CScript& script) const override;
+
+ bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
+ bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
+
+ bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool) override;
+ void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) override;
+
+ // Tops up the descriptor cache and m_map_script_pub_keys. The cache is stored in the wallet file
+ // and is used to expand the descriptor in GetNewDestination. DescriptorScriptPubKeyMan relies
+ // more on ephemeral data than LegacyScriptPubKeyMan. For wallets using unhardened derivation
+ // (with or without private keys), the "keypool" is a single xpub.
+ bool TopUp(unsigned int size = 0) override;
+
+ void MarkUnusedAddresses(const CScript& script) override;
+
+ bool IsHDEnabled() const override;
+
+ //! Setup descriptors based on the given CExtkey
+ bool SetupDescriptorGeneration(const CExtKey& master_key);
+
+ bool HavePrivateKeys() const override;
+
+ int64_t GetOldestKeyPoolTime() const override;
+ size_t KeypoolCountExternalKeys() const override;
+ unsigned int GetKeyPoolSize() const override;
+
+ int64_t GetTimeFirstKey() const override;
+
+ std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const override;
+
+ bool CanGetAddresses(bool internal = false) const override;
+
+ std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const override;
+
+ bool CanProvide(const CScript& script, SignatureData& sigdata) override;
+
+ bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const override;
+ SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
+ TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false) const override;
+
+ uint256 GetID() const override;
+
+ void SetType(OutputType type, bool internal) override;
+
+ void SetCache(const DescriptorCache& cache);
+
+ bool AddKey(const CKeyID& key_id, const CKey& key);
+ bool AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key);
+
+ bool HasWalletDescriptor(const WalletDescriptor& desc) const;
+ void AddDescriptorKey(const CKey& key, const CPubKey &pubkey);
+ void WriteDescriptor();
+
+ const WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
+ const std::vector<CScript> GetScriptPubKeys() const;
+};
+
#endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index d65a0e9075..66f4542cf9 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -1,16 +1,16 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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 <node/context.h>
-#include <wallet/wallet.h>
-#include <wallet/coinselection.h>
-#include <wallet/coincontrol.h>
#include <amount.h>
+#include <node/context.h>
#include <primitives/transaction.h>
#include <random.h>
#include <test/util/setup_common.h>
+#include <wallet/coincontrol.h>
+#include <wallet/coinselection.h>
#include <wallet/test/wallet_test_fixture.h>
+#include <wallet/wallet.h>
#include <boost/test/unit_test.hpp>
#include <random>
@@ -176,8 +176,8 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
selection.clear();
// Select 5 Cent
- add_coin(3 * CENT, 3, actual_selection);
- add_coin(2 * CENT, 2, actual_selection);
+ add_coin(4 * CENT, 4, actual_selection);
+ add_coin(1 * CENT, 1, actual_selection);
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 5 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
BOOST_CHECK(equal_sets(selection, actual_selection));
BOOST_CHECK_EQUAL(value_ret, 5 * CENT);
@@ -189,11 +189,23 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
actual_selection.clear();
selection.clear();
+ // Cost of change is greater than the difference between target value and utxo sum
+ add_coin(1 * CENT, 1, actual_selection);
+ BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 0.9 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
+ BOOST_CHECK_EQUAL(value_ret, 1 * CENT);
+ BOOST_CHECK(equal_sets(selection, actual_selection));
+ actual_selection.clear();
+ selection.clear();
+
+ // Cost of change is less than the difference between target value and utxo sum
+ BOOST_CHECK(!SelectCoinsBnB(GroupCoins(utxo_pool), 0.9 * CENT, 0, selection, value_ret, not_input_fees));
+ actual_selection.clear();
+ selection.clear();
+
// Select 10 Cent
add_coin(5 * CENT, 5, utxo_pool);
+ add_coin(5 * CENT, 5, actual_selection);
add_coin(4 * CENT, 4, actual_selection);
- add_coin(3 * CENT, 3, actual_selection);
- add_coin(2 * CENT, 2, actual_selection);
add_coin(1 * CENT, 1, actual_selection);
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 10 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
BOOST_CHECK(equal_sets(selection, actual_selection));
diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp
index f923de6178..35860577cd 100644
--- a/src/wallet/test/psbt_wallet_tests.cpp
+++ b/src/wallet/test/psbt_wallet_tests.cpp
@@ -1,11 +1,10 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-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 <key_io.h>
#include <util/bip32.h>
#include <util/strencodings.h>
-#include <wallet/psbtwallet.h>
#include <wallet/wallet.h>
#include <boost/test/unit_test.hpp>
@@ -61,7 +60,7 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test)
// Fill transaction with our data
bool complete = true;
- BOOST_REQUIRE_EQUAL(TransactionError::OK, FillPSBT(&m_wallet, psbtx, complete, SIGHASH_ALL, false, true));
+ BOOST_REQUIRE_EQUAL(TransactionError::OK, m_wallet.FillPSBT(psbtx, complete, SIGHASH_ALL, false, true));
// Get the final tx
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
@@ -74,9 +73,7 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test)
// Try to sign the mutated input
SignatureData sigdata;
- psbtx.inputs[0].FillSignatureData(sigdata);
- const std::unique_ptr<SigningProvider> provider = m_wallet.GetSigningProvider(ws1, sigdata);
- BOOST_CHECK(!SignPSBTInput(*provider, psbtx, 0, SIGHASH_ALL));
+ BOOST_CHECK(spk_man->FillPSBT(psbtx, SIGHASH_ALL, true, true) != TransactionError::OK);
}
BOOST_AUTO_TEST_CASE(parse_hd_keypath)
diff --git a/src/wallet/test/scriptpubkeyman_tests.cpp b/src/wallet/test/scriptpubkeyman_tests.cpp
new file mode 100644
index 0000000000..757865ea37
--- /dev/null
+++ b/src/wallet/test/scriptpubkeyman_tests.cpp
@@ -0,0 +1,43 @@
+// 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 <key.h>
+#include <script/standard.h>
+#include <test/util/setup_common.h>
+#include <wallet/scriptpubkeyman.h>
+#include <wallet/wallet.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(scriptpubkeyman_tests, BasicTestingSetup)
+
+// Test LegacyScriptPubKeyMan::CanProvide behavior, making sure it returns true
+// for recognized scripts even when keys may not be available for signing.
+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(), WalletLocation(), WalletDatabase::CreateDummy());
+ LegacyScriptPubKeyMan& keyman = *wallet.GetOrCreateLegacyScriptPubKeyMan();
+
+ // Make a 1 of 2 multisig script
+ std::vector<CKey> keys(2);
+ std::vector<CPubKey> pubkeys;
+ for (CKey& key : keys) {
+ key.MakeNewKey(true);
+ pubkeys.emplace_back(key.GetPubKey());
+ }
+ CScript multisig_script = GetScriptForMultisig(1, pubkeys);
+ CScript p2sh_script = GetScriptForDestination(ScriptHash(multisig_script));
+ SignatureData data;
+
+ // Verify the p2sh(multisig) script is not recognized until the multisig
+ // script is added to the keystore to make it solvable
+ BOOST_CHECK(!keyman.CanProvide(p2sh_script, data));
+ keyman.AddCScript(multisig_script);
+ BOOST_CHECK(keyman.CanProvide(p2sh_script, data));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index ba0843f352..7ba3148ff3 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -10,7 +10,6 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
{
bool fFirstRun;
m_wallet.LoadWallet(fFirstRun);
- m_wallet.handleNotifications();
-
+ m_chain_notifications_handler = m_chain->handleNotifications({ &m_wallet, [](CWallet*) {} });
m_chain_client->registerRpcs();
}
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index 4e4129fb2c..a294935b64 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -23,6 +23,7 @@ struct WalletTestingSetup: public TestingSetup {
std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<interfaces::ChainClient> m_chain_client = interfaces::MakeWalletClient(*m_chain, {});
CWallet m_wallet;
+ std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
};
#endif // BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index a487e9e2e0..c049f2f15f 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -1,9 +1,10 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-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 <wallet/wallet.h>
+#include <future>
#include <memory>
#include <stdint.h>
#include <vector>
@@ -12,6 +13,7 @@
#include <node/context.h>
#include <policy/policy.h>
#include <rpc/server.h>
+#include <test/util/logging.h>
#include <test/util/setup_common.h>
#include <validation.h>
#include <wallet/coincontrol.h>
@@ -26,6 +28,36 @@ extern UniValue importwallet(const JSONRPCRequest& request);
BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
+static std::shared_ptr<CWallet> TestLoadWallet(interfaces::Chain& chain)
+{
+ std::string error;
+ std::vector<std::string> warnings;
+ auto wallet = CWallet::CreateWalletFromFile(chain, WalletLocation(""), error, warnings);
+ wallet->postInitProcess();
+ return wallet;
+}
+
+static void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
+{
+ SyncWithValidationInterfaceQueue();
+ wallet->m_chain_notifications_handler.reset();
+ UnloadWallet(std::move(wallet));
+}
+
+static CMutableTransaction TestSimpleSpend(const CTransaction& from, uint32_t index, const CKey& key, const CScript& pubkey)
+{
+ CMutableTransaction mtx;
+ mtx.vout.push_back({from.vout[index].nValue - DEFAULT_TRANSACTION_MAXFEE, pubkey});
+ mtx.vin.push_back({CTxIn{from.GetHash(), index}});
+ FillableSigningProvider keystore;
+ keystore.AddKey(key);
+ std::map<COutPoint, Coin> coins;
+ coins[mtx.vin[0].prevout].out = from.vout[index];
+ std::map<int, std::string> input_errors;
+ BOOST_CHECK(SignTransaction(mtx, &keystore, coins, SIGHASH_ALL, input_errors));
+ return mtx;
+}
+
static void AddKey(CWallet& wallet, const CKey& key)
{
auto spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
@@ -43,10 +75,8 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
NodeContext node;
auto chain = interfaces::MakeChain(node);
- auto locked_chain = chain->lock();
- LockAssertion lock(::cs_main);
- // Verify ScanForWalletTransactions accommodates a null start block.
+ // Verify ScanForWalletTransactions fails to read an unknown start block.
{
CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
{
@@ -54,10 +84,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
}
AddKey(wallet, coinbaseKey);
- WalletRescanReserver reserver(&wallet);
+ WalletRescanReserver reserver(wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet.ScanForWalletTransactions({} /* start_block */, {} /* stop_block */, reserver, false /* update */);
- BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions({} /* start_block */, 0 /* start_height */, {} /* max_height */, reserver, false /* update */);
+ BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::FAILURE);
BOOST_CHECK(result.last_failed_block.IsNull());
BOOST_CHECK(result.last_scanned_block.IsNull());
BOOST_CHECK(!result.last_scanned_height);
@@ -73,9 +103,9 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
}
AddKey(wallet, coinbaseKey);
- WalletRescanReserver reserver(&wallet);
+ WalletRescanReserver reserver(wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), {} /* stop_block */, reserver, false /* update */);
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), oldTip->nHeight, {} /* max_height */, reserver, false /* update */);
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
BOOST_CHECK(result.last_failed_block.IsNull());
BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash());
@@ -84,7 +114,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
}
// Prune the older block file.
- PruneOneBlockFile(oldTip->GetBlockPos().nFile);
+ {
+ LOCK(cs_main);
+ PruneOneBlockFile(oldTip->GetBlockPos().nFile);
+ }
UnlinkPrunedFiles({oldTip->GetBlockPos().nFile});
// Verify ScanForWalletTransactions only picks transactions in the new block
@@ -96,9 +129,9 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
}
AddKey(wallet, coinbaseKey);
- WalletRescanReserver reserver(&wallet);
+ WalletRescanReserver reserver(wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), {} /* stop_block */, reserver, false /* update */);
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), oldTip->nHeight, {} /* max_height */, reserver, false /* update */);
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::FAILURE);
BOOST_CHECK_EQUAL(result.last_failed_block, oldTip->GetBlockHash());
BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash());
@@ -107,7 +140,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
}
// Prune the remaining block file.
- PruneOneBlockFile(newTip->GetBlockPos().nFile);
+ {
+ LOCK(cs_main);
+ PruneOneBlockFile(newTip->GetBlockPos().nFile);
+ }
UnlinkPrunedFiles({newTip->GetBlockPos().nFile});
// Verify ScanForWalletTransactions scans no blocks.
@@ -118,9 +154,9 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
}
AddKey(wallet, coinbaseKey);
- WalletRescanReserver reserver(&wallet);
+ WalletRescanReserver reserver(wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), {} /* stop_block */, reserver, false /* update */);
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), oldTip->nHeight, {} /* max_height */, reserver, false /* update */);
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::FAILURE);
BOOST_CHECK_EQUAL(result.last_failed_block, newTip->GetBlockHash());
BOOST_CHECK(result.last_scanned_block.IsNull());
@@ -139,11 +175,12 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
NodeContext node;
auto chain = interfaces::MakeChain(node);
- auto locked_chain = chain->lock();
- LockAssertion lock(::cs_main);
// Prune the older block file.
- PruneOneBlockFile(oldTip->GetBlockPos().nFile);
+ {
+ LOCK(cs_main);
+ PruneOneBlockFile(oldTip->GetBlockPos().nFile);
+ }
UnlinkPrunedFiles({oldTip->GetBlockPos().nFile});
// Verify importmulti RPC returns failure for a key whose creation time is
@@ -152,6 +189,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
{
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
wallet->SetupLegacyScriptPubKeyMan();
+ WITH_LOCK(wallet->cs_wallet, wallet->SetLastBlockProcessed(newTip->nHeight, newTip->GetBlockHash()));
AddWallet(wallet);
UniValue keys;
keys.setArray();
@@ -208,23 +246,25 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
NodeContext node;
auto chain = interfaces::MakeChain(node);
- auto locked_chain = chain->lock();
- LockAssertion lock(::cs_main);
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(), WalletLocation(), WalletDatabase::CreateDummy());
- auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
- LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
- spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
- spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
+ {
+ auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
+ LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
+ spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
+ spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
+ AddWallet(wallet);
+ wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
+ }
JSONRPCRequest request;
request.params.setArray();
request.params.push_back(backup_file);
- AddWallet(wallet);
+
::dumpwallet(request);
RemoveWallet(wallet);
}
@@ -233,16 +273,17 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// were scanned, and no prior blocks were scanned.
{
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
+ LOCK(wallet->cs_wallet);
wallet->SetupLegacyScriptPubKeyMan();
JSONRPCRequest request;
request.params.setArray();
request.params.push_back(backup_file);
AddWallet(wallet);
+ wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
::importwallet(request);
RemoveWallet(wallet);
- LOCK(wallet->cs_wallet);
BOOST_CHECK_EQUAL(wallet->mapWallet.size(), 3U);
BOOST_CHECK_EQUAL(m_coinbase_txns.size(), 103U);
for (size_t i = 0; i < m_coinbase_txns.size(); ++i) {
@@ -270,8 +311,6 @@ BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
auto spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
CWalletTx wtx(&wallet, m_coinbase_txns.back());
- auto locked_chain = chain->lock();
- LockAssertion lock(::cs_main);
LOCK2(wallet.cs_wallet, spk_man->cs_KeyStore);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -296,8 +335,6 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64
SetMockTime(mockTime);
CBlockIndex* block = nullptr;
if (blockTime > 0) {
- auto locked_chain = wallet.chain().lock();
- LockAssertion lock(::cs_main);
auto inserted = ::BlockIndex().emplace(GetRandHash(), new CBlockIndex);
assert(inserted.second);
const uint256& hash = inserted.first->first;
@@ -307,7 +344,6 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64
}
CWalletTx wtx(&wallet, MakeTransactionRef(tx));
- LOCK(cs_main);
LOCK(wallet.cs_wallet);
// If transaction is already in map, to avoid inconsistencies, unconfirmation
// is needed before confirm again with different block.
@@ -454,15 +490,15 @@ public:
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
wallet = MakeUnique<CWallet>(m_chain.get(), WalletLocation(), WalletDatabase::CreateMock());
{
- LOCK(wallet->cs_wallet);
+ LOCK2(wallet->cs_wallet, ::cs_main);
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
}
bool firstRun;
wallet->LoadWallet(firstRun);
AddKey(*wallet, coinbaseKey);
- WalletRescanReserver reserver(wallet.get());
+ WalletRescanReserver reserver(*wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet->ScanForWalletTransactions(::ChainActive().Genesis()->GetBlockHash(), {} /* stop_block */, reserver, false /* update */);
+ CWallet::ScanResult result = wallet->ScanForWalletTransactions(::ChainActive().Genesis()->GetBlockHash(), 0 /* start_height */, {} /* max_height */, reserver, false /* update */);
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
BOOST_CHECK_EQUAL(result.last_scanned_block, ::ChainActive().Tip()->GetBlockHash());
BOOST_CHECK_EQUAL(*result.last_scanned_height, ::ChainActive().Height());
@@ -482,8 +518,7 @@ public:
std::string error;
CCoinControl dummy;
{
- auto locked_chain = m_chain->lock();
- BOOST_CHECK(wallet->CreateTransaction(*locked_chain, {recipient}, tx, fee, changePos, error, dummy));
+ BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, fee, changePos, error, dummy));
}
wallet->CommitTransaction(tx, {}, {});
CMutableTransaction blocktx;
@@ -493,7 +528,6 @@ public:
}
CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- LOCK(cs_main);
LOCK(wallet->cs_wallet);
wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, ::ChainActive().Tip()->GetBlockHash());
auto it = wallet->mapWallet.find(tx->GetHash());
@@ -516,9 +550,8 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
// address.
std::map<CTxDestination, std::vector<COutput>> list;
{
- auto locked_chain = m_chain->lock();
LOCK(wallet->cs_wallet);
- list = wallet->ListCoins(*locked_chain);
+ list = wallet->ListCoins();
}
BOOST_CHECK_EQUAL(list.size(), 1U);
BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
@@ -533,9 +566,8 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
// pubkey.
AddTx(CRecipient{GetScriptForRawPubKey({}), 1 * COIN, false /* subtract fee */});
{
- auto locked_chain = m_chain->lock();
LOCK(wallet->cs_wallet);
- list = wallet->ListCoins(*locked_chain);
+ list = wallet->ListCoins();
}
BOOST_CHECK_EQUAL(list.size(), 1U);
BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
@@ -543,10 +575,9 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
// Lock both coins. Confirm number of available coins drops to 0.
{
- auto locked_chain = m_chain->lock();
LOCK(wallet->cs_wallet);
std::vector<COutput> available;
- wallet->AvailableCoins(*locked_chain, available);
+ wallet->AvailableCoins(available);
BOOST_CHECK_EQUAL(available.size(), 2U);
}
for (const auto& group : list) {
@@ -556,18 +587,16 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
}
}
{
- auto locked_chain = m_chain->lock();
LOCK(wallet->cs_wallet);
std::vector<COutput> available;
- wallet->AvailableCoins(*locked_chain, available);
+ wallet->AvailableCoins(available);
BOOST_CHECK_EQUAL(available.size(), 0U);
}
// Confirm ListCoins still returns same result as before, despite coins
// being locked.
{
- auto locked_chain = m_chain->lock();
LOCK(wallet->cs_wallet);
- list = wallet->ListCoins(*locked_chain);
+ list = wallet->ListCoins();
}
BOOST_CHECK_EQUAL(list.size(), 1U);
BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
@@ -631,4 +660,137 @@ BOOST_FIXTURE_TEST_CASE(dummy_input_size_test, TestChain100Setup)
BOOST_CHECK_EQUAL(CalculateNestedKeyhashInputSize(true), DUMMY_NESTED_P2WPKH_INPUT_SIZE);
}
+bool malformed_descriptor(std::ios_base::failure e)
+{
+ std::string s(e.what());
+ return s.find("Missing checksum") != std::string::npos;
+}
+
+BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
+{
+ std::vector<unsigned char> malformed_record;
+ CVectorWriter vw(0, 0, malformed_record, 0);
+ vw << std::string("notadescriptor");
+ vw << (uint64_t)0;
+ vw << (int32_t)0;
+ vw << (int32_t)0;
+ vw << (int32_t)1;
+
+ VectorReader vr(0, 0, malformed_record, 0);
+ WalletDescriptor w_desc;
+ BOOST_CHECK_EXCEPTION(vr >> w_desc, std::ios_base::failure, malformed_descriptor);
+}
+
+//! Test CreateWalletFromFile function 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.
+//!
+//! It isn't possible to verify there aren't race condition in every case, so
+//! this test just checks two specific cases and ensures that timing of
+//! notifications in these cases doesn't prevent the wallet from detecting
+//! transactions.
+//!
+//! In the first case, block and mempool transactions are created before the
+//! wallet is loaded, but notifications about these transactions are delayed
+//! until after it is loaded. The notifications are superfluous in this case, so
+//! the test verifies the transactions are detected before they arrive.
+//!
+//! In the second case, block and mempool transactions are created after the
+//! 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)
+{
+ // Create new wallet with known key and unload it.
+ auto chain = interfaces::MakeChain(m_node);
+ auto wallet = TestLoadWallet(*chain);
+ CKey key;
+ key.MakeNewKey(true);
+ AddKey(*wallet, key);
+ TestUnloadWallet(std::move(wallet));
+
+
+ // Add log hook to detect AddToWallet events from rescans, blockConnected,
+ // and transactionAddedToMempool notifications
+ int addtx_count = 0;
+ DebugLogHelper addtx_counter("[default wallet] AddToWallet", [&](const std::string* s) {
+ if (s) ++addtx_count;
+ return false;
+ });
+
+
+ bool rescan_completed = false;
+ DebugLogHelper rescan_check("[default wallet] Rescan completed", [&](const std::string* s) {
+ if (s) rescan_completed = true;
+ return false;
+ });
+
+
+ // Block the queue to prevent the wallet receiving blockConnected and
+ // transactionAddedToMempool notifications, and create block and mempool
+ // transactions paying to the wallet
+ std::promise<void> promise;
+ CallFunctionInValidationInterfaceQueue([&promise] {
+ promise.get_future().wait();
+ });
+ std::string error;
+ m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
+ 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));
+
+
+ // Reload wallet and make sure new transactions are detected despite events
+ // being blocked
+ wallet = TestLoadWallet(*chain);
+ BOOST_CHECK(rescan_completed);
+ BOOST_CHECK_EQUAL(addtx_count, 2);
+ {
+ LOCK(wallet->cs_wallet);
+ BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_tx.GetHash()), 1);
+ BOOST_CHECK_EQUAL(wallet->mapWallet.count(mempool_tx.GetHash()), 1);
+ }
+
+
+ // Unblock notification queue and make sure stale blockConnected and
+ // transactionAddedToMempool events are processed
+ promise.set_value();
+ SyncWithValidationInterfaceQueue();
+ BOOST_CHECK_EQUAL(addtx_count, 4);
+
+
+ TestUnloadWallet(std::move(wallet));
+
+
+ // Load wallet again, this time creating new block and mempool transactions
+ // paying to the wallet as the wallet finishes loading and syncing the
+ // queue so the events have to be handled immediately. Releasing the wallet
+ // lock during the sync is a little artificial but is needed to avoid a
+ // 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) {
+ 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));
+ LEAVE_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
+ SyncWithValidationInterfaceQueue();
+ ENTER_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
+ });
+ wallet = TestLoadWallet(*chain);
+ BOOST_CHECK_EQUAL(addtx_count, 4);
+ {
+ LOCK(wallet->cs_wallet);
+ BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_tx.GetHash()), 1);
+ BOOST_CHECK_EQUAL(wallet->mapWallet.count(mempool_tx.GetHash()), 1);
+ }
+
+
+ TestUnloadWallet(std::move(wallet));
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 4a38571dfc..a20ede59fd 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -13,6 +13,7 @@
#include <interfaces/wallet.h>
#include <key.h>
#include <key_io.h>
+#include <optional.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <primitives/block.h>
@@ -21,12 +22,12 @@
#include <script/script.h>
#include <script/signingprovider.h>
#include <util/bip32.h>
+#include <util/check.h>
#include <util/error.h>
#include <util/fees.h>
#include <util/moneystr.h>
#include <util/rbf.h>
#include <util/translation.h>
-#include <util/validation.h>
#include <wallet/coincontrol.h>
#include <wallet/fees.h>
@@ -35,6 +36,8 @@
#include <boost/algorithm/string/replace.hpp>
+using interfaces::FoundBlock;
+
const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS{
{WALLET_FLAG_AVOID_REUSE,
"You need to rescan the blockchain in order to correctly mark used "
@@ -62,8 +65,10 @@ bool AddWallet(const std::shared_ptr<CWallet>& wallet)
bool RemoveWallet(const std::shared_ptr<CWallet>& wallet)
{
- LOCK(cs_wallets);
assert(wallet);
+ // Unregister with the validation interface which also drops shared ponters.
+ wallet->m_chain_notifications_handler.reset();
+ LOCK(cs_wallets);
std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i == vpwallets.end()) return false;
vpwallets.erase(i);
@@ -105,13 +110,9 @@ static std::set<std::string> g_unloading_wallet_set;
// Custom deleter for shared_ptr<CWallet>.
static void ReleaseWallet(CWallet* wallet)
{
- // Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain
- // so that it's in sync with the current chainstate.
const std::string name = wallet->GetName();
wallet->WalletLogPrintf("Releasing wallet\n");
- wallet->BlockUntilSyncedToCurrentChain();
wallet->Flush();
- wallet->m_chain_notifications_handler.reset();
delete wallet;
// Wallet is now released, notify UnloadWallet, if any.
{
@@ -137,6 +138,7 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
// Notify the unload intent so that all remaining shared pointers are
// released.
wallet->NotifyUnload();
+
// Time to ditch our shared_ptr and wait for ReleaseWallet call.
wallet.reset();
{
@@ -149,19 +151,24 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings)
{
- if (!CWallet::Verify(chain, location, false, error, warnings)) {
- error = "Wallet file verification failed: " + error;
- return nullptr;
- }
+ try {
+ if (!CWallet::Verify(chain, location, false, error, warnings)) {
+ error = "Wallet file verification failed: " + error;
+ return nullptr;
+ }
- std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings);
- if (!wallet) {
- error = "Wallet loading failed: " + error;
+ std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings);
+ if (!wallet) {
+ error = "Wallet loading failed: " + error;
+ return nullptr;
+ }
+ AddWallet(wallet);
+ wallet->postInitProcess();
+ return wallet;
+ } catch (const std::runtime_error& e) {
+ error = e.what();
return nullptr;
}
- AddWallet(wallet);
- wallet->postInitProcess();
- return wallet;
}
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings)
@@ -221,10 +228,14 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString&
// Set a seed for the wallet
{
LOCK(wallet->cs_wallet);
- for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
- if (!spk_man->SetupGeneration()) {
- error = "Unable to generate initial keys";
- return WalletCreationStatus::CREATION_FAILED;
+ if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
+ wallet->SetupDescriptorScriptPubKeyMans();
+ } else {
+ for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
+ if (!spk_man->SetupGeneration()) {
+ error = "Unable to generate initial keys";
+ return WalletCreationStatus::CREATION_FAILED;
+ }
}
}
}
@@ -344,7 +355,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
return false;
}
-void CWallet::ChainStateFlushed(const CBlockLocator& loc)
+void CWallet::chainStateFlushed(const CBlockLocator& loc)
{
WalletBatch batch(*database);
batch.WriteBestBlock(loc);
@@ -581,8 +592,11 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Lock();
Unlock(strWalletPassphrase);
- // if we are using HD, replace the HD seed with a new one
- if (auto spk_man = GetLegacyScriptPubKeyMan()) {
+ // If we are using descriptors, make new descriptors with a new seed
+ if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)) {
+ SetupDescriptorScriptPubKeyMans();
+ } else if (auto spk_man = GetLegacyScriptPubKeyMan()) {
+ // if we are using HD, replace the HD seed with a new one
if (spk_man->IsHDEnabled()) {
if (!spk_man->SetupGeneration(true)) {
return false;
@@ -713,7 +727,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
return success;
}
-void CWallet::SetUsedDestinationState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations)
+void CWallet::SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations)
{
AssertLockHeld(cs_wallet);
const CWalletTx* srctx = GetWalletTx(hash);
@@ -733,29 +747,36 @@ void CWallet::SetUsedDestinationState(WalletBatch& batch, const uint256& hash, u
}
}
-bool CWallet::IsUsedDestination(const uint256& hash, unsigned int n) const
+bool CWallet::IsSpentKey(const uint256& hash, unsigned int n) const
{
AssertLockHeld(cs_wallet);
CTxDestination dst;
const CWalletTx* srctx = GetWalletTx(hash);
if (srctx) {
assert(srctx->tx->vout.size() > n);
- LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
- // When descriptor wallets arrive, these additional checks are
- // likely superfluous and can be optimized out
- assert(spk_man != nullptr);
- for (const auto& keyid : GetAffectedKeys(srctx->tx->vout[n].scriptPubKey, *spk_man)) {
- WitnessV0KeyHash wpkh_dest(keyid);
- if (GetDestData(wpkh_dest, "used", nullptr)) {
- return true;
- }
- ScriptHash sh_wpkh_dest(GetScriptForDestination(wpkh_dest));
- if (GetDestData(sh_wpkh_dest, "used", nullptr)) {
- return true;
- }
- PKHash pkh_dest(keyid);
- if (GetDestData(pkh_dest, "used", nullptr)) {
- return true;
+ CTxDestination dest;
+ if (!ExtractDestination(srctx->tx->vout[n].scriptPubKey, dest)) {
+ return false;
+ }
+ if (GetDestData(dest, "used", nullptr)) {
+ return true;
+ }
+ if (IsLegacy()) {
+ LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
+ assert(spk_man != nullptr);
+ for (const auto& keyid : GetAffectedKeys(srctx->tx->vout[n].scriptPubKey, *spk_man)) {
+ WitnessV0KeyHash wpkh_dest(keyid);
+ if (GetDestData(wpkh_dest, "used", nullptr)) {
+ return true;
+ }
+ ScriptHash sh_wpkh_dest(GetScriptForDestination(wpkh_dest));
+ if (GetDestData(sh_wpkh_dest, "used", nullptr)) {
+ return true;
+ }
+ PKHash pkh_dest(keyid);
+ if (GetDestData(pkh_dest, "used", nullptr)) {
+ return true;
+ }
}
}
}
@@ -776,7 +797,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
for (const CTxIn& txin : wtxIn.tx->vin) {
const COutPoint& op = txin.prevout;
- SetUsedDestinationState(batch, op.hash, op.n, true, tx_destinations);
+ SetSpentKeyState(batch, op.hash, op.n, true, tx_destinations);
}
MarkDestinationsDirty(tx_destinations);
@@ -846,6 +867,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
if (!strCmd.empty())
{
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
+#ifndef WIN32
+ // Substituting the wallet name isn't currently supported on windows
+ // because windows shell escaping has not been implemented yet:
+ // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-537384875
+ // A few ways it could be implemented in the future are described in:
+ // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-461288094
+ boost::replace_all(strCmd, "%w", ShellEscape(GetName()));
+#endif
std::thread t(runCommand, strCmd);
t.detach(); // thread runs free
}
@@ -856,10 +885,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
void CWallet::LoadToWallet(CWalletTx& wtxIn)
{
- // If wallet doesn't have a chain (e.g bitcoin-wallet), lock can't be taken.
- auto locked_chain = LockChain();
- if (locked_chain) {
- Optional<int> block_height = locked_chain->getBlockHeight(wtxIn.m_confirm.hashBlock);
+ // 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(wtxIn.m_confirm.hashBlock);
if (block_height) {
// Update cached block height variable since it not stored in the
// serialized transaction.
@@ -946,7 +974,6 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
bool CWallet::TransactionCanBeAbandoned(const uint256& hashTx) const
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
const CWalletTx* wtx = GetWalletTx(hashTx);
return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain() == 0 && !wtx->InMempool();
@@ -964,7 +991,6 @@ void CWallet::MarkInputsDirty(const CTransactionRef& tx)
bool CWallet::AbandonTransaction(const uint256& hashTx)
{
- auto locked_chain = chain().lock(); // Temporary. Removed in upcoming lock cleanup
LOCK(cs_wallet);
WalletBatch batch(*database, "r+");
@@ -1019,7 +1045,6 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
@@ -1081,8 +1106,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmatio
MarkInputsDirty(ptx);
}
-void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) {
- auto locked_chain = chain().lock();
+void CWallet::transactionAddedToMempool(const CTransactionRef& ptx) {
LOCK(cs_wallet);
CWalletTx::Confirmation confirm(CWalletTx::Status::UNCONFIRMED, /* block_height */ 0, {}, /* nIndex */ 0);
SyncTransaction(ptx, confirm);
@@ -1093,7 +1117,7 @@ void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) {
}
}
-void CWallet::TransactionRemovedFromMempool(const CTransactionRef &ptx) {
+void CWallet::transactionRemovedFromMempool(const CTransactionRef &ptx) {
LOCK(cs_wallet);
auto it = mapWallet.find(ptx->GetHash());
if (it != mapWallet.end()) {
@@ -1101,10 +1125,9 @@ void CWallet::TransactionRemovedFromMempool(const CTransactionRef &ptx) {
}
}
-void CWallet::BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& vtxConflicted, int height)
+void CWallet::blockConnected(const CBlock& block, int height)
{
const uint256& block_hash = block.GetHash();
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
m_last_block_processed_height = height;
@@ -1112,16 +1135,12 @@ void CWallet::BlockConnected(const CBlock& block, const std::vector<CTransaction
for (size_t index = 0; index < block.vtx.size(); index++) {
CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, height, block_hash, index);
SyncTransaction(block.vtx[index], confirm);
- TransactionRemovedFromMempool(block.vtx[index]);
- }
- for (const CTransactionRef& ptx : vtxConflicted) {
- TransactionRemovedFromMempool(ptx);
+ transactionRemovedFromMempool(block.vtx[index]);
}
}
-void CWallet::BlockDisconnected(const CBlock& block, int height)
+void CWallet::blockDisconnected(const CBlock& block, int height)
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
// At block disconnection, this will change an abandoned transaction to
@@ -1136,13 +1155,13 @@ void CWallet::BlockDisconnected(const CBlock& block, int height)
}
}
-void CWallet::UpdatedBlockTip()
+void CWallet::updatedBlockTip()
{
m_best_block_time = GetTime();
}
-void CWallet::BlockUntilSyncedToCurrentChain() {
+void CWallet::BlockUntilSyncedToCurrentChain() const {
AssertLockNotHeld(cs_wallet);
// Skip the queue-draining stuff if we know we're caught up with
// ::ChainActive().Tip(), otherwise put a callback in the validation interface queue and wait
@@ -1233,8 +1252,9 @@ bool CWallet::IsChange(const CScript& script) const
return true;
LOCK(cs_wallet);
- if (!mapAddressBook.count(address))
+ if (!FindAddressBookEntry(address)) {
return true;
+ }
}
return false;
}
@@ -1318,14 +1338,15 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
bool CWallet::IsHDEnabled() const
{
+ // All Active ScriptPubKeyMans must be HD for this to be true
bool result = true;
- for (const auto& spk_man_pair : m_spk_managers) {
- result &= spk_man_pair.second->IsHDEnabled();
+ for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
+ result &= spk_man->IsHDEnabled();
}
return result;
}
-bool CWallet::CanGetAddresses(bool internal)
+bool CWallet::CanGetAddresses(bool internal) const
{
LOCK(cs_wallet);
if (m_spk_managers.empty()) return false;
@@ -1399,7 +1420,7 @@ bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig
const CScript& scriptPubKey = txout.scriptPubKey;
SignatureData sigdata;
- std::unique_ptr<SigningProvider> provider = GetSigningProvider(scriptPubKey);
+ std::unique_ptr<SigningProvider> provider = GetSolvingProvider(scriptPubKey);
if (!provider) {
// We don't know about this scriptpbuKey;
return false;
@@ -1584,22 +1605,17 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
// Find starting block. May be null if nCreateTime is greater than the
// highest blockchain timestamp, in which case there is nothing that needs
// to be scanned.
+ int start_height = 0;
uint256 start_block;
- {
- auto locked_chain = chain().lock();
- const Optional<int> start_height = locked_chain->findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, &start_block);
- const Optional<int> tip_height = locked_chain->getHeight();
- WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, tip_height && start_height ? *tip_height - *start_height + 1 : 0);
- }
+ bool start = chain().findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, FoundBlock().hash(start_block).height(start_height));
+ WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) - start_height + 1 : 0);
- if (!start_block.IsNull()) {
+ if (start) {
// TODO: this should take into account failure by ScanResult::USER_ABORT
- ScanResult result = ScanForWalletTransactions(start_block, {} /* stop_block */, reserver, update);
+ ScanResult result = ScanForWalletTransactions(start_block, start_height, {} /* max_height */, reserver, update);
if (result.status == ScanResult::FAILURE) {
int64_t time_max;
- if (!chain().findBlock(result.last_failed_block, nullptr /* block */, nullptr /* time */, &time_max)) {
- throw std::logic_error("ScanForWalletTransactions returned invalid block hash");
- }
+ CHECK_NONFATAL(chain().findBlock(result.last_failed_block, FoundBlock().maxTime(time_max)));
return time_max + TIMESTAMP_WINDOW + 1;
}
}
@@ -1613,9 +1629,9 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
*
* @param[in] start_block Scan starting block. If block is not on the active
* chain, the scan will return SUCCESS immediately.
- * @param[in] stop_block Scan ending block. If block is not on the active
- * chain, the scan will continue until it reaches the
- * chain tip.
+ * @param[in] start_height Height of start_block
+ * @param[in] max_height Optional max scanning height. If unset there is
+ * no maximum and scanning can continue to the tip
*
* @return ScanResult returning scan information and indicating success or
* failure. Return status will be set to SUCCESS if scan was
@@ -1627,7 +1643,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
* the main chain after to the addition of any new keys you want to detect
* transactions for.
*/
-CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, const uint256& stop_block, const WalletRescanReserver& reserver, bool fUpdate)
+CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, Optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate)
{
int64_t nNow = GetTime();
int64_t start_time = GetTimeMillis();
@@ -1641,36 +1657,31 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
fAbortRescan = false;
ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
- uint256 tip_hash;
- // The way the 'block_height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
- Optional<int> block_height = MakeOptional(false, int());
- double progress_begin;
- double progress_end;
- {
- auto locked_chain = chain().lock();
- if (Optional<int> tip_height = locked_chain->getHeight()) {
- tip_hash = locked_chain->getBlockHash(*tip_height);
- }
- block_height = locked_chain->getBlockHeight(block_hash);
- progress_begin = chain().guessVerificationProgress(block_hash);
- progress_end = chain().guessVerificationProgress(stop_block.IsNull() ? tip_hash : stop_block);
- }
+ uint256 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
+ uint256 end_hash = tip_hash;
+ if (max_height) chain().findAncestorByHeight(tip_hash, *max_height, FoundBlock().hash(end_hash));
+ double progress_begin = chain().guessVerificationProgress(block_hash);
+ double progress_end = chain().guessVerificationProgress(end_hash);
double progress_current = progress_begin;
- while (block_height && !fAbortRescan && !chain().shutdownRequested()) {
+ int block_height = start_height;
+ while (!fAbortRescan && !chain().shutdownRequested()) {
m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
- if (*block_height % 100 == 0 && progress_end - progress_begin > 0.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))));
}
if (GetTime() >= nNow + 60) {
nNow = GetTime();
- WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", *block_height, progress_current);
+ WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
}
CBlock block;
- if (chain().findBlock(block_hash, &block) && !block.IsNull()) {
- auto locked_chain = chain().lock();
+ bool next_block;
+ uint256 next_block_hash;
+ bool reorg = false;
+ if (chain().findBlock(block_hash, FoundBlock().data(block)) && !block.IsNull()) {
LOCK(cs_wallet);
- if (!locked_chain->getBlockHeight(block_hash)) {
+ next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg);
+ if (reorg) {
// 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
@@ -1680,37 +1691,37 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
break;
}
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
- CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, *block_height, block_hash, posInBlock);
+ CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, block_height, block_hash, posInBlock);
SyncTransaction(block.vtx[posInBlock], confirm, fUpdate);
}
// scan succeeded, record block as most recent successfully scanned
result.last_scanned_block = block_hash;
- result.last_scanned_height = *block_height;
+ result.last_scanned_height = block_height;
} else {
// 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 (block_hash == stop_block) {
+ if (max_height && block_height >= *max_height) {
break;
}
{
- auto locked_chain = chain().lock();
- Optional<int> tip_height = locked_chain->getHeight();
- if (!tip_height || *tip_height <= block_height || !locked_chain->getBlockHeight(block_hash)) {
+ if (!next_block || reorg) {
// break successfully when rescan has reached the tip, or
// previous block is no longer on the chain due to a reorg
break;
}
// increment block and verification progress
- block_hash = locked_chain->getBlockHash(++*block_height);
+ block_hash = next_block_hash;
+ ++block_height;
progress_current = chain().guessVerificationProgress(block_hash);
// handle updated tip hash
const uint256 prev_tip_hash = tip_hash;
- tip_hash = locked_chain->getBlockHash(*tip_height);
- if (stop_block.IsNull() && prev_tip_hash != tip_hash) {
+ tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
+ if (!max_height && prev_tip_hash != tip_hash) {
// in case the tip has changed, update progress max
progress_end = chain().guessVerificationProgress(tip_hash);
}
@@ -1718,10 +1729,10 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
}
ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), 100); // hide progress dialog in GUI
if (block_height && fAbortRescan) {
- WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", *block_height, progress_current);
+ WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
result.status = ScanResult::USER_ABORT;
} else if (block_height && chain().shutdownRequested()) {
- WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", *block_height, progress_current);
+ WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
result.status = ScanResult::USER_ABORT;
} else {
WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - start_time);
@@ -1780,7 +1791,7 @@ bool CWalletTx::SubmitMemoryPoolAndRelay(std::string& err_string, bool relay)
// Irrespective of the failure reason, un-marking fInMempool
// out-of-order is incorrect - it should be unmarked when
// TransactionRemovedFromMempool fires.
- bool ret = pwallet->chain().broadcastTransaction(tx, err_string, pwallet->m_default_max_tx_fee, relay);
+ bool ret = pwallet->chain().broadcastTransaction(tx, pwallet->m_default_max_tx_fee, relay, err_string);
fInMempool |= ret;
return ret;
}
@@ -1869,7 +1880,7 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter
uint256 hashTx = GetHash();
for (unsigned int i = 0; i < tx->vout.size(); i++)
{
- if (!pwallet->IsSpent(hashTx, i) && (allow_used_addresses || !pwallet->IsUsedDestination(hashTx, i))) {
+ if (!pwallet->IsSpent(hashTx, i) && (allow_used_addresses || !pwallet->IsSpentKey(hashTx, i))) {
const CTxOut &txout = tx->vout[i];
nCredit += pwallet->GetCredit(txout, filter);
if (!MoneyRange(nCredit))
@@ -1908,16 +1919,16 @@ bool CWalletTx::InMempool() const
return fInMempool;
}
-bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const
+bool CWalletTx::IsTrusted() const
{
std::set<uint256> s;
- return IsTrusted(locked_chain, s);
+ return IsTrusted(s);
}
-bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain, std::set<uint256>& trusted_parents) const
+bool CWalletTx::IsTrusted(std::set<uint256>& trusted_parents) const
{
// Quick answer in most cases
- if (!locked_chain.checkFinalTx(*tx)) return false;
+ if (!pwallet->chain().checkFinalTx(*tx)) return false;
int nDepth = GetDepthInMainChain();
if (nDepth >= 1) return true;
if (nDepth < 0) return false;
@@ -1939,7 +1950,7 @@ bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain, std::set<uint25
// If we've already trusted this parent, continue
if (trusted_parents.count(parent->GetHash())) continue;
// Recurse to check that the parent is also trusted
- if (!parent->IsTrusted(locked_chain, trusted_parents)) return false;
+ if (!parent->IsTrusted(trusted_parents)) return false;
trusted_parents.insert(parent->GetHash());
}
return true;
@@ -1973,7 +1984,8 @@ void CWallet::ResendWalletTransactions()
// that these are our transactions.
if (GetTime() < nNextResend || !fBroadcastTransactions) return;
bool fFirst = (nNextResend == 0);
- nNextResend = GetTime() + GetRand(30 * 60);
+ // resend 12-36 hours from now, ~1 day on average.
+ nNextResend = GetTime() + (12 * 60 * 60) + GetRand(24 * 60 * 60);
if (fFirst) return;
// Only do it if there's been a new block since last time
@@ -1982,8 +1994,7 @@ void CWallet::ResendWalletTransactions()
int submitted_tx_count = 0;
- { // locked_chain and cs_wallet scope
- auto locked_chain = chain().lock();
+ { // cs_wallet scope
LOCK(cs_wallet);
// Relay transactions
@@ -1996,7 +2007,7 @@ void CWallet::ResendWalletTransactions()
std::string unused_err_string;
if (wtx.SubmitMemoryPoolAndRelay(unused_err_string, true)) ++submitted_tx_count;
}
- } // locked_chain and cs_wallet
+ } // cs_wallet
if (submitted_tx_count > 0) {
WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
@@ -2024,13 +2035,12 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons
Balance ret;
isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED;
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
std::set<uint256> trusted_parents;
for (const auto& entry : mapWallet)
{
const CWalletTx& wtx = entry.second;
- const bool is_trusted{wtx.IsTrusted(*locked_chain, trusted_parents)};
+ const bool is_trusted{wtx.IsTrusted(trusted_parents)};
const int tx_depth{wtx.GetDepthInMainChain()};
const CAmount tx_credit_mine{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)};
const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)};
@@ -2051,12 +2061,11 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons
CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
CAmount balance = 0;
std::vector<COutput> vCoins;
- AvailableCoins(*locked_chain, vCoins, true, coinControl);
+ AvailableCoins(vCoins, true, coinControl);
for (const COutput& out : vCoins) {
if (out.fSpendable) {
balance += out.tx->tx->vout[out.i].nValue;
@@ -2065,7 +2074,7 @@ CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
return balance;
}
-void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<COutput>& vCoins, bool fOnlySafe, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount) const
+void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount) const
{
AssertLockHeld(cs_wallet);
@@ -2083,7 +2092,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
const uint256& wtxid = entry.first;
const CWalletTx& wtx = entry.second;
- if (!locked_chain.checkFinalTx(*wtx.tx)) {
+ if (!chain().checkFinalTx(*wtx.tx)) {
continue;
}
@@ -2099,7 +2108,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
if (nDepth == 0 && !wtx.InMempool())
continue;
- bool safeTx = wtx.IsTrusted(locked_chain, trusted_parents);
+ bool safeTx = wtx.IsTrusted(trusted_parents);
// We should not consider coins from transactions that are replacing
// other transactions.
@@ -2159,11 +2168,11 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
continue;
}
- if (!allow_used_addresses && IsUsedDestination(wtxid, i)) {
+ if (!allow_used_addresses && IsSpentKey(wtxid, i)) {
continue;
}
- std::unique_ptr<SigningProvider> provider = GetSigningProvider(wtx.tx->vout[i].scriptPubKey);
+ std::unique_ptr<SigningProvider> provider = GetSolvingProvider(wtx.tx->vout[i].scriptPubKey);
bool solvable = provider ? IsSolvable(*provider, wtx.tx->vout[i].scriptPubKey) : false;
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
@@ -2187,14 +2196,14 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
}
}
-std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins(interfaces::Chain::Lock& locked_chain) const
+std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins() const
{
AssertLockHeld(cs_wallet);
std::map<CTxDestination, std::vector<COutput>> result;
std::vector<COutput> availableCoins;
- AvailableCoins(locked_chain, availableCoins);
+ AvailableCoins(availableCoins);
for (const COutput& coin : availableCoins) {
CTxDestination address;
@@ -2367,6 +2376,13 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
++it;
}
+ unsigned int limit_ancestor_count = 0;
+ unsigned int limit_descendant_count = 0;
+ chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
+ size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
+ size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
+ bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS);
+
// form groups from remaining coins; note that preset coins will not
// automatically have their associated (same address) coins included
if (coin_control.m_avoid_partial_spends && vCoins.size() > OUTPUT_GROUP_MAX_ENTRIES) {
@@ -2375,14 +2391,7 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
// explicitly shuffling the outputs before processing
Shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());
}
- std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.m_avoid_partial_spends);
-
- unsigned int limit_ancestor_count;
- unsigned int limit_descendant_count;
- chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
- size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
- size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
- bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS);
+ std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.m_avoid_partial_spends, max_ancestors);
bool res = value_to_select <= 0 ||
SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 6, 0), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
@@ -2402,34 +2411,113 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
return res;
}
-bool CWallet::SignTransaction(CMutableTransaction& tx)
+bool CWallet::SignTransaction(CMutableTransaction& tx) const
{
AssertLockHeld(cs_wallet);
- // sign the new tx
- int nIn = 0;
+ // Build coins map
+ std::map<COutPoint, Coin> coins;
for (auto& input : tx.vin) {
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
return false;
}
- const CScript& scriptPubKey = mi->second.tx->vout[input.prevout.n].scriptPubKey;
- const CAmount& amount = mi->second.tx->vout[input.prevout.n].nValue;
- SignatureData sigdata;
+ const CWalletTx& wtx = mi->second;
+ coins[input.prevout] = Coin(wtx.tx->vout[input.prevout.n], wtx.m_confirm.block_height, wtx.IsCoinBase());
+ }
+ std::map<int, std::string> input_errors;
+ return SignTransaction(tx, coins, SIGHASH_ALL, input_errors);
+}
- std::unique_ptr<SigningProvider> provider = GetSigningProvider(scriptPubKey);
- if (!provider) {
- // We don't know about this scriptpbuKey;
- return false;
+bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
+{
+ // Try to sign with all ScriptPubKeyMans
+ for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
+ // spk_man->SignTransaction will return true if the transaction is complete,
+ // so we can exit early and return true if that happens
+ if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
+ return true;
}
+ }
- if (!ProduceSignature(*provider, MutableTransactionSignatureCreator(&tx, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) {
- return false;
+ // At this point, one input was not fully signed otherwise we would have exited already
+ // Find that input and figure out what went wrong.
+ for (unsigned int i = 0; i < tx.vin.size(); i++) {
+ // Get the prevout
+ CTxIn& txin = tx.vin[i];
+ auto coin = coins.find(txin.prevout);
+ if (coin == coins.end() || coin->second.IsSpent()) {
+ input_errors[i] = "Input not found or already spent";
+ continue;
+ }
+
+ // Check if this input is complete
+ SignatureData sigdata = DataFromTransaction(tx, i, coin->second.out);
+ if (!sigdata.complete) {
+ input_errors[i] = "Unable to sign input, missing keys";
+ continue;
}
- UpdateInput(input, sigdata);
- nIn++;
}
- return true;
+ return false;
+}
+
+TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs) const
+{
+ LOCK(cs_wallet);
+ // Get all of the previous transactions
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ const CTxIn& txin = psbtx.tx->vin[i];
+ PSBTInput& input = psbtx.inputs.at(i);
+
+ if (PSBTInputSigned(input)) {
+ continue;
+ }
+
+ // Verify input looks sane. This will check that we have at most one uxto, witness or non-witness.
+ if (!input.IsSane()) {
+ return TransactionError::INVALID_PSBT;
+ }
+
+ // If we have no utxo, grab it from the wallet.
+ if (!input.non_witness_utxo && input.witness_utxo.IsNull()) {
+ const uint256& txhash = txin.prevout.hash;
+ const auto it = mapWallet.find(txhash);
+ if (it != mapWallet.end()) {
+ const CWalletTx& wtx = it->second;
+ // We only need the non_witness_utxo, which is a superset of the witness_utxo.
+ // The signing code will switch to the smaller witness_utxo if this is ok.
+ input.non_witness_utxo = wtx.tx;
+ }
+ }
+ }
+
+ // Fill in information from ScriptPubKeyMans
+ for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
+ TransactionError res = spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs);
+ if (res != TransactionError::OK) {
+ return res;
+ }
+ }
+
+ // Complete if every input is now signed
+ complete = true;
+ for (const auto& input : psbtx.inputs) {
+ complete &= PSBTInputSigned(input);
+ }
+
+ return TransactionError::OK;
+}
+
+SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
+{
+ SignatureData sigdata;
+ CScript script_pub_key = GetScriptForDestination(pkhash);
+ for (const auto& spk_man_pair : m_spk_managers) {
+ if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
+ return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
+ }
+ }
+ return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
}
bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
@@ -2451,11 +2539,10 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
// Acquire the locks to prevent races to the new locked unspents between the
// CreateTransaction call and LockCoin calls (when lockUnspents is true).
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
CTransactionRef tx_new;
- if (!CreateTransaction(*locked_chain, vecSend, tx_new, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) {
+ if (!CreateTransaction(vecSend, tx_new, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) {
return false;
}
@@ -2483,13 +2570,15 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
return true;
}
-static bool IsCurrentForAntiFeeSniping(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain)
+static bool IsCurrentForAntiFeeSniping(interfaces::Chain& chain, const uint256& block_hash)
{
if (chain.isInitialBlockDownload()) {
return false;
}
constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60; // in seconds
- if (locked_chain.getBlockTime(*locked_chain.getHeight()) < (GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
+ int64_t block_time;
+ CHECK_NONFATAL(chain.findBlock(block_hash, FoundBlock().time(block_time)));
+ if (block_time < (GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
return false;
}
return true;
@@ -2499,9 +2588,8 @@ static bool IsCurrentForAntiFeeSniping(interfaces::Chain& chain, interfaces::Cha
* Return a height-based locktime for new transactions (uses the height of the
* current chain tip unless we are not synced with the current chain
*/
-static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain)
+static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, const uint256& block_hash, int block_height)
{
- uint32_t const height = locked_chain.getHeight().get_value_or(-1);
uint32_t locktime;
// Discourage fee sniping.
//
@@ -2523,8 +2611,8 @@ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, interface
// enough, that fee sniping isn't a problem yet, but by implementing a fix
// now we ensure code won't be written that makes assumptions about
// nLockTime that preclude a fix later.
- if (IsCurrentForAntiFeeSniping(chain, locked_chain)) {
- locktime = height;
+ if (IsCurrentForAntiFeeSniping(chain, block_hash)) {
+ locktime = block_height;
// Secondly occasionally randomly pick a nLockTime even further back, so
// that transactions that are delayed after signing for whatever reason,
@@ -2538,7 +2626,6 @@ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, interface
// unique "nLockTime fingerprint", set nLockTime to a constant.
locktime = 0;
}
- assert(locktime <= height);
assert(locktime < LOCKTIME_THRESHOLD);
return locktime;
}
@@ -2571,8 +2658,7 @@ OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vec
return m_default_address_type;
}
-bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet,
- int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign)
+bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign)
{
CAmount nValue = 0;
const OutputType change_type = TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : m_default_change_type, vecSend);
@@ -2598,19 +2684,16 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
}
CMutableTransaction txNew;
-
- txNew.nLockTime = GetLocktimeForNewTransaction(chain(), locked_chain);
-
FeeCalculation feeCalc;
CAmount nFeeNeeded;
int nBytes;
{
std::set<CInputCoin> setCoins;
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
+ txNew.nLockTime = GetLocktimeForNewTransaction(chain(), GetLastBlockHash(), GetLastBlockHeight());
{
std::vector<COutput> vAvailableCoins;
- AvailableCoins(*locked_chain, vAvailableCoins, true, &coin_control, 1, MAX_MONEY, MAX_MONEY, 0);
+ AvailableCoins(vAvailableCoins, true, &coin_control, 1, MAX_MONEY, MAX_MONEY, 0);
CoinSelectionParams coin_selection_params; // Parameters for coin selection, init with dummy
// Create change script that will be used if we need change
@@ -2629,20 +2712,14 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
// rediscover unknown transactions that were written with keys of ours to recover
// post-backup change.
- // Reserve a new key pair from key pool
- if (!CanGetAddresses(true)) {
- strFailReason = _("Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.").translated;
- return false;
- }
+ // Reserve a new key pair from key pool. If it fails, provide a dummy
+ // destination in case we don't need change.
CTxDestination dest;
- bool ret = reservedest.GetReservedDestination(dest, true);
- if (!ret)
- {
- strFailReason = "Keypool ran out, please call keypoolrefill first";
- return false;
+ if (!reservedest.GetReservedDestination(dest, true)) {
+ strFailReason = _("Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.").translated;
}
-
scriptChange = GetScriptForDestination(dest);
+ assert(!dest.empty() || scriptChange.empty());
}
CTxOut change_prototype_txout(0, scriptChange);
coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout);
@@ -2858,6 +2935,11 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
coin_selection_params.use_bnb = false;
continue;
}
+
+ // Give up if change keypool ran out and we failed to find a solution without change:
+ if (scriptChange.empty() && nChangePosInOut != -1) {
+ return false;
+ }
}
// Shuffle selected coins and fill in final vin
@@ -2878,25 +2960,9 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence));
}
- if (sign)
- {
- int nIn = 0;
- for (const auto& coin : selected_coins)
- {
- const CScript& scriptPubKey = coin.txout.scriptPubKey;
- SignatureData sigdata;
-
- std::unique_ptr<SigningProvider> provider = GetSigningProvider(scriptPubKey);
- if (!provider || !ProduceSignature(*provider, MutableTransactionSignatureCreator(&txNew, nIn, coin.txout.nValue, SIGHASH_ALL), scriptPubKey, sigdata))
- {
- strFailReason = _("Signing transaction failed").translated;
- return false;
- } else {
- UpdateInput(txNew.vin.at(nIn), sigdata);
- }
-
- nIn++;
- }
+ if (sign && !SignTransaction(txNew)) {
+ strFailReason = _("Signing transaction failed").translated;
+ return false;
}
// Return the constructed transaction data.
@@ -2940,7 +3006,6 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
CWalletTx wtxNew(this, std::move(tx));
@@ -2980,11 +3045,6 @@ void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
- // Even if we don't use this lock in this function, we want to preserve
- // lock order in LoadToWallet if query of chain state is needed to know
- // tx status. If lock can't be taken (e.g bitcoin-wallet), tx confirmation
- // status may be not reliable.
- auto locked_chain = LockChain();
LOCK(cs_wallet);
fFirstRunRet = false;
@@ -3065,11 +3125,11 @@ bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& add
bool fUpdated = false;
{
LOCK(cs_wallet);
- std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
- fUpdated = mi != mapAddressBook.end();
- mapAddressBook[address].name = strName;
+ std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
+ fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
+ m_address_book[address].SetLabel(strName);
if (!strPurpose.empty()) /* update purpose only if requested */
- mapAddressBook[address].purpose = strPurpose;
+ m_address_book[address].purpose = strPurpose;
}
NotifyAddressBookChanged(this, address, strName, IsMine(address) != ISMINE_NO,
strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
@@ -3086,16 +3146,24 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s
bool CWallet::DelAddressBook(const CTxDestination& address)
{
+ // 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)
+ // NOTE: This isn't a problem for sending addresses because they never have any DestData yet!
+ // When adding new DestData, it should be considered here whether to retain or delete it (or move it?).
+ if (IsMine(address)) {
+ WalletLogPrintf("%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, PACKAGE_BUGREPORT);
+ return false;
+ }
+
{
LOCK(cs_wallet);
// Delete destdata tuples associated with address
std::string strAddress = EncodeDestination(address);
- for (const std::pair<const std::string, std::string> &item : mapAddressBook[address].destdata)
+ for (const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
{
WalletBatch(*database).EraseDestData(strAddress, item.first);
}
- mapAddressBook.erase(address);
+ m_address_book.erase(address);
}
NotifyAddressBookChanged(this, address, "", IsMine(address) != ISMINE_NO, "", CT_DELETED);
@@ -3104,7 +3172,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
return WalletBatch(*database).EraseName(EncodeDestination(address));
}
-size_t CWallet::KeypoolCountExternalKeys()
+size_t CWallet::KeypoolCountExternalKeys() const
{
AssertLockHeld(cs_wallet);
@@ -3146,6 +3214,8 @@ bool CWallet::GetNewDestination(const OutputType type, const std::string label,
if (spk_man) {
spk_man->TopUp();
result = spk_man->GetNewDestination(type, dest, error);
+ } else {
+ error = strprintf("Error: No %s addresses available.", FormatOutputType(type));
}
if (result) {
SetAddressBook(dest, label, "receive");
@@ -3161,7 +3231,7 @@ bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& des
ReserveDestination reservedest(this, type);
if (!reservedest.GetReservedDestination(dest, true)) {
- error = "Error: Keypool ran out, please call keypoolrefill first";
+ error = _("Error: Keypool ran out, please call keypoolrefill first").translated;
return false;
}
@@ -3169,7 +3239,7 @@ bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& des
return true;
}
-int64_t CWallet::GetOldestKeyPoolTime()
+int64_t CWallet::GetOldestKeyPoolTime() const
{
LOCK(cs_wallet);
int64_t oldestKey = std::numeric_limits<int64_t>::max();
@@ -3193,7 +3263,7 @@ void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations
}
}
-std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain::Lock& locked_chain)
+std::map<CTxDestination, CAmount> CWallet::GetAddressBalances() const
{
std::map<CTxDestination, CAmount> balances;
@@ -3204,7 +3274,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain:
{
const CWalletTx& wtx = walletEntry.second;
- if (!wtx.IsTrusted(locked_chain, trusted_parents))
+ if (!wtx.IsTrusted(trusted_parents))
continue;
if (wtx.IsImmatureCoinBase())
@@ -3234,7 +3304,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain:
return balances;
}
-std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
+std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings() const
{
AssertLockHeld(cs_wallet);
std::set< std::set<CTxDestination> > groupings;
@@ -3331,10 +3401,11 @@ std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) co
{
LOCK(cs_wallet);
std::set<CTxDestination> result;
- for (const std::pair<const CTxDestination, CAddressBookData>& item : mapAddressBook)
+ for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
{
+ if (item.second.IsChange()) continue;
const CTxDestination& address = item.first;
- const std::string& strName = item.second.name;
+ const std::string& strName = item.second.GetLabel();
if (strName == label)
result.insert(address);
}
@@ -3419,7 +3490,7 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
/** @} */ // end of Actions
-void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<CKeyID, int64_t>& mapKeyBirth) const {
+void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
AssertLockHeld(cs_wallet);
mapKeyBirth.clear();
@@ -3435,12 +3506,13 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
}
// map in which we'll infer heights of other keys
- const Optional<int> tip_height = locked_chain.getHeight();
- const int max_height = tip_height && *tip_height > 144 ? *tip_height - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
- std::map<CKeyID, int> mapKeyFirstBlock;
+ std::map<CKeyID, const CWalletTx::Confirmation*> mapKeyFirstBlock;
+ CWalletTx::Confirmation max_confirm;
+ max_confirm.block_height = GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
+ CHECK_NONFATAL(chain().findAncestorByHeight(GetLastBlockHash(), max_confirm.block_height, FoundBlock().hash(max_confirm.hashBlock)));
for (const CKeyID &keyid : spk_man->GetKeys()) {
if (mapKeyBirth.count(keyid) == 0)
- mapKeyFirstBlock[keyid] = max_height;
+ mapKeyFirstBlock[keyid] = &max_confirm;
}
// if there are no such keys, we're done
@@ -3451,23 +3523,27 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
for (const auto& entry : mapWallet) {
// iterate over all wallet transactions...
const CWalletTx &wtx = entry.second;
- if (Optional<int> height = locked_chain.getBlockHeight(wtx.m_confirm.hashBlock)) {
+ if (wtx.m_confirm.status == CWalletTx::CONFIRMED) {
// ... which are already in a block
for (const CTxOut &txout : wtx.tx->vout) {
// iterate over all their outputs
for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
// ... and all their affected keys
- std::map<CKeyID, int>::iterator rit = mapKeyFirstBlock.find(keyid);
- if (rit != mapKeyFirstBlock.end() && *height < rit->second)
- rit->second = *height;
+ auto rit = mapKeyFirstBlock.find(keyid);
+ if (rit != mapKeyFirstBlock.end() && wtx.m_confirm.block_height < rit->second->block_height) {
+ rit->second = &wtx.m_confirm;
+ }
}
}
}
}
// Extract block timestamps for those keys
- for (const auto& entry : mapKeyFirstBlock)
- mapKeyBirth[entry.first] = locked_chain.getBlockTime(entry.second) - TIMESTAMP_WINDOW; // block times can be 2h off
+ for (const auto& entry : mapKeyFirstBlock) {
+ int64_t block_time;
+ CHECK_NONFATAL(chain().findBlock(entry.second->hashBlock, FoundBlock().time(block_time)));
+ mapKeyBirth[entry.first] = block_time - TIMESTAMP_WINDOW; // block times can be 2h off
+ }
}
/**
@@ -3496,7 +3572,7 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
unsigned int nTimeSmart = wtx.nTimeReceived;
if (!wtx.isUnconfirmed() && !wtx.isAbandoned()) {
int64_t blocktime;
- if (chain().findBlock(wtx.m_confirm.hashBlock, nullptr /* block */, &blocktime)) {
+ if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(blocktime))) {
int64_t latestNow = wtx.nTimeReceived;
int64_t latestEntry = 0;
@@ -3535,26 +3611,26 @@ bool CWallet::AddDestData(WalletBatch& batch, const CTxDestination &dest, const
if (boost::get<CNoDestination>(&dest))
return false;
- mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
+ m_address_book[dest].destdata.insert(std::make_pair(key, value));
return batch.WriteDestData(EncodeDestination(dest), key, value);
}
bool CWallet::EraseDestData(WalletBatch& batch, const CTxDestination &dest, const std::string &key)
{
- if (!mapAddressBook[dest].destdata.erase(key))
+ if (!m_address_book[dest].destdata.erase(key))
return false;
return batch.EraseDestData(EncodeDestination(dest), key);
}
void CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
{
- mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
+ m_address_book[dest].destdata.insert(std::make_pair(key, value));
}
bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
{
- std::map<CTxDestination, CAddressBookData>::const_iterator i = mapAddressBook.find(dest);
- if(i != mapAddressBook.end())
+ std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
+ if(i != m_address_book.end())
{
CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
if(j != i->second.destdata.end())
@@ -3570,7 +3646,7 @@ bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, st
std::vector<std::string> CWallet::GetDestValues(const std::string& prefix) const
{
std::vector<std::string> values;
- for (const auto& address : mapAddressBook) {
+ for (const auto& address : m_address_book) {
for (const auto& data : address.second.destdata) {
if (!data.first.compare(0, prefix.size(), prefix)) {
values.emplace_back(data.second);
@@ -3624,11 +3700,6 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, b
// Recover readable keypairs:
CWallet dummyWallet(&chain, WalletLocation(), WalletDatabase::CreateDummy());
std::string backup_filename;
- // Even if we don't use this lock in this function, we want to preserve
- // lock order in LoadToWallet if query of chain state is needed to know
- // tx status. If lock can't be taken, tx confirmation status may be not
- // reliable.
- auto locked_chain = dummyWallet.LockChain();
if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
return false;
}
@@ -3689,44 +3760,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
}
}
- int prev_version = walletInstance->GetVersion();
- if (gArgs.GetBoolArg("-upgradewallet", fFirstRun))
- {
- int nMaxVersion = gArgs.GetArg("-upgradewallet", 0);
- if (nMaxVersion == 0) // the -upgradewallet without argument case
- {
- walletInstance->WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
- nMaxVersion = FEATURE_LATEST;
- walletInstance->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
- }
- else
- walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
- if (nMaxVersion < walletInstance->GetVersion())
- {
- error = _("Cannot downgrade wallet").translated;
- return nullptr;
- }
- walletInstance->SetMaxVersion(nMaxVersion);
- }
-
- // Upgrade to HD if explicit upgrade
- if (gArgs.GetBoolArg("-upgradewallet", false)) {
- LOCK(walletInstance->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 = walletInstance->GetVersion();
- if (!walletInstance->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 -upgradewallet=169900 or -upgradewallet with no version specified.").translated;
- return nullptr;
- }
-
- for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
- if (!spk_man->Upgrade(prev_version, error)) {
- return nullptr;
- }
- }
- }
-
if (fFirstRun)
{
// ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
@@ -3734,21 +3767,28 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
walletInstance->SetWalletFlags(wallet_creation_flags, false);
- // Always create LegacyScriptPubKeyMan for now
- walletInstance->SetupLegacyScriptPubKeyMan();
+ // Only create LegacyScriptPubKeyMan when not descriptor wallet
+ if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
+ walletInstance->SetupLegacyScriptPubKeyMan();
+ }
if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
LOCK(walletInstance->cs_wallet);
- for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
- if (!spk_man->SetupGeneration()) {
- error = _("Unable to generate initial keys").translated;
- return nullptr;
+ if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
+ walletInstance->SetupDescriptorScriptPubKeyMans();
+ // SetupDescriptorScriptPubKeyMans already calls SetupGeneration for us so we don't need to call SetupGeneration separately
+ } else {
+ // Legacy wallets need SetupGeneration here.
+ for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
+ if (!spk_man->SetupGeneration()) {
+ error = _("Unable to generate initial keys").translated;
+ return nullptr;
+ }
}
}
}
- auto locked_chain = chain.lock();
- walletInstance->ChainStateFlushed(locked_chain->getTipLocator());
+ walletInstance->chainStateFlushed(chain.getTipLocator());
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
// Make it impossible to disable private keys after creation
error = strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, walletFile);
@@ -3861,24 +3901,33 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// Try to top up keypool. No-op if the wallet is locked.
walletInstance->TopUpKeyPool();
- auto locked_chain = chain.lock();
LOCK(walletInstance->cs_wallet);
+ // Register wallet with validationinterface. It's done before rescan to avoid
+ // missing block connections between end of rescan and validation subscribing.
+ // Because of wallet lock being hold, block connection notifications are going to
+ // be pending on the validation-side until lock release. It's likely to have
+ // block processing duplicata (if rescan block range overlaps with notification one)
+ // but we guarantee at least than wallet state is correct after notifications delivery.
+ // This is temporary until rescan and notifications delivery are unified under same
+ // interface.
+ walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
+
int rescan_height = 0;
if (!gArgs.GetBoolArg("-rescan", false))
{
WalletBatch batch(*walletInstance->database);
CBlockLocator locator;
if (batch.ReadBestBlock(locator)) {
- if (const Optional<int> fork_height = locked_chain->findLocatorFork(locator)) {
+ if (const Optional<int> fork_height = chain.findLocatorFork(locator)) {
rescan_height = *fork_height;
}
}
}
- const Optional<int> tip_height = locked_chain->getHeight();
+ const Optional<int> tip_height = chain.getHeight();
if (tip_height) {
- walletInstance->m_last_block_processed = locked_chain->getBlockHash(*tip_height);
+ walletInstance->m_last_block_processed = chain.getBlockHash(*tip_height);
walletInstance->m_last_block_processed_height = *tip_height;
} else {
walletInstance->m_last_block_processed.SetNull();
@@ -3895,7 +3944,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// If a block is pruned after this check, we will load the wallet,
// but fail the rescan with a generic error.
int block_height = *tip_height;
- while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
+ while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
--block_height;
}
@@ -3910,25 +3959,26 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// No need to read and scan block if block was created before
// our wallet birthday (as adjusted for block time variability)
- Optional<int64_t> time_first_key;
+ // The way the 'time_first_key' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
+ Optional<int64_t> time_first_key = MakeOptional(false, int64_t());;
for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
int64_t time = spk_man->GetTimeFirstKey();
if (!time_first_key || time < *time_first_key) time_first_key = time;
}
if (time_first_key) {
- if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
+ if (Optional<int> first_block = chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
rescan_height = *first_block;
}
}
{
- WalletRescanReserver reserver(walletInstance.get());
- if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) {
+ WalletRescanReserver reserver(*walletInstance);
+ if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, {} /* max height */, reserver, true /* update */).status)) {
error = _("Failed to rescan the wallet during initialization").translated;
return nullptr;
}
}
- walletInstance->ChainStateFlushed(locked_chain->getTipLocator());
+ walletInstance->chainStateFlushed(chain.getTipLocator());
walletInstance->database->IncrementUpdateCounter();
// Restore wallet transaction metadata after -zapwallettxes=1
@@ -3963,28 +4013,65 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
}
}
- // Register with the validation interface. It's ok to do this after rescan since we're still holding locked_chain.
- walletInstance->handleNotifications();
-
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
{
walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
- walletInstance->WalletLogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size());
+ walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size());
}
return walletInstance;
}
-void CWallet::handleNotifications()
+const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
+{
+ const auto& address_book_it = m_address_book.find(dest);
+ if (address_book_it == m_address_book.end()) return nullptr;
+ if ((!allow_change) && address_book_it->second.IsChange()) {
+ return nullptr;
+ }
+ return &address_book_it->second;
+}
+
+bool CWallet::UpgradeWallet(int version, std::string& error, std::vector<std::string>& warnings)
{
- m_chain_notifications_handler = m_chain->handleNotifications(*this);
+ int prev_version = GetVersion();
+ int nMaxVersion = version;
+ if (nMaxVersion == 0) // the -upgradewallet without argument case
+ {
+ WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
+ nMaxVersion = FEATURE_LATEST;
+ SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
+ }
+ else
+ WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
+ if (nMaxVersion < GetVersion())
+ {
+ error = _("Cannot downgrade wallet").translated;
+ 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.").translated;
+ return false;
+ }
+
+ for (auto spk_man : GetActiveScriptPubKeyMans()) {
+ if (!spk_man->Upgrade(prev_version, error)) {
+ return false;
+ }
+ }
+ return true;
}
void CWallet::postInitProcess()
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
// Add wallet transactions that aren't already in a block to mempool
@@ -3995,7 +4082,7 @@ void CWallet::postInitProcess()
chain().requestMempoolTransactions(*this);
}
-bool CWallet::BackupWallet(const std::string& strDest)
+bool CWallet::BackupWallet(const std::string& strDest) const
{
return database->Backup(strDest);
}
@@ -4039,32 +4126,49 @@ bool CWalletTx::IsImmatureCoinBase() const
return GetBlocksToMaturity() > 0;
}
-std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const {
+std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outputs, bool single_coin, const size_t max_ancestors) const {
std::vector<OutputGroup> groups;
std::map<CTxDestination, OutputGroup> gmap;
- CTxDestination dst;
+ std::set<CTxDestination> full_groups;
+
for (const auto& output : outputs) {
if (output.fSpendable) {
+ CTxDestination dst;
CInputCoin input_coin = output.GetInputCoin();
size_t ancestors, descendants;
chain().getTransactionAncestry(output.tx->GetHash(), ancestors, descendants);
if (!single_coin && ExtractDestination(output.tx->tx->vout[output.i].scriptPubKey, dst)) {
- // Limit output groups to no more than 10 entries, to protect
- // against inadvertently creating a too-large transaction
- // when using -avoidpartialspends
- if (gmap[dst].m_outputs.size() >= OUTPUT_GROUP_MAX_ENTRIES) {
- groups.push_back(gmap[dst]);
- gmap.erase(dst);
+ auto it = gmap.find(dst);
+ if (it != gmap.end()) {
+ // Limit output groups to no more than OUTPUT_GROUP_MAX_ENTRIES
+ // number of entries, to protect against inadvertently creating
+ // a too-large transaction when using -avoidpartialspends to
+ // prevent breaking consensus or surprising users with a very
+ // high amount of fees.
+ if (it->second.m_outputs.size() >= OUTPUT_GROUP_MAX_ENTRIES) {
+ groups.push_back(it->second);
+ it->second = OutputGroup{};
+ full_groups.insert(dst);
+ }
+ it->second.Insert(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
+ } else {
+ gmap[dst].Insert(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
}
- gmap[dst].Insert(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
} else {
groups.emplace_back(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
}
}
}
if (!single_coin) {
- for (const auto& it : gmap) groups.push_back(it.second);
+ for (auto& it : gmap) {
+ auto& group = it.second;
+ if (full_groups.count(it.first) > 0) {
+ // Make this unattractive as we want coin selection to avoid it if possible
+ group.m_ancestors = max_ancestors - 1;
+ }
+ groups.push_back(group);
+ }
}
return groups;
}
@@ -4146,6 +4250,17 @@ ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const OutputType& type, bool intern
return it->second;
}
+std::set<ScriptPubKeyMan*> CWallet::GetScriptPubKeyMans(const CScript& script, SignatureData& sigdata) const
+{
+ std::set<ScriptPubKeyMan*> spk_mans;
+ for (const auto& spk_man_pair : m_spk_managers) {
+ if (spk_man_pair.second->CanProvide(script, sigdata)) {
+ spk_mans.insert(spk_man_pair.second.get());
+ }
+ }
+ return spk_mans;
+}
+
ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const CScript& script) const
{
SignatureData sigdata;
@@ -4165,17 +4280,17 @@ ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const uint256& id) const
return nullptr;
}
-std::unique_ptr<SigningProvider> CWallet::GetSigningProvider(const CScript& script) const
+std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script) const
{
SignatureData sigdata;
- return GetSigningProvider(script, sigdata);
+ return GetSolvingProvider(script, sigdata);
}
-std::unique_ptr<SigningProvider> CWallet::GetSigningProvider(const CScript& script, SignatureData& sigdata) const
+std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script, SignatureData& sigdata) const
{
for (const auto& spk_man_pair : m_spk_managers) {
if (spk_man_pair.second->CanProvide(script, sigdata)) {
- return spk_man_pair.second->GetSigningProvider(script);
+ return spk_man_pair.second->GetSolvingProvider(script);
}
}
return nullptr;
@@ -4183,6 +4298,9 @@ std::unique_ptr<SigningProvider> CWallet::GetSigningProvider(const CScript& scri
LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
{
+ if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
+ return nullptr;
+ }
// Legacy wallets only have one ScriptPubKeyMan which is a LegacyScriptPubKeyMan.
// Everything in m_internal_spk_managers and m_external_spk_managers point to the same legacyScriptPubKeyMan.
auto it = m_internal_spk_managers.find(OutputType::LEGACY);
@@ -4198,7 +4316,7 @@ LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
void CWallet::SetupLegacyScriptPubKeyMan()
{
- if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty()) {
+ if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty() || IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
return;
}
@@ -4227,3 +4345,153 @@ void CWallet::ConnectScriptPubKeyManNotifiers()
spk_man->NotifyCanGetAddressesChanged.connect(NotifyCanGetAddressesChanged);
}
}
+
+void CWallet::LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc)
+{
+ auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc));
+ m_spk_managers[id] = std::move(spk_manager);
+}
+
+void CWallet::SetupDescriptorScriptPubKeyMans()
+{
+ AssertLockHeld(cs_wallet);
+
+ // Make a seed
+ CKey seed_key;
+ seed_key.MakeNewKey(true);
+ CPubKey seed = seed_key.GetPubKey();
+ assert(seed_key.VerifyPubKey(seed));
+
+ // Get the extended key
+ CExtKey master_key;
+ master_key.SetSeed(seed_key.begin(), seed_key.size());
+
+ for (bool internal : {false, true}) {
+ for (OutputType t : OUTPUT_TYPES) {
+ auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, t, internal));
+ if (IsCrypted()) {
+ if (IsLocked()) {
+ throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
+ }
+ if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, nullptr)) {
+ throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
+ }
+ }
+ spk_manager->SetupDescriptorGeneration(master_key);
+ uint256 id = spk_manager->GetID();
+ m_spk_managers[id] = std::move(spk_manager);
+ SetActiveScriptPubKeyMan(id, t, internal);
+ }
+ }
+}
+
+void CWallet::SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly)
+{
+ WalletLogPrintf("Setting spkMan to active: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
+ auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
+ auto spk_man = m_spk_managers.at(id).get();
+ spk_man->SetType(type, internal);
+ spk_mans[type] = spk_man;
+
+ if (!memonly) {
+ WalletBatch batch(*database);
+ if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
+ throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
+ }
+ }
+ NotifyCanGetAddressesChanged();
+}
+
+bool CWallet::IsLegacy() const
+{
+ if (m_internal_spk_managers.count(OutputType::LEGACY) == 0) {
+ return false;
+ }
+ auto spk_man = dynamic_cast<LegacyScriptPubKeyMan*>(m_internal_spk_managers.at(OutputType::LEGACY));
+ return spk_man != nullptr;
+}
+
+DescriptorScriptPubKeyMan* CWallet::GetDescriptorScriptPubKeyMan(const WalletDescriptor& desc) const
+{
+ for (auto& spk_man_pair : m_spk_managers) {
+ // Try to downcast to DescriptorScriptPubKeyMan then check if the descriptors match
+ DescriptorScriptPubKeyMan* spk_manager = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man_pair.second.get());
+ if (spk_manager != nullptr && spk_manager->HasWalletDescriptor(desc)) {
+ return spk_manager;
+ }
+ }
+
+ return nullptr;
+}
+
+ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label)
+{
+ if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
+ WalletLogPrintf("Cannot add WalletDescriptor to a non-descriptor wallet\n");
+ return nullptr;
+ }
+
+ LOCK(cs_wallet);
+ auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc));
+
+ // If we already have this descriptor, remove it from the maps but add the existing cache to desc
+ auto old_spk_man = GetDescriptorScriptPubKeyMan(desc);
+ if (old_spk_man) {
+ WalletLogPrintf("Update existing descriptor: %s\n", desc.descriptor->ToString());
+
+ {
+ LOCK(old_spk_man->cs_desc_man);
+ new_spk_man->SetCache(old_spk_man->GetWalletDescriptor().cache);
+ }
+
+ // Remove from maps of active spkMans
+ auto old_spk_man_id = old_spk_man->GetID();
+ for (bool internal : {false, true}) {
+ for (OutputType t : OUTPUT_TYPES) {
+ auto active_spk_man = GetScriptPubKeyMan(t, internal);
+ if (active_spk_man && active_spk_man->GetID() == old_spk_man_id) {
+ if (internal) {
+ m_internal_spk_managers.erase(t);
+ } else {
+ m_external_spk_managers.erase(t);
+ }
+ break;
+ }
+ }
+ }
+ m_spk_managers.erase(old_spk_man_id);
+ }
+
+ // Add the private keys to the descriptor
+ for (const auto& entry : signing_provider.keys) {
+ const CKey& key = entry.second;
+ new_spk_man->AddDescriptorKey(key, key.GetPubKey());
+ }
+
+ // Top up key pool, the manager will generate new scriptPubKeys internally
+ new_spk_man->TopUp();
+
+ // Apply the label if necessary
+ // Note: we disable labels for ranged descriptors
+ if (!desc.descriptor->IsRange()) {
+ auto script_pub_keys = new_spk_man->GetScriptPubKeys();
+ if (script_pub_keys.empty()) {
+ WalletLogPrintf("Could not generate scriptPubKeys (cache is empty)\n");
+ return nullptr;
+ }
+
+ CTxDestination dest;
+ if (ExtractDestination(script_pub_keys.at(0), dest)) {
+ SetAddressBook(dest, label, "receive");
+ }
+ }
+
+ // Save the descriptor to memory
+ auto ret = new_spk_man.get();
+ m_spk_managers[new_spk_man->GetID()] = std::move(new_spk_man);
+
+ // Save the descriptor to DB
+ ret->WriteDescriptor();
+
+ return ret;
+}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index a918bb8833..72b3cf1fb8 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -11,9 +11,12 @@
#include <interfaces/handler.h>
#include <outputtype.h>
#include <policy/feerate.h>
+#include <psbt.h>
#include <tinyformat.h>
#include <ui_interface.h>
+#include <util/message.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <util/system.h>
#include <validationinterface.h>
#include <wallet/coinselection.h>
@@ -108,7 +111,8 @@ static constexpr uint64_t KNOWN_WALLET_FLAGS =
WALLET_FLAG_AVOID_REUSE
| WALLET_FLAG_BLANK_WALLET
| WALLET_FLAG_KEY_ORIGIN_METADATA
- | WALLET_FLAG_DISABLE_PRIVATE_KEYS;
+ | WALLET_FLAG_DISABLE_PRIVATE_KEYS
+ | WALLET_FLAG_DESCRIPTORS;
static constexpr uint64_t MUTABLE_WALLET_FLAGS =
WALLET_FLAG_AVOID_REUSE;
@@ -118,6 +122,7 @@ static const std::map<std::string,WalletFlags> WALLET_FLAG_MAP{
{"blank", WALLET_FLAG_BLANK_WALLET},
{"key_origin_metadata", WALLET_FLAG_KEY_ORIGIN_METADATA},
{"disable_private_keys", WALLET_FLAG_DISABLE_PRIVATE_KEYS},
+ {"descriptor_wallet", WALLET_FLAG_DESCRIPTORS},
};
extern const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS;
@@ -141,7 +146,7 @@ class ReserveDestination
{
protected:
//! The wallet to reserve from
- CWallet* const pwallet;
+ const CWallet* const pwallet;
//! The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called
ScriptPubKeyMan* m_spk_man{nullptr};
OutputType const type;
@@ -178,14 +183,23 @@ public:
/** Address book data */
class CAddressBookData
{
+private:
+ bool m_change{true};
+ std::string m_label;
public:
- std::string name;
std::string purpose;
CAddressBookData() : purpose("unknown") {}
typedef std::map<std::string, std::string> StringMap;
StringMap destdata;
+
+ bool IsChange() const { return m_change; }
+ const std::string& GetLabel() const { return m_label; }
+ void SetLabel(const std::string& label) {
+ m_change = false;
+ m_label = label;
+ }
};
struct CRecipient
@@ -213,7 +227,7 @@ static inline void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
{
if (nOrderPos == -1)
return;
- mapValue["n"] = i64tostr(nOrderPos);
+ mapValue["n"] = ToString(nOrderPos);
}
struct COutputEntry
@@ -485,8 +499,8 @@ public:
bool IsEquivalentTo(const CWalletTx& tx) const;
bool InMempool() const;
- bool IsTrusted(interfaces::Chain::Lock& locked_chain) const;
- bool IsTrusted(interfaces::Chain::Lock& locked_chain, std::set<uint256>& trusted_parents) const;
+ bool IsTrusted() const;
+ bool IsTrusted(std::set<uint256>& trusted_parents) const;
int64_t GetTxTime() const;
@@ -603,7 +617,7 @@ class WalletRescanReserver; //forward declarations for ScanForWalletTransactions
/**
* A CWallet maintains a set of transactions and balances, and provides the ability to create new transactions.
*/
-class CWallet final : public WalletStorage, private interfaces::Chain::Notifications
+class CWallet final : public WalletStorage, public interfaces::Chain::Notifications
{
private:
CKeyingMaterial vMasterKey GUARDED_BY(cs_wallet);
@@ -761,8 +775,8 @@ public:
bool IsLocked() const override;
bool Lock();
- /** Interface to assert chain access and if successful lock it */
- std::unique_ptr<interfaces::Chain::Lock> LockChain() { return m_chain ? m_chain->lock() : nullptr; }
+ /** Interface to assert chain access */
+ bool HaveChain() const { return m_chain ? true : false; }
std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
@@ -772,16 +786,14 @@ public:
int64_t nOrderPosNext GUARDED_BY(cs_wallet) = 0;
uint64_t nAccountingEntryNumber = 0;
- std::map<CTxDestination, CAddressBookData> mapAddressBook GUARDED_BY(cs_wallet);
+ std::map<CTxDestination, CAddressBookData> m_address_book GUARDED_BY(cs_wallet);
+ const CAddressBookData* FindAddressBookEntry(const CTxDestination&, bool allow_change = false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::set<COutPoint> setLockedCoins GUARDED_BY(cs_wallet);
/** Registered interfaces::Chain::Notifications handler. */
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
- /** Register the wallet for chain notifications */
- void handleNotifications();
-
/** Interface for accessing chain state. */
interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
@@ -793,12 +805,12 @@ public:
/**
* populate vCoins with vector of available COutputs.
*/
- void AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<COutput>& vCoins, bool fOnlySafe = true, const CCoinControl* coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe = true, const CCoinControl* coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Return list of available coins and locked coins grouped by non-change output address.
*/
- std::map<CTxDestination, std::vector<COutput>> ListCoins(interfaces::Chain::Lock& locked_chain) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ std::map<CTxDestination, std::vector<COutput>> ListCoins() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Find non-change parent output.
@@ -817,10 +829,10 @@ public:
bool IsSpent(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
// Whether this or any known UTXO with the same single key has been spent.
- bool IsUsedDestination(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void SetUsedDestinationState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool IsSpentKey(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const;
+ std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin, const size_t max_ancestors) const;
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void LockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -832,8 +844,8 @@ public:
* Rescan abort properties
*/
void AbortRescan() { fAbortRescan = true; }
- bool IsAbortingRescan() { return fAbortRescan; }
- bool IsScanning() { return fScanningWallet; }
+ bool IsAbortingRescan() const { return fAbortRescan; }
+ bool IsScanning() const { return fScanningWallet; }
int64_t ScanningDuration() const { return fScanningWallet ? GetTimeMillis() - m_scanning_start : 0; }
double ScanningProgress() const { return fScanningWallet ? (double) m_scanning_progress : 0; }
@@ -842,7 +854,10 @@ public:
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
- //! Adds a destination data tuple to the store, and saves it to disk
+ /**
+ * Adds a destination data tuple to the store, and saves it to disk
+ * When adding new fields, take care to consider how DelAddressBook should handle it!
+ */
bool AddDestData(WalletBatch& batch, const CTxDestination& dest, const std::string& key, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Erases a destination data tuple in the store and on disk
bool EraseDestData(WalletBatch& batch, const CTxDestination& dest, const std::string& key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -860,7 +875,7 @@ public:
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);
- void GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
/**
@@ -873,10 +888,10 @@ public:
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
void LoadToWallet(CWalletTx& wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void TransactionAddedToMempool(const CTransactionRef& tx) override;
- void BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& vtxConflicted, int height) override;
- void BlockDisconnected(const CBlock& block, int height) override;
- void UpdatedBlockTip() override;
+ void transactionAddedToMempool(const CTransactionRef& tx) override;
+ void blockConnected(const CBlock& block, int height) override;
+ void blockDisconnected(const CBlock& block, int height) override;
+ void updatedBlockTip() override;
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
struct ScanResult {
@@ -894,8 +909,8 @@ public:
//! USER_ABORT.
uint256 last_failed_block;
};
- ScanResult ScanForWalletTransactions(const uint256& first_block, const uint256& last_block, const WalletRescanReserver& reserver, bool fUpdate);
- void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
+ ScanResult ScanForWalletTransactions(const uint256& start_block, int start_height, Optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate);
+ void transactionRemovedFromMempool(const CTransactionRef &ptx) override;
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void ResendWalletTransactions();
struct Balance {
@@ -916,15 +931,37 @@ public:
* calling CreateTransaction();
*/
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
- bool SignTransaction(CMutableTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ // Fetch the inputs and sign with SIGHASH_ALL.
+ bool SignTransaction(CMutableTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ // Sign the tx given the input coins and sighash.
+ bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const;
+ SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const;
+
+ /**
+ * Fills out a PSBT with information from the wallet. Fills in UTXOs if we have
+ * them. Tries to sign if sign=true. Sets `complete` if the PSBT is now complete
+ * (i.e. has all required signatures or signature-parts, and is ready to
+ * finalize.) Sets `error` and returns false if something goes wrong.
+ *
+ * @param[in] psbtx PartiallySignedTransaction to fill in
+ * @param[out] complete indicates whether the PSBT is now complete
+ * @param[in] sighash_type the sighash type to use when signing (if PSBT does not specify)
+ * @param[in] sign whether to sign or not
+ * @param[in] bip32derivs whether to fill in bip32 derivation information if available
+ * return error
+ */
+ TransactionError FillPSBT(PartiallySignedTransaction& psbtx,
+ bool& complete,
+ int sighash_type = 1 /* SIGHASH_ALL */,
+ bool sign = true,
+ bool bip32derivs = true) const;
/**
* Create a new transaction paying the recipients with a set of coins
* selected by SelectCoins(); Also create the change output, when needed
* @note passing nChangePosInOut as -1 will result in setting a random position
*/
- bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut,
- std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
+ bool CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
/**
* Submit the transaction to the node's mempool and then relay to peers.
* Should be called after CreateTransaction unless you want to abort
@@ -968,13 +1005,13 @@ public:
/** Absolute maximum transaction fee (in satoshis) used by default for the wallet */
CAmount m_default_max_tx_fee{DEFAULT_TRANSACTION_MAXFEE};
- size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool TopUpKeyPool(unsigned int kpSize = 0);
- int64_t GetOldestKeyPoolTime();
+ int64_t GetOldestKeyPoolTime() const;
- std::set<std::set<CTxDestination>> GetAddressGroupings() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- std::map<CTxDestination, CAmount> GetAddressBalances(interfaces::Chain::Lock& locked_chain);
+ std::set<std::set<CTxDestination>> GetAddressGroupings() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ std::map<CTxDestination, CAmount> GetAddressBalances() const;
std::set<CTxDestination> GetLabelAddresses(const std::string& label) const;
@@ -1008,7 +1045,7 @@ public:
bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const;
CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const;
CAmount GetChange(const CTransaction& tx) const;
- void ChainStateFlushed(const CBlockLocator& loc) override;
+ void chainStateFlushed(const CBlockLocator& loc) override;
DBErrors LoadWallet(bool& fFirstRunRet);
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
@@ -1027,7 +1064,7 @@ public:
bool SetMaxVersion(int nVersion);
//! get the current wallet format (the oldest client version guaranteed to understand this wallet)
- int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
+ int GetVersion() const { LOCK(cs_wallet); return nWalletVersion; }
//! Get wallet transactions that conflict with given transaction (spend same outputs)
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -1098,13 +1135,13 @@ public:
*/
void postInitProcess();
- bool BackupWallet(const std::string& strDest);
+ bool BackupWallet(const std::string& strDest) const;
/* Returns true if HD is enabled */
bool IsHDEnabled() const;
/* Returns true if the wallet can give out new addresses. This means it has keys in the keypool or can generate new keys */
- bool CanGetAddresses(bool internal = false);
+ bool CanGetAddresses(bool internal = false) const;
/**
* Blocks until the wallet state is up-to-date to /at least/ the current
@@ -1112,7 +1149,7 @@ public:
* Obviously holding cs_main/cs_wallet when going into this call may cause
* deadlock
*/
- void BlockUntilSyncedToCurrentChain() LOCKS_EXCLUDED(cs_main, cs_wallet);
+ void BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(cs_main, cs_wallet);
/** set a single wallet flag */
void SetWalletFlag(uint64_t flags);
@@ -1127,6 +1164,9 @@ public:
returns false if unknown, non-tolerable flags are present */
bool SetWalletFlags(uint64_t overwriteFlags, bool memOnly);
+ /** Determine if we are a legacy wallet */
+ bool IsLegacy() const;
+
/** Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet has no name */
const std::string GetDisplayName() const override {
std::string wallet_name = GetName().length() == 0 ? "default wallet" : GetName();
@@ -1139,6 +1179,9 @@ public:
LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...);
};
+ /** Upgrade the wallet */
+ bool UpgradeWallet(int version, std::string& error, std::vector<std::string>& warnings);
+
//! Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers
std::set<ScriptPubKeyMan*> GetActiveScriptPubKeyMans() const;
@@ -1153,9 +1196,12 @@ public:
//! Get the ScriptPubKeyMan by id
ScriptPubKeyMan* GetScriptPubKeyMan(const uint256& id) const;
+ //! Get all of the ScriptPubKeyMans for a script given additional information in sigdata (populated by e.g. a psbt)
+ std::set<ScriptPubKeyMan*> GetScriptPubKeyMans(const CScript& script, SignatureData& sigdata) const;
+
//! Get the SigningProvider for a script
- std::unique_ptr<SigningProvider> GetSigningProvider(const CScript& script) const;
- std::unique_ptr<SigningProvider> GetSigningProvider(const CScript& script, SignatureData& sigdata) const;
+ std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const;
+ std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script, SignatureData& sigdata) const;
//! Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const;
@@ -1174,6 +1220,12 @@ public:
assert(m_last_block_processed_height >= 0);
return m_last_block_processed_height;
};
+ uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
+ {
+ AssertLockHeld(cs_wallet);
+ assert(m_last_block_processed_height >= 0);
+ return m_last_block_processed;
+ }
/** Set last block processed height, currently only use in unit test */
void SetLastBlockProcessed(int block_height, uint256 block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
{
@@ -1184,6 +1236,25 @@ public:
//! Connect the signals from ScriptPubKeyMans to the signals in CWallet
void ConnectScriptPubKeyManNotifiers();
+
+ //! Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it
+ void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc);
+
+ //! Sets the active ScriptPubKeyMan for the specified type and internal
+ //! @param[in] id The unique id for the ScriptPubKeyMan
+ //! @param[in] type The OutputType this ScriptPubKeyMan provides addresses for
+ //! @param[in] internal Whether this ScriptPubKeyMan provides change addresses
+ //! @param[in] memonly Whether to record this update to the database. Set to true for wallet loading, normally false when actually updating the wallet.
+ void SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly = false);
+
+ //! Create new DescriptorScriptPubKeyMans and add them to the wallet
+ void SetupDescriptorScriptPubKeyMans();
+
+ //! Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet
+ 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);
};
/**
@@ -1196,35 +1267,35 @@ void MaybeResendWalletTxs();
class WalletRescanReserver
{
private:
- CWallet* m_wallet;
+ CWallet& m_wallet;
bool m_could_reserve;
public:
- explicit WalletRescanReserver(CWallet* w) : m_wallet(w), m_could_reserve(false) {}
+ explicit WalletRescanReserver(CWallet& w) : m_wallet(w), m_could_reserve(false) {}
bool reserve()
{
assert(!m_could_reserve);
- std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
- if (m_wallet->fScanningWallet) {
+ std::lock_guard<std::mutex> lock(m_wallet.mutexScanning);
+ if (m_wallet.fScanningWallet) {
return false;
}
- m_wallet->m_scanning_start = GetTimeMillis();
- m_wallet->m_scanning_progress = 0;
- m_wallet->fScanningWallet = true;
+ m_wallet.m_scanning_start = GetTimeMillis();
+ m_wallet.m_scanning_progress = 0;
+ m_wallet.fScanningWallet = true;
m_could_reserve = true;
return true;
}
bool isReserved() const
{
- return (m_could_reserve && m_wallet->fScanningWallet);
+ return (m_could_reserve && m_wallet.fScanningWallet);
}
~WalletRescanReserver()
{
- std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
+ std::lock_guard<std::mutex> lock(m_wallet.mutexScanning);
if (m_could_reserve) {
- m_wallet->fScanningWallet = false;
+ m_wallet.fScanningWallet = false;
}
}
};
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index a1928f45c4..79316ca3e7 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -21,6 +21,8 @@
namespace DBKeys {
const std::string ACENTRY{"acentry"};
+const std::string ACTIVEEXTERNALSPK{"activeexternalspk"};
+const std::string ACTIVEINTERNALSPK{"activeinternalspk"};
const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"};
const std::string BESTBLOCK{"bestblock"};
const std::string CRYPTED_KEY{"ckey"};
@@ -41,6 +43,10 @@ const std::string PURPOSE{"purpose"};
const std::string SETTINGS{"settings"};
const std::string TX{"tx"};
const std::string VERSION{"version"};
+const std::string WALLETDESCRIPTOR{"walletdescriptor"};
+const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"};
+const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"};
+const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"};
const std::string WATCHMETA{"watchmeta"};
const std::string WATCHS{"watchs"};
} // namespace DBKeys
@@ -179,6 +185,51 @@ bool WalletBatch::WriteMinVersion(int nVersion)
return WriteIC(DBKeys::MINVERSION, nVersion);
}
+bool WalletBatch::WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal)
+{
+ std::string key = internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK;
+ return WriteIC(make_pair(key, type), id);
+}
+
+bool WalletBatch::WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey)
+{
+ // hash pubkey/privkey to accelerate wallet load
+ std::vector<unsigned char> key;
+ key.reserve(pubkey.size() + privkey.size());
+ key.insert(key.end(), pubkey.begin(), pubkey.end());
+ key.insert(key.end(), privkey.begin(), privkey.end());
+
+ return WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY, std::make_pair(desc_id, pubkey)), std::make_pair(privkey, Hash(key.begin(), key.end())), false);
+}
+
+bool WalletBatch::WriteCryptedDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const std::vector<unsigned char>& secret)
+{
+ if (!WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORCKEY, std::make_pair(desc_id, pubkey)), secret, false)) {
+ return false;
+ }
+ EraseIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY, std::make_pair(desc_id, pubkey)));
+ return true;
+}
+
+bool WalletBatch::WriteDescriptor(const uint256& desc_id, const WalletDescriptor& descriptor)
+{
+ return WriteIC(make_pair(DBKeys::WALLETDESCRIPTOR, desc_id), descriptor);
+}
+
+bool WalletBatch::WriteDescriptorDerivedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index, uint32_t der_index)
+{
+ std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE);
+ xpub.Encode(ser_xpub.data());
+ return WriteIC(std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORCACHE, desc_id), std::make_pair(key_exp_index, der_index)), ser_xpub);
+}
+
+bool WalletBatch::WriteDescriptorParentCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index)
+{
+ std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE);
+ xpub.Encode(ser_xpub.data());
+ return WriteIC(std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORCACHE, desc_id), key_exp_index), ser_xpub);
+}
+
class CWalletScanState {
public:
unsigned int nKeys{0};
@@ -189,6 +240,11 @@ public:
bool fIsEncrypted{false};
bool fAnyUnordered{false};
std::vector<uint256> vWalletUpgrade;
+ std::map<OutputType, uint256> m_active_external_spks;
+ std::map<OutputType, uint256> m_active_internal_spks;
+ std::map<uint256, DescriptorCache> m_descriptor_caches;
+ std::map<std::pair<uint256, CKeyID>, CKey> m_descriptor_keys;
+ std::map<std::pair<uint256, CKeyID>, std::pair<CPubKey, std::vector<unsigned char>>> m_descriptor_crypt_keys;
CWalletScanState() {
}
@@ -206,11 +262,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
if (strType == DBKeys::NAME) {
std::string strAddress;
ssKey >> strAddress;
- ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name;
+ std::string label;
+ ssValue >> label;
+ pwallet->m_address_book[DecodeDestination(strAddress)].SetLabel(label);
} else if (strType == DBKeys::PURPOSE) {
std::string strAddress;
ssKey >> strAddress;
- ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose;
+ ssValue >> pwallet->m_address_book[DecodeDestination(strAddress)].purpose;
} else if (strType == DBKeys::TX) {
uint256 hash;
ssKey >> hash;
@@ -402,6 +460,108 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
} else if (strType == DBKeys::OLD_KEY) {
strErr = "Found unsupported 'wkey' record, try loading with version 0.18";
return false;
+ } else if (strType == DBKeys::ACTIVEEXTERNALSPK || strType == DBKeys::ACTIVEINTERNALSPK) {
+ uint8_t type;
+ ssKey >> type;
+ uint256 id;
+ ssValue >> id;
+
+ bool internal = strType == DBKeys::ACTIVEINTERNALSPK;
+ auto& spk_mans = internal ? wss.m_active_internal_spks : wss.m_active_external_spks;
+ if (spk_mans.count(static_cast<OutputType>(type)) > 0) {
+ strErr = "Multiple ScriptPubKeyMans specified for a single type";
+ return false;
+ }
+ spk_mans[static_cast<OutputType>(type)] = id;
+ } else if (strType == DBKeys::WALLETDESCRIPTOR) {
+ uint256 id;
+ ssKey >> id;
+ WalletDescriptor desc;
+ ssValue >> desc;
+ if (wss.m_descriptor_caches.count(id) == 0) {
+ wss.m_descriptor_caches[id] = DescriptorCache();
+ }
+ pwallet->LoadDescriptorScriptPubKeyMan(id, desc);
+ } else if (strType == DBKeys::WALLETDESCRIPTORCACHE) {
+ bool parent = true;
+ uint256 desc_id;
+ uint32_t key_exp_index;
+ uint32_t der_index;
+ ssKey >> desc_id;
+ ssKey >> key_exp_index;
+
+ // if the der_index exists, it's a derived xpub
+ try
+ {
+ ssKey >> der_index;
+ parent = false;
+ }
+ catch (...) {}
+
+ std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE);
+ ssValue >> ser_xpub;
+ CExtPubKey xpub;
+ xpub.Decode(ser_xpub.data());
+ if (wss.m_descriptor_caches.count(desc_id)) {
+ wss.m_descriptor_caches[desc_id] = DescriptorCache();
+ }
+ if (parent) {
+ wss.m_descriptor_caches[desc_id].CacheParentExtPubKey(key_exp_index, xpub);
+ } else {
+ wss.m_descriptor_caches[desc_id].CacheDerivedExtPubKey(key_exp_index, der_index, xpub);
+ }
+ } else if (strType == DBKeys::WALLETDESCRIPTORKEY) {
+ uint256 desc_id;
+ CPubKey pubkey;
+ ssKey >> desc_id;
+ ssKey >> pubkey;
+ if (!pubkey.IsValid())
+ {
+ strErr = "Error reading wallet database: CPubKey corrupt";
+ return false;
+ }
+ CKey key;
+ CPrivKey pkey;
+ uint256 hash;
+
+ wss.nKeys++;
+ ssValue >> pkey;
+ ssValue >> hash;
+
+ // hash pubkey/privkey to accelerate wallet load
+ std::vector<unsigned char> to_hash;
+ to_hash.reserve(pubkey.size() + pkey.size());
+ to_hash.insert(to_hash.end(), pubkey.begin(), pubkey.end());
+ to_hash.insert(to_hash.end(), pkey.begin(), pkey.end());
+
+ if (Hash(to_hash.begin(), to_hash.end()) != hash)
+ {
+ strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
+ return false;
+ }
+
+ if (!key.Load(pkey, pubkey, true))
+ {
+ strErr = "Error reading wallet database: CPrivKey corrupt";
+ return false;
+ }
+ wss.m_descriptor_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), key));
+ } else if (strType == DBKeys::WALLETDESCRIPTORCKEY) {
+ uint256 desc_id;
+ CPubKey pubkey;
+ ssKey >> desc_id;
+ ssKey >> pubkey;
+ if (!pubkey.IsValid())
+ {
+ strErr = "Error reading wallet database: CPubKey corrupt";
+ return false;
+ }
+ std::vector<unsigned char> privkey;
+ ssValue >> privkey;
+ wss.nCKeys++;
+
+ wss.m_descriptor_crypt_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), std::make_pair(pubkey, privkey)));
+ wss.fIsEncrypted = true;
} else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE &&
strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY &&
strType != DBKeys::VERSION && strType != DBKeys::SETTINGS) {
@@ -495,6 +655,31 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
result = DBErrors::CORRUPT;
}
+ // Set the active ScriptPubKeyMans
+ for (auto spk_man_pair : wss.m_active_external_spks) {
+ pwallet->SetActiveScriptPubKeyMan(spk_man_pair.second, spk_man_pair.first, /* internal */ false, /* memonly */ true);
+ }
+ for (auto spk_man_pair : wss.m_active_internal_spks) {
+ pwallet->SetActiveScriptPubKeyMan(spk_man_pair.second, spk_man_pair.first, /* internal */ true, /* memonly */ true);
+ }
+
+ // Set the descriptor caches
+ for (auto desc_cache_pair : wss.m_descriptor_caches) {
+ auto spk_man = pwallet->GetScriptPubKeyMan(desc_cache_pair.first);
+ assert(spk_man);
+ ((DescriptorScriptPubKeyMan*)spk_man)->SetCache(desc_cache_pair.second);
+ }
+
+ // Set the descriptor keys
+ for (auto desc_key_pair : wss.m_descriptor_keys) {
+ auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
+ ((DescriptorScriptPubKeyMan*)spk_man)->AddKey(desc_key_pair.first.second, desc_key_pair.second);
+ }
+ for (auto desc_key_pair : wss.m_descriptor_crypt_keys) {
+ auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
+ ((DescriptorScriptPubKeyMan*)spk_man)->AddCryptedKey(desc_key_pair.first.second, desc_key_pair.second.first, desc_key_pair.second.second);
+ }
+
if (fNoncriticalErrors && result == DBErrors::LOAD_OK)
result = DBErrors::NONCRITICAL_ERROR;
@@ -514,7 +699,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys, wss.m_unknown_records);
// nTimeFirstKey is only reliable if all keys have metadata
- if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) {
+ if (pwallet->IsLegacy() && (wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) {
auto spk_man = pwallet->GetOrCreateLegacyScriptPubKeyMan();
if (spk_man) {
LOCK(spk_man->cs_KeyStore);
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 1a65125480..2701481c58 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-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.
@@ -9,6 +9,7 @@
#include <amount.h>
#include <script/sign.h>
#include <wallet/db.h>
+#include <wallet/walletutil.h>
#include <key.h>
#include <stdint.h>
@@ -54,6 +55,8 @@ enum class DBErrors
namespace DBKeys {
extern const std::string ACENTRY;
+extern const std::string ACTIVEEXTERNALSPK;
+extern const std::string ACTIVEINTERNALSPK;
extern const std::string BESTBLOCK;
extern const std::string BESTBLOCK_NOMERKLE;
extern const std::string CRYPTED_KEY;
@@ -74,6 +77,9 @@ extern const std::string PURPOSE;
extern const std::string SETTINGS;
extern const std::string TX;
extern const std::string VERSION;
+extern const std::string WALLETDESCRIPTOR;
+extern const std::string WALLETDESCRIPTORCKEY;
+extern const std::string WALLETDESCRIPTORKEY;
extern const std::string WATCHMETA;
extern const std::string WATCHS;
} // namespace DBKeys
@@ -240,11 +246,19 @@ public:
bool WriteMinVersion(int nVersion);
+ bool WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey);
+ bool WriteCryptedDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const std::vector<unsigned char>& secret);
+ bool WriteDescriptor(const uint256& desc_id, const WalletDescriptor& descriptor);
+ bool WriteDescriptorDerivedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index, uint32_t der_index);
+ bool WriteDescriptorParentCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index);
+
/// Write destination data key,value tuple to database
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value);
/// Erase destination data tuple from wallet database
bool EraseDestData(const std::string &address, const std::string &key);
+ bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal);
+
DBErrors LoadWallet(CWallet* pwallet);
DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx);
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
index fbfdf9dd6b..65643669c2 100644
--- a/src/wallet/wallettool.cpp
+++ b/src/wallet/wallettool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-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.
@@ -99,7 +99,7 @@ static void WalletShowInfo(CWallet* wallet_instance)
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());
tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size());
- tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->mapAddressBook.size());
+ tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
}
bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
index 04c2407a89..8bac0608a9 100644
--- a/src/wallet/walletutil.cpp
+++ b/src/wallet/walletutil.cpp
@@ -100,5 +100,10 @@ WalletLocation::WalletLocation(const std::string& name)
bool WalletLocation::Exists() const
{
- return fs::symlink_status(m_path).type() != fs::file_not_found;
+ fs::path path = m_path;
+ // For the default wallet, check specifically for the wallet.dat file
+ if (m_name.empty()) {
+ path = fs::absolute("wallet.dat", m_path);
+ }
+ return fs::symlink_status(path).type() != fs::file_not_found;
}
diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h
index c91c9aca96..d7e07ed04c 100644
--- a/src/wallet/walletutil.h
+++ b/src/wallet/walletutil.h
@@ -6,6 +6,7 @@
#define BITCOIN_WALLET_WALLETUTIL_H
#include <fs.h>
+#include <script/descriptor.h>
#include <vector>
@@ -55,6 +56,9 @@ enum WalletFlags : uint64_t {
//! bitcoin from opening the wallet, thinking it was newly created, and
//! then improperly reinitializing it.
WALLET_FLAG_BLANK_WALLET = (1ULL << 33),
+
+ //! Indicate that this wallet supports DescriptorScriptPubKeyMan
+ WALLET_FLAG_DESCRIPTORS = (1ULL << 34),
};
//! Get the path of the wallet directory.
@@ -83,4 +87,41 @@ public:
bool Exists() const;
};
+/** Descriptor with some wallet metadata */
+class WalletDescriptor
+{
+public:
+ std::shared_ptr<Descriptor> descriptor;
+ uint64_t creation_time;
+ int32_t range_start; // First item in range; start of range, inclusive, i.e. [range_start, range_end). This never changes.
+ int32_t range_end; // Item after the last; end of range, exclusive, i.e. [range_start, range_end). This will increment with each TopUp()
+ int32_t next_index; // Position of the next item to generate
+ DescriptorCache cache;
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ if (ser_action.ForRead()) {
+ std::string desc;
+ std::string error;
+ READWRITE(desc);
+ FlatSigningProvider keys;
+ descriptor = Parse(desc, keys, error, true);
+ if (!descriptor) {
+ throw std::ios_base::failure("Invalid descriptor: " + error);
+ }
+ } else {
+ READWRITE(descriptor->ToString());
+ }
+ READWRITE(creation_time);
+ READWRITE(next_index);
+ READWRITE(range_start);
+ READWRITE(range_end);
+ }
+
+ WalletDescriptor() {}
+ WalletDescriptor(std::shared_ptr<Descriptor> descriptor, uint64_t creation_time, int32_t range_start, int32_t range_end, int32_t next_index) : descriptor(descriptor), creation_time(creation_time), range_start(range_start), range_end(range_end), next_index(next_index) {}
+};
+
#endif // BITCOIN_WALLET_WALLETUTIL_H
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 0ce14f232e..d55b106e04 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -177,7 +177,7 @@ void CZMQNotificationInterface::TransactionAddedToMempool(const CTransactionRef&
}
}
-void CZMQNotificationInterface::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted)
+void CZMQNotificationInterface::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected)
{
for (const CTransactionRef& ptx : pblock->vtx) {
// Do a normal notify for each transaction added in the block
diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h
index c820865497..60f3b6148a 100644
--- a/src/zmq/zmqnotificationinterface.h
+++ b/src/zmq/zmqnotificationinterface.h
@@ -26,7 +26,7 @@ protected:
// CValidationInterface
void TransactionAddedToMempool(const CTransactionRef& tx) override;
- void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted) override;
+ void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override;
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexDisconnected) override;
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
diff --git a/src/zmq/zmqrpc.cpp b/src/zmq/zmqrpc.cpp
index 5652877f3c..cce6210129 100644
--- a/src/zmq/zmqrpc.cpp
+++ b/src/zmq/zmqrpc.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// 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.
@@ -19,14 +19,15 @@ UniValue getzmqnotifications(const JSONRPCRequest& request)
"\nReturns information about the active ZeroMQ notifications.\n",
{},
RPCResult{
- "[\n"
- " { (json object)\n"
- " \"type\": \"pubhashtx\", (string) Type of notification\n"
- " \"address\": \"...\", (string) Address of the publisher\n"
- " \"hwm\": n (numeric) Outbound message high water mark\n"
- " },\n"
- " ...\n"
- "]\n"
+ RPCResult::Type::ARR, "", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "type", "Type of notification"},
+ {RPCResult::Type::STR, "address", "Address of the publisher"},
+ {RPCResult::Type::NUM, "hwm", "Outbound message high water mark"},
+ }},
+ }
},
RPCExamples{
HelpExampleCli("getzmqnotifications", "")
diff --git a/test/README.md b/test/README.md
index c3e4ae9ad2..e1dab92a06 100644
--- a/test/README.md
+++ b/test/README.md
@@ -145,7 +145,7 @@ levels using the logger included in the test_framework, e.g.
`test_framework.log` and no logs are output to the console.
- when run directly, *all* logs are written to `test_framework.log` and INFO
level and above are output to the console.
-- when run on Travis, no logs are output to the console. However, if a test
+- when run by [our CI (Continuous Integration)](/ci/README.md), no logs are output to the console. However, if a test
fails, the `test_framework.log` and bitcoind `debug.log`s will all be dumped
to the console to help troubleshooting.
diff --git a/test/functional/README.md b/test/functional/README.md
index 77a9ce9acb..004e0afb1d 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -51,10 +51,13 @@ don't have test cases for.
#### General test-writing advice
+- Instead of inline comments or no test documentation at all, log the comments to the test log, e.g.
+ `self.log.info('Create enough transactions to fill a block')`. Logs make the test code easier to read and the test
+ logic easier [to debug](/test/README.md#test-logging).
- Set `self.num_nodes` to the minimum number of nodes necessary for the test.
Having additional unrequired nodes adds to the execution time of the test as
well as memory/CPU/disk requirements (which is important when running tests in
- parallel or on Travis).
+ parallel).
- Avoid stop-starting the nodes multiple times during the test if possible. A
stop-start takes several seconds, so doing it several times blows up the
runtime of the test.
@@ -131,9 +134,6 @@ Utilities for manipulating transaction scripts (originally from python-bitcoinli
#### [key.py](test_framework/key.py)
Test-only secp256k1 elliptic curve implementation
-#### [bignum.py](test_framework/bignum.py)
-Helpers for script.py
-
#### [blocktools.py](test_framework/blocktools.py)
Helper functions for creating blocks and transactions.
diff --git a/test/functional/data/invalid_txs.py b/test/functional/data/invalid_txs.py
index 99c88bbcc0..ae5721bec2 100644
--- a/test/functional/data/invalid_txs.py
+++ b/test/functional/data/invalid_txs.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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.
"""
@@ -21,7 +21,13 @@ Invalid tx cases not covered here can be found by running:
"""
import abc
-from test_framework.messages import CTransaction, CTxIn, CTxOut, COutPoint
+from test_framework.messages import (
+ COutPoint,
+ CTransaction,
+ CTxIn,
+ CTxOut,
+ MAX_MONEY,
+)
from test_framework import script as sc
from test_framework.blocktools import create_tx_with_script, MAX_BLOCK_SIGOPS
from test_framework.script import (
@@ -166,7 +172,7 @@ class SpendTooMuch(BadTxTemplate):
self.spend_tx, 0, script_pub_key=basic_p2sh, amount=(self.spend_avail + 1))
-class SpendNegative(BadTxTemplate):
+class CreateNegative(BadTxTemplate):
reject_reason = 'bad-txns-vout-negative'
expect_disconnect = True
@@ -174,6 +180,25 @@ class SpendNegative(BadTxTemplate):
return create_tx_with_script(self.spend_tx, 0, amount=-1)
+class CreateTooLarge(BadTxTemplate):
+ reject_reason = 'bad-txns-vout-toolarge'
+ expect_disconnect = True
+
+ def get_tx(self):
+ return create_tx_with_script(self.spend_tx, 0, amount=MAX_MONEY + 1)
+
+
+class CreateSumTooLarge(BadTxTemplate):
+ reject_reason = 'bad-txns-txouttotal-toolarge'
+ expect_disconnect = True
+
+ def get_tx(self):
+ tx = create_tx_with_script(self.spend_tx, 0, amount=MAX_MONEY)
+ tx.vout = [tx.vout[0]] * 2
+ tx.calc_sha256()
+ return tx
+
+
class InvalidOPIFConstruction(BadTxTemplate):
reject_reason = "mandatory-script-verify-flag-failed (Invalid OP_IF construction)"
expect_disconnect = True
@@ -237,4 +262,3 @@ DisabledOpcodeTemplates = [getDisabledOpcodeTemplate(opcode) for opcode in [
def iter_all_templates():
"""Iterate through all bad transaction template types."""
return BadTxTemplate.__subclasses__()
-
diff --git a/test/functional/feature_abortnode.py b/test/functional/feature_abortnode.py
index 9b878e8bf8..75267de80b 100755
--- a/test/functional/feature_abortnode.py
+++ b/test/functional/feature_abortnode.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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 bitcoind aborts if can't disconnect a block.
@@ -14,11 +14,12 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import wait_until, get_datadir_path, connect_nodes
import os
-class AbortNodeTest(BitcoinTestFramework):
+class AbortNodeTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
+ self.rpc_timeout = 240
def setup_network(self):
self.setup_nodes()
@@ -44,5 +45,6 @@ class AbortNodeTest(BitcoinTestFramework):
self.log.info("Node crashed - now verifying restart fails")
self.nodes[0].assert_start_raises_init_error()
+
if __name__ == '__main__':
AbortNodeTest().main()
diff --git a/test/functional/feature_asmap.py b/test/functional/feature_asmap.py
new file mode 100755
index 0000000000..2c6553fbe2
--- /dev/null
+++ b/test/functional/feature_asmap.py
@@ -0,0 +1,106 @@
+#!/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 asmap config argument for ASN-based IP bucketing.
+
+Verify node behaviour and debug log when launching bitcoind in these cases:
+
+1. `bitcoind` with no -asmap arg, using /16 prefix for IP bucketing
+
+2. `bitcoind -asmap=<absolute path>`, using the unit test skeleton asmap
+
+3. `bitcoind -asmap=<relative path>`, using the unit test skeleton asmap
+
+4. `bitcoind -asmap/-asmap=` with no file specified, using the default asmap
+
+5. `bitcoind -asmap` with no file specified and a missing default asmap file
+
+6. `bitcoind -asmap` with an empty (unparsable) default asmap file
+
+The tests are order-independent.
+
+"""
+import os
+import shutil
+
+from test_framework.test_framework import BitcoinTestFramework
+
+DEFAULT_ASMAP_FILENAME = 'ip_asn.map' # defined in src/init.cpp
+ASMAP = '../../src/test/data/asmap.raw' # path to unit test skeleton asmap
+VERSION = 'fec61fa21a9f46f3b17bdcd660d7f4cd90b966aad3aec593c99b35f0aca15853'
+
+def expected_messages(filename):
+ return ['Opened asmap file "{}" (59 bytes) from disk'.format(filename),
+ 'Using asmap version {} for IP bucketing'.format(VERSION)]
+
+class AsmapTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+
+ def test_without_asmap_arg(self):
+ self.log.info('Test bitcoind with no -asmap arg passed')
+ self.stop_node(0)
+ with self.node.assert_debug_log(['Using /16 prefix for IP bucketing']):
+ self.start_node(0)
+
+ def test_asmap_with_absolute_path(self):
+ self.log.info('Test bitcoind -asmap=<absolute path>')
+ self.stop_node(0)
+ filename = os.path.join(self.datadir, 'my-map-file.map')
+ shutil.copyfile(self.asmap_raw, filename)
+ with self.node.assert_debug_log(expected_messages(filename)):
+ self.start_node(0, ['-asmap={}'.format(filename)])
+ os.remove(filename)
+
+ def test_asmap_with_relative_path(self):
+ self.log.info('Test bitcoind -asmap=<relative path>')
+ self.stop_node(0)
+ name = 'ASN_map'
+ filename = os.path.join(self.datadir, name)
+ shutil.copyfile(self.asmap_raw, filename)
+ with self.node.assert_debug_log(expected_messages(filename)):
+ self.start_node(0, ['-asmap={}'.format(name)])
+ os.remove(filename)
+
+ def test_default_asmap(self):
+ shutil.copyfile(self.asmap_raw, self.default_asmap)
+ for arg in ['-asmap', '-asmap=']:
+ self.log.info('Test bitcoind {} (using default map file)'.format(arg))
+ self.stop_node(0)
+ with self.node.assert_debug_log(expected_messages(self.default_asmap)):
+ self.start_node(0, [arg])
+ os.remove(self.default_asmap)
+
+ def test_default_asmap_with_missing_file(self):
+ self.log.info('Test bitcoind -asmap with missing default map file')
+ self.stop_node(0)
+ msg = "Error: Could not find asmap file \"{}\"".format(self.default_asmap)
+ self.node.assert_start_raises_init_error(extra_args=['-asmap'], expected_msg=msg)
+
+ def test_empty_asmap(self):
+ self.log.info('Test bitcoind -asmap with empty map file')
+ self.stop_node(0)
+ with open(self.default_asmap, "w", encoding="utf-8") as f:
+ f.write("")
+ msg = "Error: Could not parse asmap file \"{}\"".format(self.default_asmap)
+ self.node.assert_start_raises_init_error(extra_args=['-asmap'], expected_msg=msg)
+ os.remove(self.default_asmap)
+
+ def run_test(self):
+ self.node = self.nodes[0]
+ self.datadir = os.path.join(self.node.datadir, self.chain)
+ self.default_asmap = os.path.join(self.datadir, DEFAULT_ASMAP_FILENAME)
+ self.asmap_raw = os.path.join(os.path.dirname(os.path.realpath(__file__)), ASMAP)
+
+ self.test_without_asmap_arg()
+ self.test_asmap_with_absolute_path()
+ self.test_asmap_with_relative_path()
+ self.test_default_asmap()
+ self.test_default_asmap_with_missing_file()
+ self.test_empty_asmap()
+
+
+if __name__ == '__main__':
+ AsmapTest().main()
diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py
index 1b434c4485..79777f5582 100755
--- a/test/functional/feature_assumevalid.py
+++ b/test/functional/feature_assumevalid.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 logic for skipping signature validation on old blocks.
@@ -47,16 +47,19 @@ from test_framework.script import (CScript, OP_TRUE)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
+
class BaseNode(P2PInterface):
def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers()
headers_message.headers = [CBlockHeader(b) for b in new_blocks]
self.send_message(headers_message)
+
class AssumeValidTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
+ self.rpc_timeout = 120
def setup_network(self):
self.add_nodes(3)
@@ -187,5 +190,6 @@ class AssumeValidTest(BitcoinTestFramework):
self.send_blocks_until_disconnected(p2p2)
self.assert_blockchain_height(self.nodes[2], 101)
+
if __name__ == '__main__':
AssumeValidTest().main()
diff --git a/test/functional/feature_backwards_compatibility.py b/test/functional/feature_backwards_compatibility.py
new file mode 100755
index 0000000000..9cff79a42c
--- /dev/null
+++ b/test/functional/feature_backwards_compatibility.py
@@ -0,0 +1,354 @@
+#!/usr/bin/env python3
+# 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.
+"""Backwards compatibility functional test
+
+Test various backwards compatibility scenarios. Download the previous node binaries:
+
+contrib/devtools/previous_release.sh -b v0.19.0.1 v0.18.1 v0.17.1
+
+Due to RPC changes introduced in various versions the below tests
+won't work for older versions without some patches or workarounds.
+
+Use only the latest patch version of each release, unless a test specifically
+needs an older patch version.
+"""
+
+import os
+import shutil
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.descriptors import descsum_create
+
+from test_framework.util import (
+ assert_equal,
+ sync_blocks,
+ sync_mempools,
+)
+
+
+class BackwardsCompatibilityTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 5
+ # Add new version after each release:
+ self.extra_args = [
+ ["-addresstype=bech32"], # Pre-release: use to mine blocks
+ ["-nowallet", "-walletrbf=1", "-addresstype=bech32"], # Pre-release: use to receive coins, swap wallets, etc
+ ["-nowallet", "-walletrbf=1", "-addresstype=bech32"], # v0.19.0.1
+ ["-nowallet", "-walletrbf=1", "-addresstype=bech32"], # v0.18.1
+ ["-nowallet", "-walletrbf=1", "-addresstype=bech32"] # v0.17.1
+ ]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+ self.skip_if_no_previous_releases()
+
+ def setup_nodes(self):
+ self.add_nodes(self.num_nodes, extra_args=self.extra_args, versions=[
+ None,
+ None,
+ 190001,
+ 180100,
+ 170100,
+ ])
+
+ self.start_nodes()
+
+ def run_test(self):
+ self.nodes[0].generatetoaddress(101, self.nodes[0].getnewaddress())
+
+ sync_blocks(self.nodes)
+
+ # Sanity check the test framework:
+ res = self.nodes[self.num_nodes - 1].getblockchaininfo()
+ assert_equal(res['blocks'], 101)
+
+ node_master = self.nodes[self.num_nodes - 4]
+ node_v19 = self.nodes[self.num_nodes - 3]
+ node_v18 = self.nodes[self.num_nodes - 2]
+ node_v17 = self.nodes[self.num_nodes - 1]
+
+ self.log.info("Test wallet backwards compatibility...")
+ # Create a number of wallets and open them in older versions:
+
+ # 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")
+ wallet = node_master.get_wallet_rpc("w1")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] > 0
+ # Create a confirmed transaction, receiving coins
+ address = wallet.getnewaddress()
+ self.nodes[0].sendtoaddress(address, 10)
+ sync_mempools(self.nodes)
+ self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
+ # Create a conflicting transaction using RBF
+ return_address = self.nodes[0].getnewaddress()
+ tx1_id = self.nodes[1].sendtoaddress(return_address, 1)
+ tx2_id = self.nodes[1].bumpfee(tx1_id)["txid"]
+ # Confirm the transaction
+ sync_mempools(self.nodes)
+ self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
+ # Create another conflicting transaction using RBF
+ tx3_id = self.nodes[1].sendtoaddress(return_address, 1)
+ tx4_id = self.nodes[1].bumpfee(tx3_id)["txid"]
+ # Abandon transaction, but don't confirm
+ self.nodes[1].abandontransaction(tx3_id)
+
+ # w1_v19: regular wallet, created with v0.19
+ node_v19.rpc.createwallet(wallet_name="w1_v19")
+ wallet = node_v19.get_wallet_rpc("w1_v19")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] > 0
+ # Use addmultisigaddress (see #18075)
+ address_18075 = wallet.rpc.addmultisigaddress(1, ["0296b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52", "037211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073"], "", "legacy")["address"]
+ assert wallet.getaddressinfo(address_18075)["solvable"]
+
+ # w1_v18: regular wallet, created with v0.18
+ node_v18.rpc.createwallet(wallet_name="w1_v18")
+ wallet = node_v18.get_wallet_rpc("w1_v18")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] > 0
+
+ # 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)
+ wallet = node_master.get_wallet_rpc("w2")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled'] == False
+ assert info['keypoolsize'] == 0
+
+ # w2_v19: wallet with private keys disabled, created with v0.19
+ node_v19.rpc.createwallet(wallet_name="w2_v19", disable_private_keys=True)
+ wallet = node_v19.get_wallet_rpc("w2_v19")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled'] == False
+ assert info['keypoolsize'] == 0
+
+ # w2_v18: wallet with private keys disabled, created with v0.18
+ node_v18.rpc.createwallet(wallet_name="w2_v18", disable_private_keys=True)
+ wallet = node_v18.get_wallet_rpc("w2_v18")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled'] == False
+ assert info['keypoolsize'] == 0
+
+ # 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)
+ wallet = node_master.get_wallet_rpc("w3")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] == 0
+
+ # w3_v19: blank wallet, created with v0.19
+ node_v19.rpc.createwallet(wallet_name="w3_v19", blank=True)
+ wallet = node_v19.get_wallet_rpc("w3_v19")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] == 0
+
+ # w3_v18: blank wallet, created with v0.18
+ node_v18.rpc.createwallet(wallet_name="w3_v18", blank=True)
+ wallet = node_v18.get_wallet_rpc("w3_v18")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] == 0
+
+ # Copy the wallets to older nodes:
+ node_master_wallets_dir = os.path.join(node_master.datadir, "regtest/wallets")
+ node_v19_wallets_dir = os.path.join(node_v19.datadir, "regtest/wallets")
+ node_v18_wallets_dir = os.path.join(node_v18.datadir, "regtest/wallets")
+ node_v17_wallets_dir = os.path.join(node_v17.datadir, "regtest/wallets")
+ node_master.unloadwallet("w1")
+ node_master.unloadwallet("w2")
+ node_v19.unloadwallet("w1_v19")
+ node_v19.unloadwallet("w2_v19")
+ node_v18.unloadwallet("w1_v18")
+ node_v18.unloadwallet("w2_v18")
+
+ # Copy wallets to v0.17
+ for wallet in os.listdir(node_master_wallets_dir):
+ shutil.copytree(
+ os.path.join(node_master_wallets_dir, wallet),
+ os.path.join(node_v17_wallets_dir, wallet)
+ )
+ for wallet in os.listdir(node_v18_wallets_dir):
+ shutil.copytree(
+ os.path.join(node_v18_wallets_dir, wallet),
+ os.path.join(node_v17_wallets_dir, wallet)
+ )
+
+ # Copy wallets to v0.18
+ for wallet in os.listdir(node_master_wallets_dir):
+ shutil.copytree(
+ os.path.join(node_master_wallets_dir, wallet),
+ os.path.join(node_v18_wallets_dir, wallet)
+ )
+
+ # Copy wallets to v0.19
+ for wallet in os.listdir(node_master_wallets_dir):
+ shutil.copytree(
+ os.path.join(node_master_wallets_dir, wallet),
+ 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
+
+ # Open the wallets in v0.17
+ node_v17.loadwallet("w1_v18")
+ wallet = node_v17.get_wallet_rpc("w1_v18")
+ 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_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')
+
+ # Instead, we stop node and try to launch it with the wallet:
+ self.stop_node(self.num_nodes - 1)
+ 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")
+ self.start_node(self.num_nodes - 1)
+
+ self.log.info("Test wallet upgrade path...")
+ # u1: regular wallet, created with v0.17
+ node_v17.rpc.createwallet(wallet_name="u1_v17")
+ wallet = node_v17.get_wallet_rpc("u1_v17")
+ address = wallet.getnewaddress("bech32")
+ v17_info = wallet.getaddressinfo(address)
+ hdkeypath = v17_info["hdkeypath"]
+ pubkey = v17_info["pubkey"]
+
+ # Copy the 0.17 wallet to the last Bitcoin Core version and open it:
+ node_v17.unloadwallet("u1_v17")
+ shutil.copytree(
+ os.path.join(node_v17_wallets_dir, "u1_v17"),
+ os.path.join(node_master_wallets_dir, "u1_v17")
+ )
+ node_master.loadwallet("u1_v17")
+ wallet = node_master.get_wallet_rpc("u1_v17")
+ info = wallet.getaddressinfo(address)
+ descriptor = "wpkh([" + info["hdmasterfingerprint"] + hdkeypath[1:] + "]" + pubkey + ")"
+ assert_equal(info["desc"], descsum_create(descriptor))
+
+ # Now copy that same wallet back to 0.17 to make sure no automatic upgrade breaks it
+ node_master.unloadwallet("u1_v17")
+ shutil.rmtree(os.path.join(node_v17_wallets_dir, "u1_v17"))
+ shutil.copytree(
+ os.path.join(node_master_wallets_dir, "u1_v17"),
+ os.path.join(node_v17_wallets_dir, "u1_v17")
+ )
+ node_v17.loadwallet("u1_v17")
+ wallet = node_v17.get_wallet_rpc("u1_v17")
+ info = wallet.getaddressinfo(address)
+ assert_equal(info, v17_info)
+
+ # Copy the 0.19 wallet to the last Bitcoin Core version and open it:
+ shutil.copytree(
+ os.path.join(node_v19_wallets_dir, "w1_v19"),
+ os.path.join(node_master_wallets_dir, "w1_v19")
+ )
+ node_master.loadwallet("w1_v19")
+ wallet = node_master.get_wallet_rpc("w1_v19")
+ assert wallet.getaddressinfo(address_18075)["solvable"]
+
+ # Now copy that same wallet back to 0.19 to make sure no automatic upgrade breaks it
+ node_master.unloadwallet("w1_v19")
+ shutil.rmtree(os.path.join(node_v19_wallets_dir, "w1_v19"))
+ shutil.copytree(
+ os.path.join(node_master_wallets_dir, "w1_v19"),
+ os.path.join(node_v19_wallets_dir, "w1_v19")
+ )
+ node_v19.loadwallet("w1_v19")
+ wallet = node_v19.get_wallet_rpc("w1_v19")
+ assert wallet.getaddressinfo(address_18075)["solvable"]
+
+if __name__ == '__main__':
+ BackwardsCompatibilityTest().main()
diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py
index fe45ed34b5..549e8b2029 100755
--- a/test/functional/feature_bip68_sequence.py
+++ b/test/functional/feature_bip68_sequence.py
@@ -324,7 +324,7 @@ class BIP68Test(BitcoinTestFramework):
block.solve()
tip = block.sha256
height += 1
- self.nodes[0].submitblock(ToHex(block))
+ assert_equal(None if i == 1 else 'inconclusive', self.nodes[0].submitblock(ToHex(block)))
cur_time += 1
mempool = self.nodes[0].getrawmempool()
@@ -381,7 +381,7 @@ class BIP68Test(BitcoinTestFramework):
add_witness_commitment(block)
block.solve()
- self.nodes[0].submitblock(block.serialize().hex())
+ assert_equal(None, self.nodes[0].submitblock(block.serialize().hex()))
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
def activateCSV(self):
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index 95905f477b..6619d83dc4 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 block processing."""
@@ -630,17 +630,19 @@ class FullBlockTest(BitcoinTestFramework):
self.log.info("Reject a block with invalid work")
self.move_tip(44)
- b47 = self.next_block(47, solve=False)
+ b47 = self.next_block(47)
target = uint256_from_compact(b47.nBits)
- while b47.sha256 < target:
+ while b47.sha256 <= target:
+ # Rehash nonces until an invalid too-high-hash block is found.
b47.nNonce += 1
b47.rehash()
self.send_blocks([b47], False, force_send=True, reject_reason='high-hash', reconnect=True)
self.log.info("Reject a block with a timestamp >2 hours in the future")
self.move_tip(44)
- b48 = self.next_block(48, solve=False)
+ b48 = self.next_block(48)
b48.nTime = int(time.time()) + 60 * 60 * 3
+ # Header timestamp has changed. Re-solve the block.
b48.solve()
self.send_blocks([b48], False, force_send=True, reject_reason='time-too-new')
@@ -1261,7 +1263,7 @@ class FullBlockTest(BitcoinTestFramework):
self.save_spendable_output()
spend = self.get_spendable_output()
- self.send_blocks(blocks, True, timeout=960)
+ self.send_blocks(blocks, True, timeout=2440)
chain1_tip = i
# now create alt chain of same length
@@ -1273,14 +1275,14 @@ class FullBlockTest(BitcoinTestFramework):
# extend alt chain to trigger re-org
block = self.next_block("alt" + str(chain1_tip + 1), version=4)
- self.send_blocks([block], True, timeout=960)
+ 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)
self.send_blocks([block], False, force_send=True)
block = self.next_block(chain1_tip + 2, version=4)
- self.send_blocks([block], True, timeout=960)
+ self.send_blocks([block], True, timeout=2440)
self.log.info("Reject a block with an invalid block header version")
b_v1 = self.next_block('b_v1', version=1)
@@ -1321,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]), solve=True, *, version=1):
+ def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), *, version=1):
if self.tip is None:
base_block_hash = self.genesis_hash
block_time = int(time.time()) + 1
@@ -1343,8 +1345,8 @@ class FullBlockTest(BitcoinTestFramework):
self.sign_tx(tx, spend)
self.add_transactions_to_block(block, [tx])
block.hashMerkleRoot = block.calc_merkle_root()
- if solve:
- block.solve()
+ # Block is created. Find a valid nonce.
+ block.solve()
self.tip = block
self.block_heights[block.sha256] = height
assert number not in self.blocks
diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py
index 2c6f2e733b..fd0330924d 100755
--- a/test/functional/feature_cltv.py
+++ b/test/functional/feature_cltv.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 BIP65 (CHECKLOCKTIMEVERIFY).
@@ -55,12 +55,12 @@ class BIP65Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.extra_args = [[
- '-whitelist=127.0.0.1',
+ '-whitelist=noban@127.0.0.1',
'-par=1', # Use only one script thread to get the exact reject reason for testing
'-acceptnonstdtxn=1', # cltv_invalidate is nonstandard
]]
self.setup_clean_chain = True
- self.rpc_timeout = 120
+ self.rpc_timeout = 480
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index 719b124a65..1a7c656274 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -23,7 +23,7 @@ class ConfArgsTest(BitcoinTestFramework):
conf.write('includeconf={}\n'.format(inc_conf_file_path))
self.nodes[0].assert_start_raises_init_error(
- expected_msg='Error: Error parsing command line arguments: Invalid parameter -dash_cli',
+ expected_msg='Error: Error parsing command line arguments: Invalid parameter -dash_cli=1',
extra_args=['-dash_cli=1'],
)
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
@@ -93,8 +93,8 @@ class ConfArgsTest(BitcoinTestFramework):
'Command-line arg: rpcpassword=****',
'Command-line arg: rpcuser=****',
'Command-line arg: torpassword=****',
- 'Config file arg: regtest="1"',
- 'Config file arg: [regtest] server="1"',
+ 'Config file arg: %s="1"' % self.chain,
+ 'Config file arg: [%s] server="1"' % self.chain,
],
unexpected_msgs=[
'alice:f7efda5c189b999524f151318c0c86$d5b51b3beffbc0',
diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py
index c2b4de54f2..c6852ef017 100755
--- a/test/functional/feature_csv_activation.py
+++ b/test/functional/feature_csv_activation.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 CSV soft fork activation.
@@ -35,6 +35,7 @@ bip112txs_vary_nSequence_9 - 16 txs with nSequence relative_locktimes of 9 evalu
bip112txs_vary_OP_CSV - 16 txs with nSequence = 10 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
bip112txs_vary_OP_CSV_9 - 16 txs with nSequence = 9 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
bip112tx_special - test negative argument to OP_CSV
+bip112tx_emptystack - test empty stack (= no argument) OP_CSV
"""
from decimal import Decimal
from itertools import product
@@ -56,6 +57,8 @@ from test_framework.util import (
softfork_active,
)
+TESTING_TX_COUNT = 83 # Number of testing transactions: 1 BIP113 tx, 16 BIP68 txs, 66 BIP112 txs (see comments above)
+COINBASE_BLOCK_COUNT = TESTING_TX_COUNT # Number of coinbase blocks we need to generate as inputs for our txs
BASE_RELATIVE_LOCKTIME = 10
CSV_ACTIVATION_HEIGHT = 432
SEQ_DISABLE_FLAG = 1 << 31
@@ -95,6 +98,13 @@ def create_bip112special(node, input, txversion, address):
signtx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
return signtx
+def create_bip112emptystack(node, input, txversion, address):
+ tx = create_transaction(node, input, address, amount=Decimal("49.98"))
+ tx.nVersion = txversion
+ signtx = sign_transaction(node, tx)
+ signtx.vin[0].scriptSig = CScript([OP_CHECKSEQUENCEVERIFY] + list(CScript(signtx.vin[0].scriptSig)))
+ return signtx
+
def send_generic_input_tx(node, coinbases, address):
return node.sendrawtransaction(ToHex(sign_transaction(node, create_transaction(node, node.getblock(coinbases.pop())['tx'][0], address, amount=Decimal("49.99")))))
@@ -138,7 +148,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
- self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-addresstype=legacy']]
+ 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
+ ]]
self.supports_cli = False
def skip_test_if_missing_module(self):
@@ -163,11 +178,11 @@ class BIP68_112_113Test(BitcoinTestFramework):
block.solve()
return block
- def send_blocks(self, blocks, success=True):
+ def send_blocks(self, blocks, success=True, reject_reason=None):
"""Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
Call with success = False if the tip shouldn't advance to the most recent block."""
- self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success)
+ self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason)
def run_test(self):
self.nodes[0].add_p2p_connection(P2PDataStore())
@@ -175,15 +190,16 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.log.info("Generate blocks in the past for coinbase outputs.")
long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future
self.nodes[0].setmocktime(long_past_time - 100) # enough so that the generated blocks will still all be before long_past_time
- self.coinbase_blocks = self.nodes[0].generate(1 + 16 + 2 * 32 + 1) # 82 blocks generated for inputs
+ self.coinbase_blocks = self.nodes[0].generate(COINBASE_BLOCK_COUNT) # blocks generated for inputs
self.nodes[0].setmocktime(0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time
- self.tipheight = 82 # height of the next block to build
+ self.tipheight = COINBASE_BLOCK_COUNT # height of the next block to build
self.last_block_time = long_past_time
self.tip = int(self.nodes[0].getbestblockhash(), 16)
self.nodeaddress = self.nodes[0].getnewaddress()
# Activation height is hardcoded
- test_blocks = self.generate_blocks(345)
+ # We advance to block height five below BIP112 activation for the following tests
+ test_blocks = self.generate_blocks(CSV_ACTIVATION_HEIGHT-5 - COINBASE_BLOCK_COUNT)
self.send_blocks(test_blocks)
assert not softfork_active(self.nodes[0], 'csv')
@@ -214,6 +230,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
# 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
bip112specialinput = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
+ # 1 special input with (empty stack) OP_CSV (actually will be prepended to spending scriptSig)
+ bip112emptystackinput = send_generic_input_tx(self.nodes[0],self.coinbase_blocks, self.nodeaddress)
# 1 normal input
bip113input = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
@@ -224,7 +242,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.tip = int(inputblockhash, 16)
self.tipheight += 1
self.last_block_time += 600
- assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), 82 + 1)
+ assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), TESTING_TX_COUNT + 1)
# 2 more version 4 blocks
test_blocks = self.generate_blocks(2)
@@ -263,6 +281,9 @@ class BIP68_112_113Test(BitcoinTestFramework):
# -1 OP_CSV OP_DROP input
bip112tx_special_v1 = create_bip112special(self.nodes[0], bip112specialinput, 1, self.nodeaddress)
bip112tx_special_v2 = create_bip112special(self.nodes[0], bip112specialinput, 2, self.nodeaddress)
+ # (empty stack) OP_CSV input
+ bip112tx_emptystack_v1 = create_bip112emptystack(self.nodes[0], bip112emptystackinput, 1, self.nodeaddress)
+ bip112tx_emptystack_v2 = create_bip112emptystack(self.nodes[0], bip112emptystackinput, 2, self.nodeaddress)
self.log.info("TESTING")
@@ -270,11 +291,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.log.info("Test version 1 txs")
success_txs = []
- # add BIP113 tx and -1 CSV tx
+ # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
success_txs.append(bip113signed1)
success_txs.append(bip112tx_special_v1)
+ success_txs.append(bip112tx_emptystack_v1)
# add BIP 68 txs
success_txs.extend(all_rlt_txs(bip68txs_v1))
# add BIP 112 with seq=10 txs
@@ -289,11 +311,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.log.info("Test version 2 txs")
success_txs = []
- # add BIP113 tx and -1 CSV tx
+ # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
success_txs.append(bip113signed2)
success_txs.append(bip112tx_special_v2)
+ success_txs.append(bip112tx_emptystack_v2)
# add BIP 68 txs
success_txs.extend(all_rlt_txs(bip68txs_v2))
# add BIP 112 with seq=10 txs
@@ -320,7 +343,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
for bip113tx in [bip113signed1, bip113signed2]:
- self.send_blocks([self.create_test_block([bip113tx])], success=False)
+ self.send_blocks([self.create_test_block([bip113tx])], success=False, reject_reason='bad-txns-nonfinal')
# BIP 113 tests should now pass if the locktime is < MTP
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
@@ -352,11 +375,11 @@ class BIP68_112_113Test(BitcoinTestFramework):
# All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512
bip68timetxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and tx['stf']]
for tx in bip68timetxs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
bip68heighttxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and not tx['stf']]
for tx in bip68heighttxs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
# Advance one block to 438
test_blocks = self.generate_blocks(1)
@@ -367,7 +390,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.send_blocks([self.create_test_block(bip68success_txs)])
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
for tx in bip68heighttxs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
# Advance one block to 439
test_blocks = self.generate_blocks(1)
@@ -381,8 +404,11 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.log.info("BIP 112 tests")
self.log.info("Test version 1 txs")
- # -1 OP_CSV tx should fail
- self.send_blocks([self.create_test_block([bip112tx_special_v1])], success=False)
+ # -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
+ self.send_blocks([self.create_test_block([bip112tx_special_v1])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Negative locktime)')
+ self.send_blocks([self.create_test_block([bip112tx_emptystack_v1])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Operation not valid with the current stack size)')
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass
success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if tx['sdf']]
@@ -393,15 +419,19 @@ class BIP68_112_113Test(BitcoinTestFramework):
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV, version 1 txs should now fail
fail_txs = all_rlt_txs(bip112txs_vary_nSequence_v1)
fail_txs += all_rlt_txs(bip112txs_vary_nSequence_9_v1)
- fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx['sdf']]
+ fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if not tx['sdf']]
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx['sdf']]
for tx in fail_txs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Locktime requirement not satisfied)')
self.log.info("Test version 2 txs")
- # -1 OP_CSV tx should fail
- self.send_blocks([self.create_test_block([bip112tx_special_v2])], success=False)
+ # -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
+ self.send_blocks([self.create_test_block([bip112tx_special_v2])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Negative locktime)')
+ self.send_blocks([self.create_test_block([bip112tx_emptystack_v2])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Operation not valid with the current stack size)')
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met)
success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if tx['sdf']]
@@ -416,18 +446,21 @@ class BIP68_112_113Test(BitcoinTestFramework):
fail_txs = all_rlt_txs(bip112txs_vary_nSequence_9_v2)
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v2 if not tx['sdf']]
for tx in fail_txs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Locktime requirement not satisfied)')
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail
fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if tx['sdf']]
for tx in fail_txs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Locktime requirement not satisfied)')
# If sequencelock types mismatch, tx should fail
fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and tx['stf']]
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and tx['stf']]
for tx in fail_txs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Locktime requirement not satisfied)')
# Remaining txs should pass, just test masking works properly
success_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and not tx['stf']]
@@ -445,7 +478,5 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.send_blocks([self.create_test_block(time_txs)])
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
- # TODO: Test empty stack fails
-
if __name__ == '__main__':
BIP68_112_113Test().main()
diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py
index 27da49cf24..05fdacd451 100755
--- a/test/functional/feature_dersig.py
+++ b/test/functional/feature_dersig.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 BIP66 (DER SIG).
@@ -36,13 +36,15 @@ def unDERify(tx):
tx.vin[0].scriptSig = CScript(newscript)
-
class BIP66Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
- self.extra_args = [['-whitelist=127.0.0.1', '-par=1']] # Use only one script thread to get the exact log msg for testing
+ self.extra_args = [[
+ '-whitelist=noban@127.0.0.1',
+ '-par=1', # Use only one script thread to get the exact log msg for testing
+ ]]
self.setup_clean_chain = True
- self.rpc_timeout = 120
+ self.rpc_timeout = 240
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py
index d2d41b1206..3cf0fb8f7b 100755
--- a/test/functional/feature_fee_estimation.py
+++ b/test/functional/feature_fee_estimation.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 fee estimation code."""
@@ -99,8 +99,20 @@ def split_inputs(from_node, txins, txouts, initial_split=False):
txouts.append({"txid": txid, "vout": 0, "amount": half_change})
txouts.append({"txid": txid, "vout": 1, "amount": rem_change})
+def check_raw_estimates(node, fees_seen):
+ """Call estimaterawfee and verify that the estimates meet certain invariants."""
-def check_estimates(node, fees_seen):
+ delta = 1.0e-6 # account for rounding error
+ for i in range(1, 26):
+ for _, e in node.estimaterawfee(i).items():
+ feerate = float(e["feerate"])
+ assert_greater_than(feerate, 0)
+
+ if feerate + delta < min(fees_seen) or feerate - delta > max(fees_seen):
+ raise AssertionError("Estimated fee (%f) out of range (%f,%f)"
+ % (feerate, min(fees_seen), max(fees_seen)))
+
+def check_smart_estimates(node, fees_seen):
"""Call estimatesmartfee and verify that the estimates meet certain invariants."""
delta = 1.0e-6 # account for rounding error
@@ -123,16 +135,19 @@ def check_estimates(node, fees_seen):
else:
assert_greater_than_or_equal(i + 1, e["blocks"])
+def check_estimates(node, fees_seen):
+ check_raw_estimates(node, fees_seen)
+ check_smart_estimates(node, fees_seen)
class EstimateFeeTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 3
# mine non-standard txs (e.g. txs with "dust" outputs)
- # Force fSendTrickle to true (via whitelist)
+ # Force fSendTrickle to true (via whitelist.noban)
self.extra_args = [
- ["-acceptnonstdtxn", "-whitelist=127.0.0.1"],
- ["-acceptnonstdtxn", "-whitelist=127.0.0.1", "-blockmaxweight=68000"],
- ["-acceptnonstdtxn", "-whitelist=127.0.0.1", "-blockmaxweight=32000"],
+ ["-acceptnonstdtxn", "-whitelist=noban@127.0.0.1"],
+ ["-acceptnonstdtxn", "-whitelist=noban@127.0.0.1", "-blockmaxweight=68000"],
+ ["-acceptnonstdtxn", "-whitelist=noban@127.0.0.1", "-blockmaxweight=32000"],
]
def skip_test_if_missing_module(self):
diff --git a/test/functional/feature_filelock.py b/test/functional/feature_filelock.py
index be1c044aa5..b56ffe179f 100755
--- a/test/functional/feature_filelock.py
+++ b/test/functional/feature_filelock.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
"""Check that it's not possible to start a second bitcoind instance using the same datadir or wallet."""
diff --git a/test/functional/feature_help.py b/test/functional/feature_help.py
index e3e2456183..9f18413255 100755
--- a/test/functional/feature_help.py
+++ b/test/functional/feature_help.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018 The Bitcoin Core developers
+# Copyright (c) 2018-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.
"""Verify that starting bitcoin with -h works as expected."""
diff --git a/test/functional/feature_loadblock.py b/test/functional/feature_loadblock.py
index 7f1e8f5bae..1138b0f0ea 100755
--- a/test/functional/feature_loadblock.py
+++ b/test/functional/feature_loadblock.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2019 The Bitcoin Core developers
+# Copyright (c) 2017-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 loadblock option
diff --git a/test/functional/feature_logging.py b/test/functional/feature_logging.py
index 1bae29b302..e4bf2d849d 100755
--- a/test/functional/feature_logging.py
+++ b/test/functional/feature_logging.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2019 The Bitcoin Core developers
+# Copyright (c) 2017-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 debug logging."""
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index 8d200915bd..d4a8f8a715 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 behavior of -maxuploadtarget.
@@ -94,8 +94,7 @@ class MaxUploadTest(BitcoinTestFramework):
# 576MB will be reserved for relaying new blocks, so expect this to
# succeed for ~235 tries.
for i in range(success_count):
- p2p_conns[0].send_message(getdata_request)
- p2p_conns[0].sync_with_ping()
+ p2p_conns[0].send_and_ping(getdata_request)
assert_equal(p2p_conns[0].block_receive_map[big_old_block], i+1)
assert_equal(len(self.nodes[0].getpeerinfo()), 3)
@@ -112,8 +111,7 @@ class MaxUploadTest(BitcoinTestFramework):
# We'll try 800 times
getdata_request.inv = [CInv(2, big_new_block)]
for i in range(800):
- p2p_conns[1].send_message(getdata_request)
- p2p_conns[1].sync_with_ping()
+ p2p_conns[1].send_and_ping(getdata_request)
assert_equal(p2p_conns[1].block_receive_map[big_new_block], i+1)
self.log.info("Peer 1 able to repeatedly download new block")
@@ -132,18 +130,16 @@ class MaxUploadTest(BitcoinTestFramework):
# and p2p_conns[2] should be able to retrieve the old block.
self.nodes[0].setmocktime(int(time.time()))
p2p_conns[2].sync_with_ping()
- p2p_conns[2].send_message(getdata_request)
- p2p_conns[2].sync_with_ping()
+ p2p_conns[2].send_and_ping(getdata_request)
assert_equal(p2p_conns[2].block_receive_map[big_old_block], 1)
self.log.info("Peer 2 able to download old block")
self.nodes[0].disconnect_p2ps()
- #stop and start node 0 with 1MB maxuploadtarget, whitelist 127.0.0.1
- self.log.info("Restarting nodes with -whitelist=127.0.0.1")
+ self.log.info("Restarting node 0 with noban permission and 1MB maxuploadtarget")
self.stop_node(0)
- self.start_node(0, ["-whitelist=127.0.0.1", "-maxuploadtarget=1"])
+ self.start_node(0, ["-whitelist=noban@127.0.0.1", "-maxuploadtarget=1"])
# Reconnect to self.nodes[0]
self.nodes[0].add_p2p_connection(TestP2PConn())
@@ -151,8 +147,7 @@ class MaxUploadTest(BitcoinTestFramework):
#retrieve 20 blocks which should be enough to break the 1MB limit
getdata_request.inv = [CInv(2, big_new_block)]
for i in range(20):
- self.nodes[0].p2p.send_message(getdata_request)
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.send_and_ping(getdata_request)
assert_equal(self.nodes[0].p2p.block_receive_map[big_new_block], i+1)
getdata_request.inv = [CInv(2, big_old_block)]
diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py
index da00b773ad..b110a559c0 100755
--- a/test/functional/feature_notifications.py
+++ b/test/functional/feature_notifications.py
@@ -13,6 +13,16 @@ from test_framework.util import (
connect_nodes,
)
+# Linux allow all characters other than \x00
+# Windows disallow control characters (0-31) and /\?%:|"<>
+FILE_CHAR_START = 32 if os.name == 'nt' else 1
+FILE_CHAR_END = 128
+FILE_CHAR_BLACKLIST = '/\\?%*:|"<>' if os.name == 'nt' else '/'
+
+
+def notify_outputname(walletname, txid):
+ return txid if os.name == 'nt' else '{}_{}'.format(walletname, txid)
+
class NotificationsTest(BitcoinTestFramework):
def set_test_params(self):
@@ -20,6 +30,7 @@ class NotificationsTest(BitcoinTestFramework):
self.setup_clean_chain = True
def setup_network(self):
+ self.wallet = ''.join(chr(i) for i in range(FILE_CHAR_START, FILE_CHAR_END) if chr(i) not in FILE_CHAR_BLACKLIST)
self.alertnotify_dir = os.path.join(self.options.tmpdir, "alertnotify")
self.blocknotify_dir = os.path.join(self.options.tmpdir, "blocknotify")
self.walletnotify_dir = os.path.join(self.options.tmpdir, "walletnotify")
@@ -33,7 +44,8 @@ class NotificationsTest(BitcoinTestFramework):
"-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))],
["-blockversion=211",
"-rescan",
- "-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, '%s'))]]
+ "-wallet={}".format(self.wallet),
+ "-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, notify_outputname('%w', '%s')))]]
super().setup_network()
def run_test(self):
@@ -53,7 +65,7 @@ class NotificationsTest(BitcoinTestFramework):
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
# directory content should equal the generated transaction hashes
- txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
+ txids_rpc = list(map(lambda t: notify_outputname(self.wallet, t['txid']), self.nodes[1].listtransactions("*", block_count)))
assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
self.stop_node(1)
for tx_file in os.listdir(self.walletnotify_dir):
@@ -67,7 +79,7 @@ class NotificationsTest(BitcoinTestFramework):
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
# directory content should equal the generated transaction hashes
- txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
+ txids_rpc = list(map(lambda t: notify_outputname(self.wallet, t['txid']), self.nodes[1].listtransactions("*", block_count)))
assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
# TODO: add test for `-alertnotify` large fork notifications
diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py
index aaf56a42d0..ff55cb76d9 100755
--- a/test/functional/feature_nulldummy.py
+++ b/test/functional/feature_nulldummy.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2019 The Bitcoin Core developers
+# Copyright (c) 2016-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 NULLDUMMY softfork.
@@ -41,7 +41,10 @@ class NULLDUMMYTest(BitcoinTestFramework):
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 = [['-whitelist=127.0.0.1', '-segwitheight=432', '-addresstype=legacy']]
+ self.extra_args = [[
+ '-segwitheight=432',
+ '-addresstype=legacy',
+ ]]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -108,7 +111,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
witness and add_witness_commitment(block)
block.rehash()
block.solve()
- node.submitblock(block.serialize().hex())
+ 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
diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py
index 21b6b299f6..c9362cf5aa 100755
--- a/test/functional/feature_pruning.py
+++ b/test/functional/feature_pruning.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 the pruning code.
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index 9e578f0026..acf551ef69 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -10,7 +10,7 @@ from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut
from test_framework.script import CScript, OP_DROP
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error, satoshi_round
-from test_framework.script_util import DUMMY_P2WPKH_SCRIPT
+from test_framework.script_util import DUMMY_P2WPKH_SCRIPT, DUMMY_2_P2WPKH_SCRIPT
MAX_REPLACEMENT_LIMIT = 100
@@ -142,7 +142,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Should fail because we haven't changed the fee
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT + b'a')]
+ tx1b.vout = [CTxOut(1 * COIN, DUMMY_2_P2WPKH_SCRIPT)]
tx1b_hex = txToHex(tx1b)
# This will raise an exception due to insufficient fee
diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py
index 82c7e55245..fdd86310c0 100755
--- a/test/functional/feature_segwit.py
+++ b/test/functional/feature_segwit.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2019 The Bitcoin Core developers
+# Copyright (c) 2016-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 the SegWit changeover logic."""
@@ -28,8 +28,8 @@ from test_framework.util import (
NODE_0 = 0
NODE_2 = 2
-WIT_V0 = 0
-WIT_V1 = 1
+P2WPKH = 0
+P2WSH = 1
def getutxo(txid):
utxo = {}
@@ -72,6 +72,7 @@ class SegWitTest(BitcoinTestFramework):
"-addresstype=legacy",
],
]
+ self.rpc_timeout = 120
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -117,8 +118,8 @@ class SegWitTest(BitcoinTestFramework):
balance_presetup = self.nodes[0].getbalance()
self.pubkey = []
- p2sh_ids = [] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh
- wit_ids = [] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness
+ p2sh_ids = [] # p2sh_ids[NODE][TYPE] is an array of txids that spend to P2WPKH (TYPE=0) or P2WSH (TYPE=1) scripts to an address for NODE embedded in p2sh
+ wit_ids = [] # wit_ids[NODE][TYPE] is an array of txids that spend to P2WPKH (TYPE=0) or P2WSH (TYPE=1) scripts to an address for NODE via bare witness
for i in range(3):
newaddress = self.nodes[i].getnewaddress()
self.pubkey.append(self.nodes[i].getaddressinfo(newaddress)["pubkey"])
@@ -151,14 +152,14 @@ class SegWitTest(BitcoinTestFramework):
self.sync_blocks()
self.log.info("Verify witness txs are skipped for mining before the fork")
- self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][0], True) # block 424
- self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][0], True) # block 425
- self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) # block 426
- self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) # block 427
+ self.skip_mine(self.nodes[2], wit_ids[NODE_2][P2WPKH][0], True) # block 424
+ self.skip_mine(self.nodes[2], wit_ids[NODE_2][P2WSH][0], True) # block 425
+ self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][P2WPKH][0], True) # block 426
+ self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][P2WSH][0], True) # block 427
self.log.info("Verify unsigned p2sh witness txs without a redeem script are invalid")
- self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V0][1], False)
- self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V1][1], False)
+ self.fail_accept(self.nodes[2], "mandatory-script-verify-flag-failed (Operation not valid with the current stack size)", p2sh_ids[NODE_2][P2WPKH][1], sign=False)
+ self.fail_accept(self.nodes[2], "mandatory-script-verify-flag-failed (Operation not valid with the current stack size)", p2sh_ids[NODE_2][P2WSH][1], sign=False)
self.nodes[2].generate(4) # blocks 428-431
@@ -172,13 +173,13 @@ class SegWitTest(BitcoinTestFramework):
self.log.info("Verify default node can't accept txs with missing witness")
# unsigned, no scriptsig
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V0][0], False)
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V1][0], False)
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False)
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False)
+ self.fail_accept(self.nodes[0], "non-mandatory-script-verify-flag (Witness program hash mismatch)", wit_ids[NODE_0][P2WPKH][0], sign=False)
+ self.fail_accept(self.nodes[0], "non-mandatory-script-verify-flag (Witness program was passed an empty witness)", wit_ids[NODE_0][P2WSH][0], sign=False)
+ self.fail_accept(self.nodes[0], "mandatory-script-verify-flag-failed (Operation not valid with the current stack size)", p2sh_ids[NODE_0][P2WPKH][0], sign=False)
+ self.fail_accept(self.nodes[0], "mandatory-script-verify-flag-failed (Operation not valid with the current stack size)", p2sh_ids[NODE_0][P2WSH][0], sign=False)
# unsigned with redeem script
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0]))
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0]))
+ self.fail_accept(self.nodes[0], "non-mandatory-script-verify-flag (Witness program hash mismatch)", p2sh_ids[NODE_0][P2WPKH][0], sign=False, redeem_script=witness_script(False, self.pubkey[0]))
+ self.fail_accept(self.nodes[0], "non-mandatory-script-verify-flag (Witness program was passed an empty witness)", p2sh_ids[NODE_0][P2WSH][0], sign=False, redeem_script=witness_script(True, self.pubkey[0]))
self.log.info("Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag")
assert self.nodes[2].getblock(blockhash, False) != self.nodes[0].getblock(blockhash, False)
@@ -193,16 +194,16 @@ class SegWitTest(BitcoinTestFramework):
assert self.nodes[0].getrawtransaction(tx_id, False, blockhash) == tx.serialize_without_witness().hex()
self.log.info("Verify witness txs without witness data are invalid after the fork")
- self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch)', wit_ids[NODE_2][WIT_V0][2], sign=False)
- self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness)', wit_ids[NODE_2][WIT_V1][2], sign=False)
- self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch)', p2sh_ids[NODE_2][WIT_V0][2], sign=False, redeem_script=witness_script(False, self.pubkey[2]))
- self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness)', p2sh_ids[NODE_2][WIT_V1][2], sign=False, redeem_script=witness_script(True, self.pubkey[2]))
+ self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch)', wit_ids[NODE_2][P2WPKH][2], sign=False)
+ self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness)', wit_ids[NODE_2][P2WSH][2], sign=False)
+ self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch)', p2sh_ids[NODE_2][P2WPKH][2], sign=False, redeem_script=witness_script(False, self.pubkey[2]))
+ self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness)', p2sh_ids[NODE_2][P2WSH][2], sign=False, redeem_script=witness_script(True, self.pubkey[2]))
self.log.info("Verify default node can now use witness txs")
- self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) # block 432
- self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) # block 433
- self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) # block 434
- self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) # block 435
+ self.success_mine(self.nodes[0], wit_ids[NODE_0][P2WPKH][0], True) # block 432
+ self.success_mine(self.nodes[0], wit_ids[NODE_0][P2WSH][0], True) # block 433
+ self.success_mine(self.nodes[0], p2sh_ids[NODE_0][P2WPKH][0], True) # block 434
+ self.success_mine(self.nodes[0], p2sh_ids[NODE_0][P2WSH][0], True) # block 435
self.log.info("Verify sigops are counted in GBT with BIP141 rules after the fork")
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index f04a58cd19..1c94305220 100755
--- a/test/functional/interface_bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -1,13 +1,19 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2019 The Bitcoin Core developers
+# Copyright (c) 2017-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 bitcoin-cli"""
+from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_process_error, get_auth_cookie
-class TestBitcoinCli(BitcoinTestFramework):
+# The block reward of coinbaseoutput.nValue (50) BTC/block matures after
+# COINBASE_MATURITY (100) blocks. Therefore, after mining 101 blocks we expect
+# node 0 to have a balance of (BLOCKS - COINBASE_MATURITY) * 50 BTC/block.
+BLOCKS = 101
+BALANCE = (BLOCKS - 100) * 50
+class TestBitcoinCli(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
@@ -17,15 +23,7 @@ class TestBitcoinCli(BitcoinTestFramework):
def run_test(self):
"""Main test logic"""
-
- cli_response = self.nodes[0].cli("-version").send_cli()
- assert "{} RPC client version".format(self.config['environment']['PACKAGE_NAME']) in cli_response
-
- self.log.info("Compare responses from getwalletinfo RPC and `bitcoin-cli getwalletinfo`")
- if self.is_wallet_compiled():
- cli_response = self.nodes[0].cli.getwalletinfo()
- rpc_response = self.nodes[0].getwalletinfo()
- assert_equal(cli_response, rpc_response)
+ self.nodes[0].generate(BLOCKS)
self.log.info("Compare responses from getblockchaininfo RPC and `bitcoin-cli getblockchaininfo`")
cli_response = self.nodes[0].cli.getblockchaininfo()
@@ -35,12 +33,12 @@ class TestBitcoinCli(BitcoinTestFramework):
user, password = get_auth_cookie(self.nodes[0].datadir, self.chain)
self.log.info("Test -stdinrpcpass option")
- assert_equal(0, self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input=password).getblockcount())
- assert_raises_process_error(1, "Incorrect rpcuser or rpcpassword", self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input="foo").echo)
+ assert_equal(BLOCKS, self.nodes[0].cli('-rpcuser={}'.format(user), '-stdinrpcpass', input=password).getblockcount())
+ assert_raises_process_error(1, 'Incorrect rpcuser or rpcpassword', self.nodes[0].cli('-rpcuser={}'.format(user), '-stdinrpcpass', input='foo').echo)
self.log.info("Test -stdin and -stdinrpcpass")
- assert_equal(["foo", "bar"], self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', input=password + "\nfoo\nbar").echo())
- assert_raises_process_error(1, "Incorrect rpcuser or rpcpassword", self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', input="foo").echo)
+ assert_equal(['foo', 'bar'], self.nodes[0].cli('-rpcuser={}'.format(user), '-stdin', '-stdinrpcpass', input=password + '\nfoo\nbar').echo())
+ assert_raises_process_error(1, 'Incorrect rpcuser or rpcpassword', self.nodes[0].cli('-rpcuser={}'.format(user), '-stdin', '-stdinrpcpass', input='foo').echo)
self.log.info("Test connecting to a non-existing server")
assert_raises_process_error(1, "Could not connect to the server", self.nodes[0].cli('-rpcport=1').echo)
@@ -48,29 +46,87 @@ class TestBitcoinCli(BitcoinTestFramework):
self.log.info("Test connecting with non-existing RPC cookie file")
assert_raises_process_error(1, "Could not locate RPC credentials", self.nodes[0].cli('-rpccookiefile=does-not-exist', '-rpcpassword=').echo)
- self.log.info("Make sure that -getinfo with arguments fails")
+ self.log.info("Test -getinfo with arguments fails")
assert_raises_process_error(1, "-getinfo takes no arguments", self.nodes[0].cli('-getinfo').help)
- self.log.info("Compare responses from `bitcoin-cli -getinfo` and the RPCs data is retrieved from.")
- cli_get_info = self.nodes[0].cli('-getinfo').send_cli()
+ self.log.info("Test -getinfo returns expected network and blockchain info")
if self.is_wallet_compiled():
- wallet_info = self.nodes[0].getwalletinfo()
+ self.nodes[0].encryptwallet(password)
+ cli_get_info = self.nodes[0].cli('-getinfo').send_cli()
network_info = self.nodes[0].getnetworkinfo()
blockchain_info = self.nodes[0].getblockchaininfo()
-
assert_equal(cli_get_info['version'], network_info['version'])
assert_equal(cli_get_info['blocks'], blockchain_info['blocks'])
+ assert_equal(cli_get_info['headers'], blockchain_info['headers'])
assert_equal(cli_get_info['timeoffset'], network_info['timeoffset'])
assert_equal(cli_get_info['connections'], network_info['connections'])
assert_equal(cli_get_info['proxy'], network_info['networks'][0]['proxy'])
assert_equal(cli_get_info['difficulty'], blockchain_info['difficulty'])
assert_equal(cli_get_info['chain'], blockchain_info['chain'])
+
if self.is_wallet_compiled():
- assert_equal(cli_get_info['balance'], wallet_info['balance'])
+ self.log.info("Test -getinfo and bitcoin-cli getwalletinfo return expected wallet info")
+ assert_equal(cli_get_info['balance'], BALANCE)
+ wallet_info = self.nodes[0].getwalletinfo()
assert_equal(cli_get_info['keypoolsize'], wallet_info['keypoolsize'])
+ assert_equal(cli_get_info['unlocked_until'], wallet_info['unlocked_until'])
assert_equal(cli_get_info['paytxfee'], wallet_info['paytxfee'])
assert_equal(cli_get_info['relayfee'], network_info['relayfee'])
- # unlocked_until is not tested because the wallet is not encrypted
+ assert_equal(self.nodes[0].cli.getwalletinfo(), wallet_info)
+
+ # Setup to test -getinfo and -rpcwallet= with multiple wallets.
+ wallets = ['', 'Encrypted', 'secret']
+ amounts = [Decimal('59.999928'), Decimal(9), Decimal(31)]
+ self.nodes[0].createwallet(wallet_name=wallets[1])
+ self.nodes[0].createwallet(wallet_name=wallets[2])
+ w1 = self.nodes[0].get_wallet_rpc(wallets[0])
+ w2 = self.nodes[0].get_wallet_rpc(wallets[1])
+ w3 = self.nodes[0].get_wallet_rpc(wallets[2])
+ w1.walletpassphrase(password, self.rpc_timeout)
+ w1.sendtoaddress(w2.getnewaddress(), amounts[1])
+ w1.sendtoaddress(w3.getnewaddress(), amounts[2])
+
+ # Mine a block to confirm; adds a block reward (50 BTC) to the default wallet.
+ self.nodes[0].generate(1)
+
+ self.log.info("Test -getinfo with multiple wallets loaded returns no balance")
+ assert_equal(set(self.nodes[0].listwallets()), set(wallets))
+ assert 'balance' not in self.nodes[0].cli('-getinfo').send_cli().keys()
+
+ self.log.info("Test -getinfo with multiple wallets and -rpcwallet returns specified wallet balance")
+ for i in range(len(wallets)):
+ cli_get_info = self.nodes[0].cli('-getinfo').send_cli('-rpcwallet={}'.format(wallets[i]))
+ assert_equal(cli_get_info['balance'], amounts[i])
+
+ self.log.info("Test -getinfo with multiple wallets and -rpcwallet=non-existing-wallet returns no balance")
+ assert 'balance' not in self.nodes[0].cli('-getinfo').send_cli('-rpcwallet=does-not-exist').keys()
+
+ self.log.info("Test -getinfo after unloading all wallets except a non-default one returns its balance")
+ self.nodes[0].unloadwallet(wallets[0])
+ self.nodes[0].unloadwallet(wallets[2])
+ assert_equal(self.nodes[0].listwallets(), [wallets[1]])
+ assert_equal(self.nodes[0].cli('-getinfo').send_cli()['balance'], amounts[1])
+
+ self.log.info("Test -getinfo -rpcwallet=remaining-non-default-wallet returns its balance")
+ assert_equal(self.nodes[0].cli('-getinfo').send_cli('-rpcwallet={}'.format(wallets[1]))['balance'], amounts[1])
+
+ self.log.info("Test -getinfo with -rpcwallet=unloaded wallet returns no balance")
+ assert 'balance' not in self.nodes[0].cli('-getinfo').send_cli('-rpcwallet={}'.format(wallets[2])).keys()
+ else:
+ self.log.info("*** Wallet not compiled; cli getwalletinfo and -getinfo wallet tests skipped")
+ self.nodes[0].generate(1) # maintain block parity with the wallet_compiled conditional branch
+
+ self.log.info("Test -version with node stopped")
+ self.stop_node(0)
+ cli_response = self.nodes[0].cli('-version').send_cli()
+ assert "{} RPC client version".format(self.config['environment']['PACKAGE_NAME']) in cli_response
+
+ self.log.info("Test -rpcwait option successfully waits for RPC connection")
+ self.nodes[0].start() # start node without RPC connection
+ self.nodes[0].wait_for_cookie_credentials() # ensure cookie file is available to avoid race condition
+ blocks = self.nodes[0].cli('-rpcwait').send_cli('getblockcount')
+ self.nodes[0].wait_for_rpc_connection()
+ assert_equal(blocks, BLOCKS + 1)
if __name__ == '__main__':
diff --git a/test/functional/interface_rpc.py b/test/functional/interface_rpc.py
index 3b3b5bb0c1..ac2e73fc5c 100755
--- a/test/functional/interface_rpc.py
+++ b/test/functional/interface_rpc.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
"""Tests some generic aspects of the RPC interface."""
diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
index 900cabccda..6df8f1c3ec 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2019 The Bitcoin Core developers
+# Copyright (c) 2017-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 mempool acceptance of raw transactions."""
@@ -16,6 +16,7 @@ from test_framework.messages import (
CTransaction,
CTxOut,
MAX_BLOCK_BASE_SIZE,
+ MAX_MONEY,
)
from test_framework.script import (
hash160,
@@ -220,7 +221,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
# The following two validations prevent overflow of the output amounts (see CVE-2010-5139).
self.log.info('A transaction with too large output value')
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference)))
- tx.vout[0].nValue = 21000000 * COIN + 1
+ tx.vout[0].nValue = MAX_MONEY + 1
self.check_mempool_result(
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-vout-toolarge'}],
rawtxs=[tx.serialize().hex()],
@@ -229,7 +230,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
self.log.info('A transaction with too large sum of output values')
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference)))
tx.vout = [tx.vout[0]] * 2
- tx.vout[0].nValue = 21000000 * COIN
+ tx.vout[0].nValue = MAX_MONEY
self.check_mempool_result(
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-txouttotal-toolarge'}],
rawtxs=[tx.serialize().hex()],
diff --git a/test/functional/mempool_expiry.py b/test/functional/mempool_expiry.py
new file mode 100755
index 0000000000..8b9b7b155a
--- /dev/null
+++ b/test/functional/mempool_expiry.py
@@ -0,0 +1,100 @@
+#!/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.
+"""Tests that a mempool transaction expires after a given timeout and that its
+children are removed as well.
+
+Both the default expiry timeout defined by DEFAULT_MEMPOOL_EXPIRY and a user
+definable expiry timeout via the '-mempoolexpiry=<n>' command line argument
+(<n> is the timeout in hours) are tested.
+"""
+
+from datetime import timedelta
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+ find_vout_for_address,
+)
+
+DEFAULT_MEMPOOL_EXPIRY = 336 # hours
+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()
+
+ 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]
+
+ # Send a parent transaction that will expire.
+ parent_address = node.getnewaddress()
+ parent_txid = node.sendtoaddress(parent_address, 1.0)
+
+ # 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.
+ half_expiry_time = entry_time + int(60 * 60 * timeout/2)
+ node.setmocktime(half_expiry_time)
+ child_txid = node.sendrawtransaction(child_signed)
+ self.log.info('Broadcast child transaction after {} hours.'.format(
+ timedelta(seconds=(half_expiry_time-entry_time))))
+
+ # 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)
+ 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'])
+
+ # Transaction should be evicted from the mempool after the expiry time
+ # 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)
+ 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',
+ node.getmempoolentry, parent_txid)
+
+ # The child transaction should be removed from the mempool as well.
+ self.log.info('Test child tx is evicted as well.')
+ assert_raises_rpc_error(-5, 'Transaction not in mempool',
+ node.getmempoolentry, child_txid)
+
+ def run_test(self):
+ self.log.info('Test default mempool expiry timeout of %d hours.' %
+ DEFAULT_MEMPOOL_EXPIRY)
+ self.test_transaction_expiry(DEFAULT_MEMPOOL_EXPIRY)
+
+ self.log.info('Test custom mempool expiry timeout of %d hours.' %
+ CUSTOM_MEMPOOL_EXPIRY)
+ self.restart_node(0, ['-mempoolexpiry=%d' % CUSTOM_MEMPOOL_EXPIRY])
+ self.test_transaction_expiry(CUSTOM_MEMPOOL_EXPIRY)
+
+
+if __name__ == '__main__':
+ MempoolExpiryTest().main()
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index 7014105d88..a07dad18d6 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -12,6 +12,7 @@ from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
satoshi_round,
+ wait_until,
)
# default limits
@@ -19,13 +20,22 @@ MAX_ANCESTORS = 25
MAX_DESCENDANTS = 25
# custom limits for node1
MAX_ANCESTORS_CUSTOM = 5
+MAX_DESCENDANTS_CUSTOM = 10
+assert MAX_DESCENDANTS_CUSTOM >= MAX_ANCESTORS_CUSTOM
class MempoolPackagesTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.extra_args = [
- ["-maxorphantx=1000"],
- ["-maxorphantx=1000", "-limitancestorcount={}".format(MAX_ANCESTORS_CUSTOM)],
+ [
+ "-maxorphantx=1000",
+ "-whitelist=noban@127.0.0.1", # immediate tx relay
+ ],
+ [
+ "-maxorphantx=1000",
+ "-limitancestorcount={}".format(MAX_ANCESTORS_CUSTOM),
+ "-limitdescendantcount={}".format(MAX_DESCENDANTS_CUSTOM),
+ ],
]
def skip_test_if_missing_module(self):
@@ -219,9 +229,11 @@ class MempoolPackagesTest(BitcoinTestFramework):
transaction_package.append({'txid': txid, 'vout': i, 'amount': sent_value})
# Sign and send up to MAX_DESCENDANT transactions chained off the parent tx
+ chain = [] # save sent txs for the purpose of checking node1's mempool later (see below)
for i in range(MAX_DESCENDANTS - 1):
utxo = transaction_package.pop(0)
(txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10)
+ chain.append(txid)
if utxo['txid'] is parent_transaction:
tx_children.append(txid)
for j in range(10):
@@ -238,7 +250,21 @@ class MempoolPackagesTest(BitcoinTestFramework):
utxo = transaction_package.pop(0)
assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10)
- # TODO: check that node1's mempool is as expected
+ # Check that node1's mempool is as expected, containing:
+ # - txs from previous ancestor test (-> custom ancestor limit)
+ # - parent tx for descendant test
+ # - txs chained off parent tx (-> custom descendant limit)
+ wait_until(lambda: len(self.nodes[1].getrawmempool(False)) ==
+ MAX_ANCESTORS_CUSTOM + 1 + MAX_DESCENDANTS_CUSTOM, timeout=10)
+ mempool0 = self.nodes[0].getrawmempool(False)
+ mempool1 = self.nodes[1].getrawmempool(False)
+ assert set(mempool1).issubset(set(mempool0))
+ assert parent_transaction in mempool1
+ for tx in chain[:MAX_DESCENDANTS_CUSTOM]:
+ assert tx in mempool1
+ for tx in chain[MAX_DESCENDANTS_CUSTOM:]:
+ assert tx not in mempool1
+ # TODO: more detailed check of node1's mempool (fees etc.)
# TODO: test descendant size limits
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
index d3690b245e..99003d2d1f 100755
--- a/test/functional/mempool_persist.py
+++ b/test/functional/mempool_persist.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 mempool persistence.
@@ -40,10 +40,13 @@ import os
import time
from test_framework.test_framework import BitcoinTestFramework
+from test_framework.mininode import P2PTxInvStore
from test_framework.util import (
assert_equal,
assert_greater_than_or_equal,
assert_raises_rpc_error,
+ connect_nodes,
+ disconnect_nodes,
wait_until,
)
@@ -80,6 +83,11 @@ class MempoolPersistTest(BitcoinTestFramework):
assert_greater_than_or_equal(tx_creation_time, tx_creation_time_lower)
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], 2)
+ self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("12"))
+ connect_nodes(self.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()
# Give this node a head-start, so we can be "extra-sure" that it didn't load anything later
@@ -89,7 +97,7 @@ class MempoolPersistTest(BitcoinTestFramework):
self.start_node(2)
wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"], timeout=1)
wait_until(lambda: self.nodes[2].getmempoolinfo()["loaded"], timeout=1)
- assert_equal(len(self.nodes[0].getrawmempool()), 5)
+ assert_equal(len(self.nodes[0].getrawmempool()), 6)
assert_equal(len(self.nodes[2].getrawmempool()), 5)
# The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now:
assert_equal(len(self.nodes[1].getrawmempool()), 0)
@@ -105,9 +113,10 @@ class MempoolPersistTest(BitcoinTestFramework):
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
assert_equal(node2_balance, self.nodes[2].getbalance())
+ # start node0 with wallet disabled so wallet transactions don't get resubmitted
self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
self.stop_nodes()
- self.start_node(0, extra_args=["-persistmempool=0"])
+ self.start_node(0, extra_args=["-persistmempool=0", "-disablewallet"])
wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"])
assert_equal(len(self.nodes[0].getrawmempool()), 0)
@@ -115,7 +124,7 @@ class MempoolPersistTest(BitcoinTestFramework):
self.stop_nodes()
self.start_node(0)
wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"])
- assert_equal(len(self.nodes[0].getrawmempool()), 5)
+ assert_equal(len(self.nodes[0].getrawmempool()), 6)
mempooldat0 = os.path.join(self.nodes[0].datadir, self.chain, 'mempool.dat')
mempooldat1 = os.path.join(self.nodes[1].datadir, self.chain, 'mempool.dat')
@@ -124,12 +133,12 @@ class MempoolPersistTest(BitcoinTestFramework):
self.nodes[0].savemempool()
assert os.path.isfile(mempooldat0)
- self.log.debug("Stop nodes, make node1 use mempool.dat from node0. Verify it has 5 transactions")
+ self.log.debug("Stop nodes, make node1 use mempool.dat from node0. Verify it has 6 transactions")
os.rename(mempooldat0, mempooldat1)
self.stop_nodes()
self.start_node(1, extra_args=[])
wait_until(lambda: self.nodes[1].getmempoolinfo()["loaded"])
- assert_equal(len(self.nodes[1].getrawmempool()), 5)
+ assert_equal(len(self.nodes[1].getrawmempool()), 6)
self.log.debug("Prevent bitcoind from writing mempool.dat to disk. Verify that `savemempool` fails")
# to test the exception we are creating a tmp folder called mempool.dat.new
@@ -139,6 +148,27 @@ class MempoolPersistTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "Unable to dump mempool to disk", self.nodes[1].savemempool)
os.rmdir(mempooldotnew1)
+ self.test_persist_unbroadcast()
+
+ def test_persist_unbroadcast(self):
+ node0 = self.nodes[0]
+ self.start_node(0)
+
+ # clear out mempool
+ node0.generate(1)
+
+ # disconnect nodes to make a txn that remains in the unbroadcast set.
+ disconnect_nodes(node0, 1)
+ node0.sendtoaddress(self.nodes[1].getnewaddress(), Decimal("12"))
+
+ # shutdown, then startup with wallet disabled
+ self.stop_nodes()
+ self.start_node(0, extra_args=["-disablewallet"])
+
+ # check that txn gets broadcast due to unbroadcast logic
+ conn = node0.add_p2p_connection(P2PTxInvStore())
+ node0.mockscheduler(16*60) # 15 min + 1 for buffer
+ wait_until(lambda: len(conn.get_invs()) == 1)
if __name__ == '__main__':
MempoolPersistTest().main()
diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py
index 3b148d5cf0..8e1f87e42c 100755
--- a/test/functional/mempool_reorg.py
+++ b/test/functional/mempool_reorg.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2018 The Bitcoin Core developers
+# Copyright (c) 2014-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 mempool re-org scenarios.
@@ -16,12 +16,16 @@ from test_framework.util import assert_equal, assert_raises_rpc_error
class MempoolCoinbaseTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
+ self.extra_args = [
+ [
+ '-whitelist=noban@127.0.0.1', # immediate tx relay
+ ],
+ []
+ ]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- alert_filename = None # Set by setup_network
-
def run_test(self):
# Start with a 200 block chain
assert_equal(self.nodes[0].getblockcount(), 200)
@@ -40,17 +44,21 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
# 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1
# Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase),
# and make sure the mempool code behaves correctly.
- b = [ self.nodes[0].getblockhash(n) for n in range(101, 105) ]
- coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
+ b = [self.nodes[0].getblockhash(n) for n in range(101, 105)]
+ coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b]
spend_101_raw = create_raw_transaction(self.nodes[0], coinbase_txids[1], node1_address, amount=49.99)
spend_102_raw = create_raw_transaction(self.nodes[0], coinbase_txids[2], node0_address, amount=49.99)
spend_103_raw = create_raw_transaction(self.nodes[0], coinbase_txids[3], node0_address, amount=49.99)
# Create a transaction which is time-locked to two blocks in the future
- timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 49.99})
- # Set the time lock
- timelock_tx = timelock_tx.replace("ffffffff", "11111191", 1)
- timelock_tx = timelock_tx[:-8] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000"
+ timelock_tx = self.nodes[0].createrawtransaction(
+ inputs=[{
+ "txid": coinbase_txids[0],
+ "vout": 0,
+ }],
+ outputs={node0_address: 49.99},
+ locktime=self.nodes[0].getblockcount() + 2,
+ )
timelock_tx = self.nodes[0].signrawtransactionwithwallet(timelock_tx)["hex"]
# This will raise an exception because the timelock transaction is too immature to spend
assert_raises_rpc_error(-26, "non-final", self.nodes[0].sendrawtransaction, timelock_tx)
@@ -69,6 +77,10 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
# Broadcast and mine 103_1:
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
last_block = self.nodes[0].generate(1)
+ # Sync blocks, so that peer 1 gets the block before timelock_tx
+ # Otherwise, peer 1 would put the timelock_tx in recentRejects
+ self.sync_all()
+
# Time-locked transaction can now be spent
timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx)
@@ -76,9 +88,8 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
spend_101_id = self.nodes[0].sendrawtransaction(spend_101_raw)
spend_102_1_id = self.nodes[0].sendrawtransaction(spend_102_1_raw)
- self.sync_all(timeout=360)
-
assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_1_id, timelock_tx_id})
+ self.sync_all()
for node in self.nodes:
node.invalidateblock(last_block[0])
@@ -91,10 +102,10 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
for node in self.nodes:
node.invalidateblock(new_blocks[0])
- self.sync_all(timeout=360)
-
# mempool should be empty.
assert_equal(set(self.nodes[0].getrawmempool()), set())
+ self.sync_all()
+
if __name__ == '__main__':
MempoolCoinbaseTest().main()
diff --git a/test/functional/mempool_unbroadcast.py b/test/functional/mempool_unbroadcast.py
new file mode 100755
index 0000000000..a561f28b91
--- /dev/null
+++ b/test/functional/mempool_unbroadcast.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017-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 that the mempool ensures transaction delivery by periodically sending
+to peers until a GETDATA is received."""
+
+import time
+
+from test_framework.mininode import P2PTxInvStore
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ connect_nodes,
+ create_confirmed_utxos,
+ disconnect_nodes,
+)
+
+
+class MempoolUnbroadcastTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 2
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def run_test(self):
+ self.test_broadcast()
+ self.test_txn_removal()
+
+ def test_broadcast(self):
+ self.log.info("Test that mempool reattempts delivery of locally submitted transaction")
+ node = self.nodes[0]
+
+ min_relay_fee = node.getnetworkinfo()["relayfee"]
+ utxos = create_confirmed_utxos(min_relay_fee, node, 10)
+
+ disconnect_nodes(node, 1)
+
+ self.log.info("Generate transactions that only node 0 knows about")
+
+ # generate a wallet txn
+ addr = node.getnewaddress()
+ wallet_tx_hsh = node.sendtoaddress(addr, 0.0001)
+
+ # generate a txn using sendrawtransaction
+ us0 = utxos.pop()
+ inputs = [{"txid": us0["txid"], "vout": us0["vout"]}]
+ outputs = {addr: 0.0001}
+ tx = node.createrawtransaction(inputs, outputs)
+ node.settxfee(min_relay_fee)
+ txF = node.fundrawtransaction(tx)
+ txFS = node.signrawtransactionwithwallet(txF["hex"])
+ rpc_tx_hsh = node.sendrawtransaction(txFS["hex"])
+
+ # check that second node doesn't have these two txns
+ mempool = self.nodes[1].getrawmempool()
+ assert rpc_tx_hsh not in mempool
+ assert wallet_tx_hsh not in mempool
+
+ # ensure that unbroadcast txs are persisted to mempool.dat
+ self.restart_node(0)
+
+ self.log.info("Reconnect nodes & check if they are sent to node 1")
+ connect_nodes(node, 1)
+
+ # fast forward into the future & ensure that the second node has the txns
+ node.mockscheduler(15 * 60) # 15 min in seconds
+ self.sync_mempools(timeout=30)
+ mempool = self.nodes[1].getrawmempool()
+ assert rpc_tx_hsh in mempool
+ assert wallet_tx_hsh in mempool
+
+ self.log.info("Add another connection & ensure transactions aren't broadcast again")
+
+ conn = node.add_p2p_connection(P2PTxInvStore())
+ node.mockscheduler(15 * 60)
+ time.sleep(5)
+ assert_equal(len(conn.get_invs()), 0)
+
+ def test_txn_removal(self):
+ self.log.info("Test that transactions removed from mempool are removed from unbroadcast set")
+ node = self.nodes[0]
+ disconnect_nodes(node, 1)
+ node.disconnect_p2ps
+
+ # since the node doesn't have any connections, it will not receive
+ # any GETDATAs & thus the transaction will remain in the unbroadcast set.
+ addr = node.getnewaddress()
+ txhsh = node.sendtoaddress(addr, 0.0001)
+
+ # check transaction was removed from unbroadcast set due to presence in
+ # a block
+ removal_reason = "Removed {} from set of unbroadcast txns before confirmation that txn was sent out".format(txhsh)
+ with node.assert_debug_log([removal_reason]):
+ node.generate(1)
+
+if __name__ == "__main__":
+ MempoolUnbroadcastTest().main()
diff --git a/test/functional/mempool_updatefromblock.py b/test/functional/mempool_updatefromblock.py
new file mode 100755
index 0000000000..8a703ef009
--- /dev/null
+++ b/test/functional/mempool_updatefromblock.py
@@ -0,0 +1,123 @@
+#!/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 mempool descendants/ancestors information update.
+
+Test mempool update of transaction descendants/ancestors information (count, size)
+when transactions have been re-added from a disconnected block to the mempool.
+"""
+import time
+
+from decimal import Decimal
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+
+class MempoolUpdateFromBlockTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+ self.extra_args = [['-limitdescendantsize=1000', '-limitancestorsize=1000']]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def transaction_graph_test(self, size, n_tx_to_mine=None, start_input_txid='', end_address='', fee=Decimal(0.00100000)):
+ """Create an acyclic tournament (a type of directed graph) of transactions and use it for testing.
+
+ Keyword arguments:
+ size -- the order N of the tournament which is equal to the number of the created transactions
+ n_tx_to_mine -- the number of transaction that should be mined into a block
+
+ If all of the N created transactions tx[0]..tx[N-1] reside in the mempool,
+ the following holds:
+ the tx[K] transaction:
+ - has N-K descendants (including this one), and
+ - has K+1 ancestors (including this one)
+
+ More details: https://en.wikipedia.org/wiki/Tournament_(graph_theory)
+ """
+
+ if not start_input_txid:
+ start_input_txid = self.nodes[0].getblock(self.nodes[0].getblockhash(1))['tx'][0]
+
+ if not end_address:
+ end_address = self.nodes[0].getnewaddress()
+
+ first_block_hash = ''
+ tx_id = []
+ tx_size = []
+ self.log.info('Creating {} transactions...'.format(size))
+ for i in range(0, size):
+ self.log.debug('Preparing transaction #{}...'.format(i))
+ # Prepare inputs.
+ if i == 0:
+ inputs = [{'txid': start_input_txid, 'vout': 0}]
+ inputs_value = self.nodes[0].gettxout(start_input_txid, 0)['value']
+ else:
+ inputs = []
+ inputs_value = 0
+ for j, tx in enumerate(tx_id[0:i]):
+ # Transaction tx[K] is a child of each of previous transactions tx[0]..tx[K-1] at their output K-1.
+ vout = i - j - 1
+ inputs.append({'txid': tx_id[j], 'vout': vout})
+ inputs_value += self.nodes[0].gettxout(tx, vout)['value']
+
+ self.log.debug('inputs={}'.format(inputs))
+ self.log.debug('inputs_value={}'.format(inputs_value))
+
+ # Prepare outputs.
+ tx_count = i + 1
+ if tx_count < size:
+ # Transaction tx[K] is an ancestor of each of subsequent transactions tx[K+1]..tx[N-1].
+ n_outputs = size - tx_count
+ output_value = ((inputs_value - fee) / Decimal(n_outputs)).quantize(Decimal('0.00000001'))
+ outputs = {}
+ for n in range(0, n_outputs):
+ outputs[self.nodes[0].getnewaddress()] = output_value
+ else:
+ output_value = (inputs_value - fee).quantize(Decimal('0.00000001'))
+ outputs = {end_address: output_value}
+
+ self.log.debug('output_value={}'.format(output_value))
+ self.log.debug('outputs={}'.format(outputs))
+
+ # Create a new transaction.
+ unsigned_raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
+ signed_raw_tx = self.nodes[0].signrawtransactionwithwallet(unsigned_raw_tx)
+ tx_id.append(self.nodes[0].sendrawtransaction(signed_raw_tx['hex']))
+ tx_size.append(self.nodes[0].getrawmempool(True)[tx_id[-1]]['vsize'])
+
+ if tx_count in n_tx_to_mine:
+ # The created transactions are mined into blocks by batches.
+ self.log.info('The batch of {} transactions has been accepted into the mempool.'.format(len(self.nodes[0].getrawmempool())))
+ block_hash = self.nodes[0].generate(1)[0]
+ if not first_block_hash:
+ first_block_hash = block_hash
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+ self.log.info('All of the transactions from the current batch have been mined into a block.')
+ elif tx_count == size:
+ # At the end all of the mined blocks are invalidated, and all of the created
+ # transactions should be re-added from disconnected blocks to the mempool.
+ self.log.info('The last batch of {} transactions has been accepted into the mempool.'.format(len(self.nodes[0].getrawmempool())))
+ start = time.time()
+ self.nodes[0].invalidateblock(first_block_hash)
+ end = time.time()
+ assert_equal(len(self.nodes[0].getrawmempool()), size)
+ self.log.info('All of the recently mined transactions have been re-added into the mempool in {} seconds.'.format(end - start))
+
+ self.log.info('Checking descendants/ancestors properties of all of the in-mempool transactions...')
+ for k, tx in enumerate(tx_id):
+ self.log.debug('Check transaction #{}.'.format(k))
+ assert_equal(self.nodes[0].getrawmempool(True)[tx]['descendantcount'], size - k)
+ assert_equal(self.nodes[0].getrawmempool(True)[tx]['descendantsize'], sum(tx_size[k:size]))
+ assert_equal(self.nodes[0].getrawmempool(True)[tx]['ancestorcount'], k + 1)
+ assert_equal(self.nodes[0].getrawmempool(True)[tx]['ancestorsize'], sum(tx_size[0:(k + 1)]))
+
+ def run_test(self):
+ # Use batch size limited by DEFAULT_ANCESTOR_LIMIT = 25 to not fire "too many unconfirmed parents" error.
+ self.transaction_graph_test(size=100, n_tx_to_mine=[25, 50, 75])
+
+
+if __name__ == '__main__':
+ MempoolUpdateFromBlockTest().main()
diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py
index 8262e30592..1bda167c87 100755
--- a/test/functional/mining_basic.py
+++ b/test/functional/mining_basic.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 mining RPCs
diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py
new file mode 100755
index 0000000000..6046237101
--- /dev/null
+++ b/test/functional/p2p_addr_relay.py
@@ -0,0 +1,71 @@
+#!/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 addr relay
+"""
+
+from test_framework.messages import (
+ CAddress,
+ NODE_NETWORK,
+ NODE_WITNESS,
+ msg_addr,
+)
+from test_framework.mininode import (
+ P2PInterface,
+)
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+)
+import time
+
+ADDRS = []
+for i in range(10):
+ addr = CAddress()
+ addr.time = int(time.time()) + i
+ addr.nServices = NODE_NETWORK | NODE_WITNESS
+ addr.ip = "123.123.123.{}".format(i % 256)
+ addr.port = 8333 + i
+ ADDRS.append(addr)
+
+
+class AddrReceiver(P2PInterface):
+ def on_addr(self, message):
+ for addr in message.addrs:
+ assert_equal(addr.nServices, 9)
+ assert addr.ip.startswith('123.123.123.')
+ assert (8333 <= addr.port < 8343)
+
+
+class AddrTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+
+ def run_test(self):
+ self.log.info('Create connection that sends addr messages')
+ addr_source = self.nodes[0].add_p2p_connection(P2PInterface())
+ msg = msg_addr()
+
+ self.log.info('Send too large addr message')
+ msg.addrs = ADDRS * 101
+ with self.nodes[0].assert_debug_log(['message addr 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())
+ msg.addrs = ADDRS
+ with self.nodes[0].assert_debug_log([
+ 'Added 10 addresses from 127.0.0.1: 0 tried',
+ '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()
+
+
+if __name__ == '__main__':
+ AddrTest().main()
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index 7905cf5018..66e6f8c424 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -378,8 +378,6 @@ class CompactBlocksTest(BitcoinTestFramework):
# request
for announce in ["inv", "header"]:
block = self.build_block_on_tip(node, segwit=segwit)
- with mininode_lock:
- test_node.last_message.pop("getdata", None)
if announce == "inv":
test_node.send_message(msg_inv([CInv(2, block.sha256)]))
@@ -387,10 +385,8 @@ class CompactBlocksTest(BitcoinTestFramework):
test_node.send_header_for_blocks([block])
else:
test_node.send_header_for_blocks([block])
- wait_until(lambda: "getdata" in test_node.last_message, timeout=30, lock=mininode_lock)
- assert_equal(len(test_node.last_message["getdata"].inv), 1)
+ test_node.wait_for_getdata([block.sha256], timeout=30)
assert_equal(test_node.last_message["getdata"].inv[0].type, 4)
- assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256)
# Send back a compactblock message that omits the coinbase
comp_block = HeaderAndShortIDs()
@@ -567,10 +563,8 @@ class CompactBlocksTest(BitcoinTestFramework):
assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock)
# We should receive a getdata request
- wait_until(lambda: "getdata" in test_node.last_message, timeout=10, lock=mininode_lock)
- assert_equal(len(test_node.last_message["getdata"].inv), 1)
+ test_node.wait_for_getdata([block.sha256], timeout=10)
assert test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[0].type == 2 | MSG_WITNESS_FLAG
- assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256)
# Deliver the block
if version == 2:
diff --git a/test/functional/p2p_dos_header_tree.py b/test/functional/p2p_dos_header_tree.py
index 6676b84e54..f8552cf53d 100755
--- a/test/functional/p2p_dos_header_tree.py
+++ b/test/functional/p2p_dos_header_tree.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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 that we reject low difficulty headers to prevent our block tree from filling up with useless bloat"""
@@ -47,8 +47,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
self.log.info("Feed all non-fork headers, including and up to the first checkpoint")
self.nodes[0].add_p2p_connection(P2PInterface())
- self.nodes[0].p2p.send_message(msg_headers(self.headers))
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.send_and_ping(msg_headers(self.headers))
assert {
'height': 546,
'hash': '000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70',
@@ -65,8 +64,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
# On node 0 it succeeds because checkpoints are disabled
self.restart_node(0, extra_args=['-nocheckpoints'])
self.nodes[0].add_p2p_connection(P2PInterface())
- self.nodes[0].p2p.send_message(msg_headers(self.headers_fork))
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.send_and_ping(msg_headers(self.headers_fork))
assert {
"height": 2,
"hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39",
@@ -76,8 +74,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
# On node 1 it succeeds because no checkpoint has been reached yet by a chain tip
self.nodes[1].add_p2p_connection(P2PInterface())
- self.nodes[1].p2p.send_message(msg_headers(self.headers_fork))
- self.nodes[1].p2p.sync_with_ping()
+ self.nodes[1].p2p.send_and_ping(msg_headers(self.headers_fork))
assert {
"height": 2,
"hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39",
diff --git a/test/functional/p2p_filter.py b/test/functional/p2p_filter.py
new file mode 100755
index 0000000000..15955a938c
--- /dev/null
+++ b/test/functional/p2p_filter.py
@@ -0,0 +1,158 @@
+#!/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 BIP 37
+"""
+
+from test_framework.messages import (
+ CInv,
+ MAX_BLOOM_FILTER_SIZE,
+ MAX_BLOOM_HASH_FUNCS,
+ MSG_BLOCK,
+ MSG_FILTERED_BLOCK,
+ msg_filteradd,
+ msg_filterclear,
+ msg_filterload,
+ msg_getdata,
+)
+from test_framework.mininode import P2PInterface
+from test_framework.script import MAX_SCRIPT_ELEMENT_SIZE
+from test_framework.test_framework import BitcoinTestFramework
+
+
+class FilterNode(P2PInterface):
+ # This is a P2SH watch-only wallet
+ watch_script_pubkey = 'a914ffffffffffffffffffffffffffffffffffffffff87'
+ # The initial filter (n=10, fp=0.000001) with just the above scriptPubKey added
+ watch_filter_init = msg_filterload(
+ data=
+ b'@\x00\x08\x00\x80\x00\x00 \x00\xc0\x00 \x04\x00\x08$\x00\x04\x80\x00\x00 \x00\x00\x00\x00\x80\x00\x00@\x00\x02@ \x00',
+ nHashFuncs=19,
+ nTweak=0,
+ nFlags=1,
+ )
+
+ def on_inv(self, message):
+ want = msg_getdata()
+ for i in message.inv:
+ # inv messages can only contain TX or BLOCK, so translate BLOCK to FILTERED_BLOCK
+ if i.type == MSG_BLOCK:
+ want.inv.append(CInv(MSG_FILTERED_BLOCK, i.hash))
+ else:
+ want.inv.append(i)
+ if len(want.inv):
+ self.send_message(want)
+
+ def on_merkleblock(self, message):
+ self.merkleblock_received = True
+
+ def on_tx(self, message):
+ self.tx_received = True
+
+
+class FilterTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+ self.extra_args = [[
+ '-peerbloomfilters',
+ '-whitelist=noban@127.0.0.1', # immediate tx relay
+ ]]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def test_size_limits(self, filter_node):
+ self.log.info('Check that too large filter is rejected')
+ with self.nodes[0].assert_debug_log(['Misbehaving']):
+ filter_node.send_and_ping(msg_filterload(data=b'\xbb'*(MAX_BLOOM_FILTER_SIZE+1)))
+
+ self.log.info('Check that max size filter is accepted')
+ with self.nodes[0].assert_debug_log([], unexpected_msgs=['Misbehaving']):
+ filter_node.send_and_ping(msg_filterload(data=b'\xbb'*(MAX_BLOOM_FILTER_SIZE)))
+ filter_node.send_and_ping(msg_filterclear())
+
+ self.log.info('Check that filter with too many hash functions is rejected')
+ with self.nodes[0].assert_debug_log(['Misbehaving']):
+ filter_node.send_and_ping(msg_filterload(data=b'\xaa', nHashFuncs=MAX_BLOOM_HASH_FUNCS+1))
+
+ self.log.info('Check that filter with max hash functions is accepted')
+ with self.nodes[0].assert_debug_log([], unexpected_msgs=['Misbehaving']):
+ filter_node.send_and_ping(msg_filterload(data=b'\xaa', nHashFuncs=MAX_BLOOM_HASH_FUNCS))
+ # Don't send filterclear until next two filteradd checks are done
+
+ self.log.info('Check that max size data element to add to the filter is accepted')
+ with self.nodes[0].assert_debug_log([], unexpected_msgs=['Misbehaving']):
+ filter_node.send_and_ping(msg_filteradd(data=b'\xcc'*(MAX_SCRIPT_ELEMENT_SIZE)))
+
+ self.log.info('Check that too large data element to add to the filter is rejected')
+ with self.nodes[0].assert_debug_log(['Misbehaving']):
+ filter_node.send_and_ping(msg_filteradd(data=b'\xcc'*(MAX_SCRIPT_ELEMENT_SIZE+1)))
+
+ filter_node.send_and_ping(msg_filterclear())
+
+ def run_test(self):
+ filter_node = self.nodes[0].add_p2p_connection(FilterNode())
+
+ self.test_size_limits(filter_node)
+
+ self.log.info('Add filtered P2P connection to the node')
+ filter_node.send_and_ping(filter_node.watch_filter_init)
+ filter_address = self.nodes[0].decodescript(filter_node.watch_script_pubkey)['addresses'][0]
+
+ self.log.info('Check that we receive merkleblock and tx if the filter matches a tx in a block')
+ block_hash = self.nodes[0].generatetoaddress(1, filter_address)[0]
+ txid = self.nodes[0].getblock(block_hash)['tx'][0]
+ filter_node.wait_for_merkleblock(block_hash)
+ filter_node.wait_for_tx(txid)
+
+ self.log.info('Check that we only receive a merkleblock if the filter does not match a tx in a block')
+ filter_node.tx_received = False
+ block_hash = self.nodes[0].generatetoaddress(1, self.nodes[0].getnewaddress())[0]
+ filter_node.wait_for_merkleblock(block_hash)
+ assert not filter_node.tx_received
+
+ self.log.info('Check that we not receive a tx if the filter does not match a mempool tx')
+ filter_node.merkleblock_received = False
+ filter_node.tx_received = False
+ self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 90)
+ filter_node.sync_with_ping()
+ filter_node.sync_with_ping()
+ assert not filter_node.merkleblock_received
+ assert not filter_node.tx_received
+
+ self.log.info('Check that we receive a tx in reply to a mempool msg if the filter matches a mempool tx')
+ filter_node.merkleblock_received = False
+ txid = self.nodes[0].sendtoaddress(filter_address, 90)
+ filter_node.wait_for_tx(txid)
+ assert not filter_node.merkleblock_received
+
+ self.log.info('Check that after deleting filter all txs get relayed again')
+ filter_node.send_and_ping(msg_filterclear())
+ for _ in range(5):
+ txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 7)
+ filter_node.wait_for_tx(txid)
+
+ self.log.info('Check that request for filtered blocks is ignored if no filter is set')
+ filter_node.merkleblock_received = False
+ filter_node.tx_received = False
+ with self.nodes[0].assert_debug_log(expected_msgs=['received getdata']):
+ block_hash = self.nodes[0].generatetoaddress(1, self.nodes[0].getnewaddress())[0]
+ filter_node.wait_for_inv([CInv(MSG_BLOCK, int(block_hash, 16))])
+ filter_node.sync_with_ping()
+ assert not filter_node.merkleblock_received
+ assert not filter_node.tx_received
+
+ self.log.info('Check that sending "filteradd" if no filter is set is treated as misbehavior')
+ with self.nodes[0].assert_debug_log(['Misbehaving']):
+ filter_node.send_and_ping(msg_filteradd(data=b'letsmisbehave'))
+
+ self.log.info("Check that division-by-zero remote crash bug [CVE-2013-5700] is fixed")
+ filter_node.send_and_ping(msg_filterload(data=b'', nHashFuncs=1))
+ filter_node.send_and_ping(msg_filteradd(data=b'letstrytocrashthisnode'))
+
+
+if __name__ == '__main__':
+ FilterTest().main()
diff --git a/test/functional/p2p_fingerprint.py b/test/functional/p2p_fingerprint.py
index fab0887197..c9fbb830c8 100755
--- a/test/functional/p2p_fingerprint.py
+++ b/test/functional/p2p_fingerprint.py
@@ -90,7 +90,7 @@ class P2PFingerprintTest(BitcoinTestFramework):
# Force reorg to a longer chain
node0.send_message(msg_headers(new_blocks))
- node0.wait_for_getdata()
+ node0.wait_for_getdata([x.sha256 for x in new_blocks])
for block in new_blocks:
node0.send_and_ping(msg_block(block))
diff --git a/test/functional/p2p_invalid_block.py b/test/functional/p2p_invalid_block.py
index 905534b862..e280a62997 100755
--- a/test/functional/p2p_invalid_block.py
+++ b/test/functional/p2p_invalid_block.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2018 The Bitcoin Core developers
+# Copyright (c) 2015-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 node responses to invalid blocks.
@@ -22,7 +22,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
- self.extra_args = [["-whitelist=127.0.0.1"]]
+ self.extra_args = [["-whitelist=noban@127.0.0.1"]]
def run_test(self):
# Add p2p connection to node0
diff --git a/test/functional/p2p_invalid_locator.py b/test/functional/p2p_invalid_locator.py
index 33b7060060..0155eb21f0 100755
--- a/test/functional/p2p_invalid_locator.py
+++ b/test/functional/p2p_invalid_locator.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2018 The Bitcoin Core developers
+# Copyright (c) 2015-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 node responses to invalid locators.
@@ -34,7 +34,7 @@ class InvalidLocatorTest(BitcoinTestFramework):
msg.locator.vHave = [int(node.getblockhash(i - 1), 16) for i in range(block_count, block_count - (MAX_LOCATOR_SZ), -1)]
node.p2p.send_message(msg)
if type(msg) == msg_getheaders:
- node.p2p.wait_for_header(int(node.getbestblockhash(), 16))
+ node.p2p.wait_for_header(node.getbestblockhash())
else:
node.p2p.wait_for_block(int(node.getbestblockhash(), 16))
diff --git a/test/functional/p2p_invalid_messages.py b/test/functional/p2p_invalid_messages.py
index 9876d749ff..4bd832e8f7 100755
--- a/test/functional/p2p_invalid_messages.py
+++ b/test/functional/p2p_invalid_messages.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 node responses to invalid network messages."""
@@ -8,14 +8,18 @@ import struct
import sys
from test_framework import messages
-from test_framework.mininode import P2PDataStore, NetworkThread
+from test_framework.mininode import (
+ NetworkThread,
+ P2PDataStore,
+ P2PInterface,
+)
from test_framework.test_framework import BitcoinTestFramework
class msg_unrecognized:
"""Nonsensical message. Modeled after similar types in test_framework.messages."""
- command = b'badmsg'
+ msgtype = b'badmsg'
def __init__(self, *, str_data):
self.str_data = str_data.encode() if not isinstance(str_data, bytes) else str_data
@@ -24,7 +28,7 @@ class msg_unrecognized:
return messages.ser_string(self.str_data)
def __repr__(self):
- return "{}(data={})".format(self.command, self.str_data)
+ return "{}(data={})".format(self.msgtype, self.str_data)
class InvalidMessagesTest(BitcoinTestFramework):
@@ -46,7 +50,8 @@ class InvalidMessagesTest(BitcoinTestFramework):
self.test_magic_bytes()
self.test_checksum()
self.test_size()
- self.test_command()
+ self.test_msgtype()
+ self.test_large_inv()
node = self.nodes[0]
self.node = node
@@ -140,7 +145,6 @@ class InvalidMessagesTest(BitcoinTestFramework):
# Node is still up.
conn = node.add_p2p_connection(P2PDataStore())
- conn.sync_with_ping()
def test_magic_bytes(self):
conn = self.nodes[0].add_p2p_connection(P2PDataStore())
@@ -164,7 +168,7 @@ class InvalidMessagesTest(BitcoinTestFramework):
msg = conn.build_message(msg_unrecognized(str_data="d"))
cut_len = (
4 + # magic
- 12 + # command
+ 12 + # msgtype
4 #len
)
# modify checksum
@@ -179,7 +183,7 @@ class InvalidMessagesTest(BitcoinTestFramework):
msg = conn.build_message(msg_unrecognized(str_data="d"))
cut_len = (
4 + # magic
- 12 # command
+ 12 # msgtype
)
# modify len to MAX_SIZE + 1
msg = msg[:cut_len] + struct.pack("<I", 0x02000000 + 1) + msg[cut_len + 4:]
@@ -187,18 +191,31 @@ class InvalidMessagesTest(BitcoinTestFramework):
conn.wait_for_disconnect(timeout=1)
self.nodes[0].disconnect_p2ps()
- def test_command(self):
+ def test_msgtype(self):
conn = self.nodes[0].add_p2p_connection(P2PDataStore())
with self.nodes[0].assert_debug_log(['PROCESSMESSAGE: ERRORS IN HEADER']):
msg = msg_unrecognized(str_data="d")
- msg.command = b'\xff' * 12
+ msg.msgtype = b'\xff' * 12
msg = conn.build_message(msg)
- # Modify command
+ # Modify msgtype
msg = msg[:7] + b'\x00' + msg[7 + 1:]
self.nodes[0].p2p.send_raw_message(msg)
conn.sync_with_ping(timeout=1)
self.nodes[0].disconnect_p2ps()
+ def test_large_inv(self):
+ conn = self.nodes[0].add_p2p_connection(P2PInterface())
+ with self.nodes[0].assert_debug_log(['Misbehaving', 'peer=4 (0 -> 20): message inv size() = 50001']):
+ msg = messages.msg_inv([messages.CInv(1, 1)] * 50001)
+ conn.send_and_ping(msg)
+ with self.nodes[0].assert_debug_log(['Misbehaving', 'peer=4 (20 -> 40): message getdata size() = 50001']):
+ msg = messages.msg_getdata([messages.CInv(1, 1)] * 50001)
+ conn.send_and_ping(msg)
+ with self.nodes[0].assert_debug_log(['Misbehaving', 'peer=4 (40 -> 60): headers message size = 2001']):
+ msg = messages.msg_headers([messages.CBlockHeader()] * 2001)
+ conn.send_and_ping(msg)
+ self.nodes[0].disconnect_p2ps()
+
def _tweak_msg_data_size(self, message, wrong_size):
"""
Return a raw message based on another message but with an incorrect data size in
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index 5975a52b2a..c70a892463 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 node responses to invalid transactions.
@@ -118,6 +118,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
tx_orphan_2_invalid = CTransaction()
tx_orphan_2_invalid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 2)))
tx_orphan_2_invalid.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_orphan_2_invalid.calc_sha256()
self.log.info('Send the orphans ... ')
# Send valid orphan txs from p2ps[0]
@@ -148,6 +149,22 @@ class InvalidTxRequestTest(BitcoinTestFramework):
wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
assert_equal(expected_mempool, set(node.getrawmempool()))
+ self.log.info('Test orphan pool overflow')
+ orphan_tx_pool = [CTransaction() for _ in range(101)]
+ for i in range(len(orphan_tx_pool)):
+ orphan_tx_pool[i].vin.append(CTxIn(outpoint=COutPoint(i, 333)))
+ orphan_tx_pool[i].vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+
+ with node.assert_debug_log(['mapOrphan overflow, removed 1 tx']):
+ node.p2p.send_txs_and_test(orphan_tx_pool, node, success=False)
+
+ rejected_parent = CTransaction()
+ rejected_parent.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_2_invalid.sha256, 0)))
+ rejected_parent.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ rejected_parent.rehash()
+ with node.assert_debug_log(['not keeping orphan with rejected parents {}'.format(rejected_parent.hash)]):
+ node.p2p.send_txs_and_test([rejected_parent], node, success=False)
+
if __name__ == '__main__':
InvalidTxRequestTest().main()
diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py
index 06049db54c..157af68203 100755
--- a/test/functional/p2p_leak.py
+++ b/test/functional/p2p_leak.py
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2019 The Bitcoin Core developers
+# Copyright (c) 2017-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 message sending before handshake completion.
-A node should never send anything other than VERSION/VERACK/REJECT until it's
+A node should never send anything other than VERSION/VERACK until it's
received a VERACK.
This test connects to a node and sends it a few messages, trying to entice it
@@ -12,13 +12,23 @@ into sending us something it shouldn't."""
import time
-from test_framework.messages import msg_getaddr, msg_ping, msg_verack
+from test_framework.messages import (
+ msg_getaddr,
+ msg_ping,
+ msg_verack,
+ msg_version,
+)
from test_framework.mininode import mininode_lock, P2PInterface
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import wait_until
+from test_framework.util import (
+ assert_equal,
+ assert_greater_than_or_equal,
+ wait_until,
+)
banscore = 10
+
class CLazyNode(P2PInterface):
def __init__(self):
super().__init__()
@@ -27,14 +37,13 @@ class CLazyNode(P2PInterface):
def bad_message(self, message):
self.unexpected_msg = True
- self.log.info("should not have received message: %s" % message.command)
+ self.log.info("should not have received message: %s" % message.msgtype)
def on_open(self):
self.ever_connected = True
def on_version(self, message): self.bad_message(message)
def on_verack(self, message): self.bad_message(message)
- def on_reject(self, message): self.bad_message(message)
def on_inv(self, message): self.bad_message(message)
def on_addr(self, message): self.bad_message(message)
def on_getdata(self, message): self.bad_message(message)
@@ -64,8 +73,6 @@ class CNodeNoVersionBan(CLazyNode):
for i in range(banscore):
self.send_message(msg_verack())
- def on_reject(self, message): pass
-
# Node that never sends a version. This one just sits idle and hopes to receive
# any message (it shouldn't!)
class CNodeNoVersionIdle(CLazyNode):
@@ -78,7 +85,6 @@ class CNodeNoVerackIdle(CLazyNode):
self.version_received = False
super().__init__()
- def on_reject(self, message): pass
def on_verack(self, message): pass
# When version is received, don't reply with a verack. Instead, see if the
# node will give us a message that it shouldn't. This is not an exhaustive
@@ -88,6 +94,15 @@ class CNodeNoVerackIdle(CLazyNode):
self.send_message(msg_ping())
self.send_message(msg_getaddr())
+
+class P2PVersionStore(P2PInterface):
+ version_received = None
+
+ def on_version(self, msg):
+ super().on_version(msg)
+ self.version_received = msg
+
+
class P2PLeakTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
@@ -96,7 +111,11 @@ class P2PLeakTest(BitcoinTestFramework):
def run_test(self):
no_version_bannode = self.nodes[0].add_p2p_connection(CNodeNoVersionBan(), send_version=False, wait_for_verack=False)
no_version_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVersionIdle(), send_version=False, wait_for_verack=False)
- no_verack_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVerackIdle())
+ no_verack_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVerackIdle(), wait_for_verack=False)
+
+ # Wait until we got the verack in response to the version. Though, don't wait for the other node to receive the
+ # verack, since we never sent one
+ no_verack_idlenode.wait_for_verack()
wait_until(lambda: no_version_bannode.ever_connected, timeout=10, lock=mininode_lock)
wait_until(lambda: no_version_idlenode.ever_connected, timeout=10, lock=mininode_lock)
@@ -121,6 +140,26 @@ class P2PLeakTest(BitcoinTestFramework):
assert no_version_idlenode.unexpected_msg == False
assert no_verack_idlenode.unexpected_msg == False
+ self.log.info('Check that the version message does not leak the local address of the node')
+ p2p_version_store = self.nodes[0].add_p2p_connection(P2PVersionStore())
+ ver = p2p_version_store.version_received
+ # Check that received time is within one hour of now
+ assert_greater_than_or_equal(ver.nTime, time.time() - 3600)
+ assert_greater_than_or_equal(time.time() + 3600, ver.nTime)
+ assert_equal(ver.addrFrom.port, 0)
+ assert_equal(ver.addrFrom.ip, '0.0.0.0')
+ assert_equal(ver.nStartingHeight, 201)
+ assert_equal(ver.nRelay, 1)
+
+ self.log.info('Check that old nodes are disconnected')
+ p2p_old_node = self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False)
+ old_version_msg = msg_version()
+ old_version_msg.nVersion = 31799
+ wait_until(lambda: p2p_old_node.is_connected)
+ with self.nodes[0].assert_debug_log(['peer=4 using obsolete version 31799; disconnecting']):
+ p2p_old_node.send_message(old_version_msg)
+ p2p_old_node.wait_for_disconnect()
+
if __name__ == '__main__':
P2PLeakTest().main()
diff --git a/test/functional/p2p_leak_tx.py b/test/functional/p2p_leak_tx.py
index dc4d475b2d..6b3436fa5f 100755
--- a/test/functional/p2p_leak_tx.py
+++ b/test/functional/p2p_leak_tx.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2018 The Bitcoin Core developers
+# Copyright (c) 2017-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 that we don't leak txs to inbound peers that we haven't yet announced to"""
@@ -39,8 +39,7 @@ class P2PLeakTxTest(BitcoinTestFramework):
want_tx = msg_getdata()
want_tx.inv.append(CInv(t=1, h=int(txid, 16)))
inbound_peer.last_message.pop('notfound', None)
- inbound_peer.send_message(want_tx)
- inbound_peer.sync_with_ping()
+ inbound_peer.send_and_ping(want_tx)
if inbound_peer.last_message.get('notfound'):
self.log.debug('tx {} was not yet announced to us.'.format(txid))
diff --git a/test/functional/p2p_permissions.py b/test/functional/p2p_permissions.py
index 93e2957fd0..2c200fccad 100755
--- a/test/functional/p2p_permissions.py
+++ b/test/functional/p2p_permissions.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 p2p permission message.
@@ -132,6 +132,16 @@ class P2PPermissionsTests(BitcoinTestFramework):
p2p_rebroadcast_wallet.send_txs_and_test([tx], self.nodes[1])
wait_until(lambda: txid in self.nodes[0].getrawmempool())
+ self.log.debug("Check that node[1] will not send an invalid tx to node[0]")
+ tx.vout[0].nValue += 1
+ txid = tx.rehash()
+ p2p_rebroadcast_wallet.send_txs_and_test(
+ [tx],
+ self.nodes[1],
+ success=False,
+ reject_reason='Not relaying non-mempool transaction {} from whitelisted peer=0'.format(txid),
+ )
+
def checkpermission(self, args, expectedPermissions, whitelisted):
self.restart_node(1, args)
connect_nodes(self.nodes[0], 1)
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 3223c27e0b..6fb0fec32b 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2019 The Bitcoin Core developers
+# Copyright (c) 2016-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 segwit transactions and blocks on P2P network."""
@@ -125,8 +125,7 @@ def test_transaction_acceptance(node, p2p, tx, with_witness, accepted, reason=No
- use the getrawmempool rpc to check for acceptance."""
reason = [reason] if reason else []
with node.assert_debug_log(expected_msgs=reason):
- p2p.send_message(msg_tx(tx) if with_witness else msg_no_witness_tx(tx))
- p2p.sync_with_ping()
+ p2p.send_and_ping(msg_tx(tx) if with_witness else msg_no_witness_tx(tx))
assert_equal(tx.hash in node.getrawmempool(), accepted)
@@ -137,8 +136,7 @@ def test_witness_block(node, p2p, block, accepted, with_witness=True, reason=Non
- use the getbestblockhash rpc to check for acceptance."""
reason = [reason] if reason else []
with node.assert_debug_log(expected_msgs=reason):
- p2p.send_message(msg_block(block) if with_witness else msg_no_witness_block(block))
- p2p.sync_with_ping()
+ p2p.send_and_ping(msg_block(block) if with_witness else msg_no_witness_block(block))
assert_equal(node.getbestblockhash() == block.hash, accepted)
@@ -147,6 +145,11 @@ class TestP2PConn(P2PInterface):
super().__init__()
self.getdataset = set()
+ # Avoid sending out msg_getdata in the mininode thread as a reply to invs.
+ # They are not needed and would only lead to races because we send msg_getdata out in the test thread
+ def on_inv(self, message):
+ pass
+
def on_getdata(self, message):
for inv in message.inv:
self.getdataset.add(inv.hash)
@@ -156,7 +159,7 @@ class TestP2PConn(P2PInterface):
self.last_message.pop("getdata", None)
self.send_message(msg_inv(inv=[CInv(1, tx.sha256)]))
if success:
- self.wait_for_getdata(timeout)
+ self.wait_for_getdata([tx.sha256], timeout)
else:
time.sleep(timeout)
assert not self.last_message.get("getdata")
@@ -173,7 +176,7 @@ class TestP2PConn(P2PInterface):
self.send_message(msg_inv(inv=[CInv(2, block.sha256)]))
self.wait_for_getheaders()
self.send_message(msg)
- self.wait_for_getdata()
+ self.wait_for_getdata([block.sha256])
def request_block(self, blockhash, inv_type, timeout=60):
with mininode_lock:
@@ -188,9 +191,9 @@ class SegWitTest(BitcoinTestFramework):
self.num_nodes = 3
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
self.extra_args = [
- ["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT)],
- ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT)],
- ["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-segwitheight=-1"]
+ ["-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT), "-whitelist=noban@127.0.0.1"],
+ ["-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT)],
+ ["-acceptnonstdtxn=1", "-segwitheight=-1"],
]
self.supports_cli = False
@@ -298,8 +301,7 @@ class SegWitTest(BitcoinTestFramework):
block = self.build_next_block(version=1)
block.solve()
- self.test_node.send_message(msg_no_witness_block(block))
- self.test_node.sync_with_ping() # make sure the block was processed
+ self.test_node.send_and_ping(msg_no_witness_block(block)) # make sure the block was processed
txid = block.vtx[0].sha256
self.nodes[0].generate(99) # let the block mature
@@ -314,8 +316,7 @@ class SegWitTest(BitcoinTestFramework):
# This is a sanity check of our testing framework.
assert_equal(msg_no_witness_tx(tx).serialize(), msg_tx(tx).serialize())
- self.test_node.send_message(msg_tx(tx))
- self.test_node.sync_with_ping() # make sure the tx was processed
+ self.test_node.send_and_ping(msg_tx(tx)) # make sure the block was processed
assert tx.hash in self.nodes[0].getrawmempool()
# Save this transaction for later
self.utxo.append(UTXO(tx.sha256, 0, 49 * 100000000))
@@ -345,8 +346,7 @@ class SegWitTest(BitcoinTestFramework):
# But it should not be permanently marked bad...
# Resend without witness information.
- self.test_node.send_message(msg_no_witness_block(block))
- self.test_node.sync_with_ping()
+ self.test_node.send_and_ping(msg_no_witness_block(block)) # make sure the block was processed
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
# Update our utxo list; we spent the first entry.
@@ -862,13 +862,13 @@ class SegWitTest(BitcoinTestFramework):
# We can't send over the p2p network, because this is too big to relay
# TODO: repeat this test with a block that can be relayed
- self.nodes[0].submitblock(block.serialize().hex())
+ assert_equal('bad-witness-nonce-size', self.nodes[0].submitblock(block.serialize().hex()))
assert self.nodes[0].getbestblockhash() != block.hash
block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.pop()
assert get_virtual_size(block) < MAX_BLOCK_BASE_SIZE
- self.nodes[0].submitblock(block.serialize().hex())
+ assert_equal(None, self.nodes[0].submitblock(block.serialize().hex()))
assert self.nodes[0].getbestblockhash() == block.hash
@@ -975,14 +975,14 @@ class SegWitTest(BitcoinTestFramework):
add_witness_commitment(block, nonce=1)
block.vtx[0].wit = CTxWitness() # drop the nonce
block.solve()
- self.nodes[0].submitblock(block.serialize().hex())
+ assert_equal('bad-witness-merkle-match', self.nodes[0].submitblock(block.serialize().hex()))
assert self.nodes[0].getbestblockhash() != block.hash
# Now redo commitment with the standard nonce, but let bitcoind fill it in.
add_witness_commitment(block, nonce=0)
block.vtx[0].wit = CTxWitness()
block.solve()
- self.nodes[0].submitblock(block.serialize().hex())
+ assert_equal(None, self.nodes[0].submitblock(block.serialize().hex()))
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
# This time, add a tx with non-empty witness, but don't supply
@@ -997,7 +997,7 @@ class SegWitTest(BitcoinTestFramework):
block_2.vtx[0].vout.pop()
block_2.vtx[0].wit = CTxWitness()
- self.nodes[0].submitblock(block_2.serialize().hex())
+ assert_equal('bad-txnmrklroot', self.nodes[0].submitblock(block_2.serialize().hex()))
# Tip should not advance!
assert self.nodes[0].getbestblockhash() != block_2.hash
@@ -1896,12 +1896,12 @@ class SegWitTest(BitcoinTestFramework):
def test_upgrade_after_activation(self):
"""Test the behavior of starting up a segwit-aware node after the softfork has activated."""
- # Restart with the new binary
self.stop_node(2)
self.start_node(2, extra_args=["-segwitheight={}".format(SEGWIT_HEIGHT)])
connect_nodes(self.nodes[0], 2)
- self.sync_blocks()
+ # We reconnect more than 100 blocks, give it plenty of time
+ self.sync_blocks(timeout=240)
# Make sure that this peer thinks segwit has activated.
assert softfork_active(self.nodes[2], 'segwit')
@@ -2049,16 +2049,14 @@ class SegWitTest(BitcoinTestFramework):
tx = FromHex(CTransaction(), raw)
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
with self.nodes[0].assert_debug_log(['Superfluous witness record']):
- self.nodes[0].p2p.send_message(msg_bogus_tx(tx))
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.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())
with self.nodes[0].assert_debug_log(['Unknown transaction optional data']):
- self.nodes[0].p2p.send_message(msg_bogus_tx(tx))
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.send_and_ping(msg_bogus_tx(tx))
if __name__ == '__main__':
diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py
index 161b67e6d0..a8fba306a7 100755
--- a/test/functional/p2p_sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 behavior of headers messages to announce blocks.
@@ -144,13 +144,6 @@ class BaseNode(P2PInterface):
getblocks_message.locator.vHave = locator
self.send_message(getblocks_message)
- def wait_for_getdata(self, hash_list, timeout=60):
- if hash_list == []:
- return
-
- test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
-
def wait_for_block_announcement(self, block_hash, timeout=60):
test_function = lambda: self.last_blockhash_announced == block_hash
wait_until(test_function, timeout=timeout, lock=mininode_lock)
@@ -243,10 +236,6 @@ class SendHeadersTest(BitcoinTestFramework):
# will occur outside of direct fetching
test_node = self.nodes[0].add_p2p_connection(BaseNode(), services=NODE_WITNESS)
- # Ensure verack's have been processed by our peer
- inv_node.sync_with_ping()
- test_node.sync_with_ping()
-
self.test_null_locators(test_node, inv_node)
self.test_nonnull_locators(test_node, inv_node)
@@ -307,8 +296,7 @@ class SendHeadersTest(BitcoinTestFramework):
new_block.solve()
test_node.send_header_for_blocks([new_block])
test_node.wait_for_getdata([new_block.sha256])
- test_node.send_message(msg_block(new_block))
- test_node.sync_with_ping() # make sure this block is processed
+ test_node.send_and_ping(msg_block(new_block)) # make sure this block is processed
wait_until(lambda: inv_node.block_announced, timeout=60, lock=mininode_lock)
inv_node.clear_block_announcements()
test_node.clear_block_announcements()
diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py
index 02ceec3dc1..5a4fa42988 100755
--- a/test/functional/p2p_timeouts.py
+++ b/test/functional/p2p_timeouts.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2018 The Bitcoin Core developers
+# Copyright (c) 2016-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 various net timeouts.
@@ -27,11 +27,13 @@ from test_framework.messages import msg_ping
from test_framework.mininode import P2PInterface
from test_framework.test_framework import BitcoinTestFramework
+
class TestP2PConn(P2PInterface):
def on_version(self, message):
# Don't send a verack in response
pass
+
class TimeoutsTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
@@ -41,10 +43,14 @@ class TimeoutsTest(BitcoinTestFramework):
def run_test(self):
# Setup the p2p connections
- no_verack_node = self.nodes[0].add_p2p_connection(TestP2PConn())
+ no_verack_node = self.nodes[0].add_p2p_connection(TestP2PConn(), wait_for_verack=False)
no_version_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False, wait_for_verack=False)
no_send_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False, wait_for_verack=False)
+ # Wait until we got the verack in response to the version. Though, don't wait for the other node to receive the
+ # verack, since we never sent one
+ no_verack_node.wait_for_verack()
+
sleep(1)
assert no_verack_node.is_connected
@@ -81,5 +87,6 @@ class TimeoutsTest(BitcoinTestFramework):
assert not no_version_node.is_connected
assert not no_send_node.is_connected
+
if __name__ == '__main__':
TimeoutsTest().main()
diff --git a/test/functional/p2p_tx_download.py b/test/functional/p2p_tx_download.py
index aada04f66f..a999fba818 100755
--- a/test/functional/p2p_tx_download.py
+++ b/test/functional/p2p_tx_download.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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.
"""
@@ -65,8 +65,7 @@ class TxDownloadTest(BitcoinTestFramework):
self.log.info("Announce the txid from each incoming peer to node 0")
msg = msg_inv([CInv(t=1, h=txid)])
for p in self.nodes[0].p2ps:
- p.send_message(msg)
- p.sync_with_ping()
+ p.send_and_ping(msg)
outstanding_peer_index = [i for i in range(len(self.nodes[0].p2ps))]
@@ -107,8 +106,7 @@ class TxDownloadTest(BitcoinTestFramework):
"Announce the transaction to all nodes from all {} incoming peers, but never send it".format(NUM_INBOUND))
msg = msg_inv([CInv(t=1, h=txid)])
for p in self.peers:
- p.send_message(msg)
- p.sync_with_ping()
+ p.send_and_ping(msg)
self.log.info("Put the tx in node 0's mempool")
self.nodes[0].sendrawtransaction(tx)
@@ -154,6 +152,10 @@ class TxDownloadTest(BitcoinTestFramework):
wait_until(lambda: p.tx_getdata_count == MAX_GETDATA_IN_FLIGHT + 2)
self.nodes[0].setmocktime(0)
+ def test_spurious_notfound(self):
+ self.log.info('Check that spurious notfound is ignored')
+ self.nodes[0].p2ps[0].send_message(msg_notfound(vec=[CInv(1, 1)]))
+
def run_test(self):
# Setup the p2p connections
self.peers = []
@@ -163,6 +165,8 @@ class TxDownloadTest(BitcoinTestFramework):
self.log.info("Nodes are setup with {} incoming connections each".format(NUM_INBOUND))
+ self.test_spurious_notfound()
+
# Test the in-flight max first, because we want no transactions in
# flight ahead of this test.
self.test_in_flight_max()
diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py
index 534d275c28..3aaf4b9977 100755
--- a/test/functional/p2p_unrequested_blocks.py
+++ b/test/functional/p2p_unrequested_blocks.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 processing of unrequested blocks.
@@ -97,11 +97,9 @@ class AcceptBlockTest(BitcoinTestFramework):
blocks_h2.append(create_block(tips[i], create_coinbase(2), block_time))
blocks_h2[i].solve()
block_time += 1
- test_node.send_message(msg_block(blocks_h2[0]))
- min_work_node.send_message(msg_block(blocks_h2[1]))
+ test_node.send_and_ping(msg_block(blocks_h2[0]))
+ min_work_node.send_and_ping(msg_block(blocks_h2[1]))
- for x in [test_node, min_work_node]:
- x.sync_with_ping()
assert_equal(self.nodes[0].getblockcount(), 2)
assert_equal(self.nodes[1].getblockcount(), 1)
self.log.info("First height 2 block accepted by node0; correctly rejected by node1")
@@ -110,9 +108,8 @@ class AcceptBlockTest(BitcoinTestFramework):
block_h1f = create_block(int("0x" + self.nodes[0].getblockhash(0), 0), create_coinbase(1), block_time)
block_time += 1
block_h1f.solve()
- test_node.send_message(msg_block(block_h1f))
+ test_node.send_and_ping(msg_block(block_h1f))
- test_node.sync_with_ping()
tip_entry_found = False
for x in self.nodes[0].getchaintips():
if x['hash'] == block_h1f.hash:
@@ -125,9 +122,8 @@ class AcceptBlockTest(BitcoinTestFramework):
block_h2f = create_block(block_h1f.sha256, create_coinbase(2), block_time)
block_time += 1
block_h2f.solve()
- test_node.send_message(msg_block(block_h2f))
+ test_node.send_and_ping(msg_block(block_h2f))
- test_node.sync_with_ping()
# Since the earlier block was not processed by node, the new block
# can't be fully validated.
tip_entry_found = False
@@ -144,9 +140,8 @@ class AcceptBlockTest(BitcoinTestFramework):
# 4b. Now send another block that builds on the forking chain.
block_h3 = create_block(block_h2f.sha256, create_coinbase(3), block_h2f.nTime+1)
block_h3.solve()
- test_node.send_message(msg_block(block_h3))
+ test_node.send_and_ping(msg_block(block_h3))
- test_node.sync_with_ping()
# Since the earlier block was not processed by node, the new block
# can't be fully validated.
tip_entry_found = False
@@ -172,8 +167,7 @@ class AcceptBlockTest(BitcoinTestFramework):
tip = next_block
# Now send the block at height 5 and check that it wasn't accepted (missing header)
- test_node.send_message(msg_block(all_blocks[1]))
- test_node.sync_with_ping()
+ test_node.send_and_ping(msg_block(all_blocks[1]))
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getblock, all_blocks[1].hash)
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getblockheader, all_blocks[1].hash)
@@ -181,8 +175,7 @@ class AcceptBlockTest(BitcoinTestFramework):
headers_message = msg_headers()
headers_message.headers.append(CBlockHeader(all_blocks[0]))
test_node.send_message(headers_message)
- test_node.send_message(msg_block(all_blocks[1]))
- test_node.sync_with_ping()
+ test_node.send_and_ping(msg_block(all_blocks[1]))
self.nodes[0].getblock(all_blocks[1].hash)
# Now send the blocks in all_blocks
@@ -207,9 +200,7 @@ class AcceptBlockTest(BitcoinTestFramework):
test_node = self.nodes[0].add_p2p_connection(P2PInterface())
- test_node.send_message(msg_block(block_h1f))
-
- test_node.sync_with_ping()
+ test_node.send_and_ping(msg_block(block_h1f))
assert_equal(self.nodes[0].getblockcount(), 2)
self.log.info("Unrequested block that would complete more-work chain was ignored")
@@ -230,9 +221,7 @@ class AcceptBlockTest(BitcoinTestFramework):
self.log.info("Inv at tip triggered getdata for unprocessed block")
# 7. Send the missing block for the third time (now it is requested)
- test_node.send_message(msg_block(block_h1f))
-
- test_node.sync_with_ping()
+ test_node.send_and_ping(msg_block(block_h1f))
assert_equal(self.nodes[0].getblockcount(), 290)
self.nodes[0].getblock(all_blocks[286].hash)
assert_equal(self.nodes[0].getbestblockhash(), all_blocks[286].hash)
@@ -259,9 +248,8 @@ class AcceptBlockTest(BitcoinTestFramework):
headers_message.headers.append(CBlockHeader(block_290f))
headers_message.headers.append(CBlockHeader(block_291))
headers_message.headers.append(CBlockHeader(block_292))
- test_node.send_message(headers_message)
+ test_node.send_and_ping(headers_message)
- test_node.sync_with_ping()
tip_entry_found = False
for x in self.nodes[0].getchaintips():
if x['hash'] == block_292.hash:
@@ -271,9 +259,8 @@ class AcceptBlockTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "Block not found on disk", self.nodes[0].getblock, block_292.hash)
test_node.send_message(msg_block(block_289f))
- test_node.send_message(msg_block(block_290f))
+ test_node.send_and_ping(msg_block(block_290f))
- test_node.sync_with_ping()
self.nodes[0].getblock(block_289f.hash)
self.nodes[0].getblock(block_290f.hash)
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index adf6f1ca4f..6273c229ae 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 RPCs related to blockchainstate.
@@ -315,8 +315,7 @@ class BlockchainTest(BitcoinTestFramework):
def solve_and_send_block(prevhash, height, time):
b = create_block(prevhash, create_coinbase(height), time)
b.solve()
- node.p2p.send_message(msg_block(b))
- node.p2p.sync_with_ping()
+ node.p2p.send_and_ping(msg_block(b))
return b
b21f = solve_and_send_block(int(b20hash, 16), 21, b20['time'] + 1)
diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py
index aa7f12848c..56e9ecfcc2 100755
--- a/test/functional/rpc_createmultisig.py
+++ b/test/functional/rpc_createmultisig.py
@@ -4,13 +4,14 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test multisig RPCs"""
-from test_framework.descriptors import descsum_create
+from test_framework.authproxy import JSONRPCException
+from test_framework.descriptors import descsum_create, drop_origins
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_raises_rpc_error,
assert_equal,
)
-from test_framework.key import ECPubKey
+from test_framework.key import ECPubKey, ECKey, bytes_to_wif
import binascii
import decimal
@@ -28,10 +29,14 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def get_keys(self):
+ self.pub = []
+ self.priv = []
node0, node1, node2 = self.nodes
- add = [node1.getnewaddress() for _ in range(self.nkeys)]
- self.pub = [node1.getaddressinfo(a)["pubkey"] for a in add]
- self.priv = [node1.dumpprivkey(a) for a in add]
+ for _ in range(self.nkeys):
+ k = ECKey()
+ k.generate()
+ self.pub.append(k.get_pubkey().get_bytes().hex())
+ self.priv.append(bytes_to_wif(k.get_bytes(), k.is_compressed))
self.final = node2.getnewaddress()
def run_test(self):
@@ -64,17 +69,20 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
pk_obj.compressed = False
pk2 = binascii.hexlify(pk_obj.get_bytes()).decode()
+ node0.createwallet(wallet_name='wmulti0', disable_private_keys=True)
+ wmulti0 = node0.get_wallet_rpc('wmulti0')
+
# Check all permutations of keys because order matters apparently
for keys in itertools.permutations([pk0, pk1, pk2]):
# Results should be the same as this legacy one
legacy_addr = node0.createmultisig(2, keys, 'legacy')['address']
- assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'legacy')['address'])
+ assert_equal(legacy_addr, wmulti0.addmultisigaddress(2, keys, '', 'legacy')['address'])
# Generate addresses with the segwit types. These should all make legacy addresses
- assert_equal(legacy_addr, node0.createmultisig(2, keys, 'bech32')['address'])
- assert_equal(legacy_addr, node0.createmultisig(2, keys, 'p2sh-segwit')['address'])
- assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'bech32')['address'])
- assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'p2sh-segwit')['address'])
+ assert_equal(legacy_addr, wmulti0.createmultisig(2, keys, 'bech32')['address'])
+ assert_equal(legacy_addr, wmulti0.createmultisig(2, keys, 'p2sh-segwit')['address'])
+ assert_equal(legacy_addr, wmulti0.addmultisigaddress(2, keys, '', 'bech32')['address'])
+ assert_equal(legacy_addr, wmulti0.addmultisigaddress(2, keys, '', 'p2sh-segwit')['address'])
self.log.info('Testing sortedmulti descriptors with BIP 67 test vectors')
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_bip67.json'), encoding='utf-8') as f:
@@ -89,6 +97,8 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
assert_equal(self.nodes[0].deriveaddresses(sorted_key_desc)[0], t['address'])
def check_addmultisigaddress_errors(self):
+ if self.options.descriptors:
+ return
self.log.info('Check that addmultisigaddress fails when the private keys are missing')
addresses = [self.nodes[1].getnewaddress(address_type='legacy') for _ in range(2)]
assert_raises_rpc_error(-5, 'no full public key for address', lambda: self.nodes[0].addmultisigaddress(nrequired=1, keys=addresses))
@@ -115,17 +125,38 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
def do_multisig(self):
node0, node1, node2 = self.nodes
+ if 'wmulti' not in node1.listwallets():
+ try:
+ node1.loadwallet('wmulti')
+ except JSONRPCException as e:
+ if e.error['code'] == -18 and 'Wallet wmulti not found' in e.error['message']:
+ node1.createwallet(wallet_name='wmulti', disable_private_keys=True)
+ else:
+ raise
+ wmulti = node1.get_wallet_rpc('wmulti')
+
+ # Construct the expected descriptor
+ desc = 'multi({},{})'.format(self.nsigs, ','.join(self.pub))
+ if self.output_type == 'legacy':
+ desc = 'sh({})'.format(desc)
+ elif self.output_type == 'p2sh-segwit':
+ desc = 'sh(wsh({}))'.format(desc)
+ elif self.output_type == 'bech32':
+ desc = 'wsh({})'.format(desc)
+ desc = descsum_create(desc)
msig = node2.createmultisig(self.nsigs, self.pub, self.output_type)
madd = msig["address"]
mredeem = msig["redeemScript"]
+ assert_equal(desc, msig['descriptor'])
if self.output_type == 'bech32':
assert madd[0:4] == "bcrt" # actually a bech32 address
# compare against addmultisigaddress
- msigw = node1.addmultisigaddress(self.nsigs, self.pub, None, self.output_type)
+ msigw = wmulti.addmultisigaddress(self.nsigs, self.pub, None, self.output_type)
maddw = msigw["address"]
mredeemw = msigw["redeemScript"]
+ assert_equal(desc, drop_origins(msigw['descriptor']))
# addmultisigiaddress and createmultisig work the same
assert maddw == madd
assert mredeemw == mredeem
@@ -182,6 +213,8 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
txinfo = node0.getrawtransaction(tx, True, blk)
self.log.info("n/m=%d/%d %s size=%d vsize=%d weight=%d" % (self.nsigs, self.nkeys, self.output_type, txinfo["size"], txinfo["vsize"], txinfo["weight"]))
+ wmulti.unloadwallet()
+
if __name__ == '__main__':
RpcCreateMultiSigTest().main()
diff --git a/test/functional/rpc_dumptxoutset.py b/test/functional/rpc_dumptxoutset.py
index 7527bdfb08..e65787ce08 100755
--- a/test/functional/rpc_dumptxoutset.py
+++ b/test/functional/rpc_dumptxoutset.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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 the generation of UTXO snapshots using `dumptxoutset`.
@@ -25,7 +25,7 @@ class DumptxoutsetTest(BitcoinTestFramework):
FILENAME = 'txoutset.dat'
out = node.dumptxoutset(FILENAME)
- expected_path = Path(node.datadir) / 'regtest' / FILENAME
+ expected_path = Path(node.datadir) / self.chain / FILENAME
assert expected_path.is_file()
diff --git a/test/functional/rpc_estimatefee.py b/test/functional/rpc_estimatefee.py
new file mode 100755
index 0000000000..1fff9e1512
--- /dev/null
+++ b/test/functional/rpc_estimatefee.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+# 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.
+"""Test the estimatefee RPCs.
+
+Test the following RPCs:
+ - estimatesmartfee
+ - estimaterawfee
+"""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_raises_rpc_error
+
+class EstimateFeeTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+
+ def run_test(self):
+ # missing required params
+ assert_raises_rpc_error(-1, "estimatesmartfee", self.nodes[0].estimatesmartfee)
+ assert_raises_rpc_error(-1, "estimaterawfee", self.nodes[0].estimaterawfee)
+
+ # wrong type for conf_target
+ assert_raises_rpc_error(-3, "Expected type number, got string", self.nodes[0].estimatesmartfee, 'foo')
+ assert_raises_rpc_error(-3, "Expected type number, got string", self.nodes[0].estimaterawfee, 'foo')
+
+ # 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')
+
+ # wrong type for estimaterawfee(threshold)
+ assert_raises_rpc_error(-3, "Expected type number, got string", self.nodes[0].estimaterawfee, 1, 'foo')
+
+ # extra params
+ assert_raises_rpc_error(-1, "estimatesmartfee", self.nodes[0].estimatesmartfee, 1, 'ECONOMICAL', 1)
+ assert_raises_rpc_error(-1, "estimaterawfee", self.nodes[0].estimaterawfee, 1, 1, 1)
+
+ # valid calls
+ self.nodes[0].estimatesmartfee(1)
+ # self.nodes[0].estimatesmartfee(1, None)
+ self.nodes[0].estimatesmartfee(1, 'ECONOMICAL')
+
+ self.nodes[0].estimaterawfee(1)
+ self.nodes[0].estimaterawfee(1, None)
+ self.nodes[0].estimaterawfee(1, 1)
+
+
+if __name__ == '__main__':
+ EstimateFeeTest().main()
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 6f1ae0d3ba..4bc4913bda 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 the fundrawtransaction RPC."""
@@ -30,7 +30,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.setup_clean_chain = True
# This test isn't testing tx relay. Set whitelist on the peers for
# instant tx relay.
- self.extra_args = [['-whitelist=127.0.0.1']] * self.num_nodes
+ self.extra_args = [['-whitelist=noban@127.0.0.1']] * self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -500,11 +500,16 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[1].getnewaddress()
self.nodes[1].getrawchangeaddress()
inputs = []
- outputs = {self.nodes[0].getnewaddress():1.1}
+ outputs = {self.nodes[0].getnewaddress():1.09999500}
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
+ # fund a transaction that does not require a new key for the change output
+ self.nodes[1].fundrawtransaction(rawtx)
+
# fund a transaction that requires a new key for the change output
# creating the key must be impossible because the wallet is locked
- assert_raises_rpc_error(-4, "Keypool ran out, please call keypoolrefill first", self.nodes[1].fundrawtransaction, rawtx)
+ outputs = {self.nodes[0].getnewaddress():1.1}
+ rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
+ assert_raises_rpc_error(-4, "Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.", self.nodes[1].fundrawtransaction, rawtx)
# Refill the keypool.
self.nodes[1].walletpassphrase("test", 100)
diff --git a/test/functional/rpc_generateblock.py b/test/functional/rpc_generateblock.py
new file mode 100755
index 0000000000..aa58c0af9d
--- /dev/null
+++ b/test/functional/rpc_generateblock.py
@@ -0,0 +1,106 @@
+#!/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 generateblock rpc.
+'''
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
+
+
+class GenerateBlockTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def run_test(self):
+ node = self.nodes[0]
+
+ self.log.info('Generate an empty block to address')
+ address = node.getnewaddress()
+ hash = node.generateblock(output=address, transactions=[])['hash']
+ block = node.getblock(blockhash=hash, verbose=2)
+ assert_equal(len(block['tx']), 1)
+ assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)
+
+ self.log.info('Generate an empty block to a descriptor')
+ hash = node.generateblock('addr(' + address + ')', [])['hash']
+ block = node.getblock(blockhash=hash, verbosity=2)
+ assert_equal(len(block['tx']), 1)
+ assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)
+
+ self.log.info('Generate an empty block to a combo descriptor with compressed pubkey')
+ combo_key = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
+ combo_address = 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080'
+ hash = node.generateblock('combo(' + combo_key + ')', [])['hash']
+ block = node.getblock(hash, 2)
+ assert_equal(len(block['tx']), 1)
+ assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], combo_address)
+
+ self.log.info('Generate an empty block to a combo descriptor with uncompressed pubkey')
+ combo_key = '0408ef68c46d20596cc3f6ddf7c8794f71913add807f1dc55949fa805d764d191c0b7ce6894c126fce0babc6663042f3dde9b0cf76467ea315514e5a6731149c67'
+ combo_address = 'mkc9STceoCcjoXEXe6cm66iJbmjM6zR9B2'
+ hash = node.generateblock('combo(' + combo_key + ')', [])['hash']
+ block = node.getblock(hash, 2)
+ assert_equal(len(block['tx']), 1)
+ assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], combo_address)
+
+ # Generate 110 blocks to spend
+ node.generatetoaddress(110, address)
+
+ # Generate some extra mempool transactions to verify they don't get mined
+ for i in range(10):
+ node.sendtoaddress(address, 0.001)
+
+ self.log.info('Generate block with txid')
+ txid = node.sendtoaddress(address, 1)
+ hash = node.generateblock(address, [txid])['hash']
+ block = node.getblock(hash, 1)
+ assert_equal(len(block['tx']), 2)
+ assert_equal(block['tx'][1], txid)
+
+ self.log.info('Generate block with raw tx')
+ utxos = node.listunspent(addresses=[address])
+ raw = node.createrawtransaction([{'txid':utxos[0]['txid'], 'vout':utxos[0]['vout']}],[{address:1}])
+ signed_raw = node.signrawtransactionwithwallet(raw)['hex']
+ hash = node.generateblock(address, [signed_raw])['hash']
+ block = node.getblock(hash, 1)
+ assert_equal(len(block['tx']), 2)
+ txid = block['tx'][1]
+ assert_equal(node.gettransaction(txid)['hex'], signed_raw)
+
+ self.log.info('Fail to generate block with out of order txs')
+ raw1 = node.createrawtransaction([{'txid':txid, 'vout':0}],[{address:0.9999}])
+ signed_raw1 = node.signrawtransactionwithwallet(raw1)['hex']
+ txid1 = node.sendrawtransaction(signed_raw1)
+ raw2 = node.createrawtransaction([{'txid':txid1, 'vout':0}],[{address:0.999}])
+ signed_raw2 = node.signrawtransactionwithwallet(raw2)['hex']
+ assert_raises_rpc_error(-25, 'TestBlockValidity failed: bad-txns-inputs-missingorspent', node.generateblock, address, [signed_raw2, txid1])
+
+ self.log.info('Fail to generate block with txid not in mempool')
+ missing_txid = '0000000000000000000000000000000000000000000000000000000000000000'
+ assert_raises_rpc_error(-5, 'Transaction ' + missing_txid + ' not in mempool.', node.generateblock, address, [missing_txid])
+
+ self.log.info('Fail to generate block with invalid raw tx')
+ invalid_raw_tx = '0000'
+ assert_raises_rpc_error(-22, 'Transaction decode failed for ' + invalid_raw_tx, node.generateblock, address, [invalid_raw_tx])
+
+ self.log.info('Fail to generate block with invalid address/descriptor')
+ assert_raises_rpc_error(-5, 'Invalid address or descriptor', node.generateblock, '1234', [])
+
+ self.log.info('Fail to generate block with a ranged descriptor')
+ ranged_descriptor = 'pkh(tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp/0/*)'
+ assert_raises_rpc_error(-8, 'Ranged descriptor not accepted. Maybe pass through deriveaddresses first?', node.generateblock, ranged_descriptor, [])
+
+ self.log.info('Fail to generate block with a descriptor missing a private key')
+ child_descriptor = 'pkh(tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp/0\'/0)'
+ assert_raises_rpc_error(-5, 'Cannot derive script without private keys', node.generateblock, child_descriptor, [])
+
+if __name__ == '__main__':
+ GenerateBlockTest().main()
diff --git a/test/functional/rpc_getaddressinfo_label_deprecation.py b/test/functional/rpc_getaddressinfo_label_deprecation.py
index 5e739ebede..4c6b2fe5cf 100755
--- a/test/functional/rpc_getaddressinfo_label_deprecation.py
+++ b/test/functional/rpc_getaddressinfo_label_deprecation.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2020 The Bitcoin Core developers
+# Copyright (c) 2020-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.
"""
diff --git a/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py b/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py
index 3f2e8dee18..903f5536b9 100755
--- a/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py
+++ b/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2020-2019 The Bitcoin Core developers
+# 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.
"""
diff --git a/test/functional/rpc_getdescriptorinfo.py b/test/functional/rpc_getdescriptorinfo.py
new file mode 100755
index 0000000000..977dc805ef
--- /dev/null
+++ b/test/functional/rpc_getdescriptorinfo.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test getdescriptorinfo RPC.
+"""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.descriptors import descsum_create
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
+
+
+class DescriptorTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+ self.extra_args = [["-disablewallet"]]
+
+ def test_desc(self, desc, isrange, issolvable, hasprivatekeys):
+ info = self.nodes[0].getdescriptorinfo(desc)
+ assert_equal(info, self.nodes[0].getdescriptorinfo(descsum_create(desc)))
+ assert_equal(info['descriptor'], descsum_create(desc))
+ assert_equal(info['isrange'], isrange)
+ assert_equal(info['issolvable'], issolvable)
+ assert_equal(info['hasprivatekeys'], hasprivatekeys)
+
+ def run_test(self):
+ assert_raises_rpc_error(-1, 'getdescriptorinfo', self.nodes[0].getdescriptorinfo)
+ assert_raises_rpc_error(-3, 'Expected type string', self.nodes[0].getdescriptorinfo, 1)
+ assert_raises_rpc_error(-5, 'is not a valid descriptor function', self.nodes[0].getdescriptorinfo, '')
+
+ # P2PK output with the specified public key.
+ self.test_desc('pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)', isrange=False, issolvable=True, hasprivatekeys=False)
+ # P2PKH output with the specified public key.
+ self.test_desc('pkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)', isrange=False, issolvable=True, hasprivatekeys=False)
+ # P2WPKH output with the specified public key.
+ self.test_desc('wpkh(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9)', isrange=False, issolvable=True, hasprivatekeys=False)
+ # P2SH-P2WPKH output with the specified public key.
+ self.test_desc('sh(wpkh(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))', isrange=False, issolvable=True, hasprivatekeys=False)
+ # Any P2PK, P2PKH, P2WPKH, or P2SH-P2WPKH output with the specified public key.
+ self.test_desc('combo(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)', isrange=False, issolvable=True, hasprivatekeys=False)
+ # An (overly complicated) P2SH-P2WSH-P2PKH output with the specified public key.
+ self.test_desc('sh(wsh(pkh(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)))', isrange=False, issolvable=True, hasprivatekeys=False)
+ # A bare *1-of-2* multisig output with keys in the specified order.
+ self.test_desc('multi(1,022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)', isrange=False, issolvable=True, hasprivatekeys=False)
+ # A P2SH *2-of-2* multisig output with keys in the specified order.
+ self.test_desc('sh(multi(2,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))', isrange=False, issolvable=True, hasprivatekeys=False)
+ # A P2WSH *2-of-3* multisig output with keys in the specified order.
+ self.test_desc('wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))', isrange=False, issolvable=True, hasprivatekeys=False)
+ # A P2SH-P2WSH *1-of-3* multisig output with keys in the specified order.
+ self.test_desc('sh(wsh(multi(1,03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8,03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)))', isrange=False, issolvable=True, hasprivatekeys=False)
+ # A P2PK output with the public key of the specified xpub.
+ self.test_desc('pk(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B)', isrange=False, issolvable=True, hasprivatekeys=False)
+ # A P2PKH output with child key *1'/2* of the specified xpub.
+ self.test_desc("pkh(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1'/2)", isrange=False, issolvable=True, hasprivatekeys=False)
+ # 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'`.
+ self.test_desc("pkh([d34db33f/44'/0'/0']tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/*)", isrange=True, issolvable=True, hasprivatekeys=False)
+ # 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).
+ self.test_desc("wsh(multi(1,tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/0/*,tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/0/0/*))", isrange=True, issolvable=True, hasprivatekeys=False)
+
+
+if __name__ == '__main__':
+ DescriptorTest().main()
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 33af819d34..51d136d26a 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
"""Test the Partially Signed Transaction RPCs.
@@ -48,18 +48,23 @@ class PSBTTest(BitcoinTestFramework):
disconnect_nodes(offline_node, 2)
disconnect_nodes(mining_node, 0)
+ # Create watchonly on online_node
+ online_node.createwallet(wallet_name='wonline', disable_private_keys=True)
+ wonline = online_node.get_wallet_rpc('wonline')
+ w2 = online_node.get_wallet_rpc('')
+
# Mine a transaction that credits the offline address
offline_addr = offline_node.getnewaddress(address_type="p2sh-segwit")
- online_addr = online_node.getnewaddress(address_type="p2sh-segwit")
- online_node.importaddress(offline_addr, "", False)
+ online_addr = w2.getnewaddress(address_type="p2sh-segwit")
+ wonline.importaddress(offline_addr, "", False)
mining_node.sendtoaddress(address=offline_addr, amount=1.0)
mining_node.generate(nblocks=1)
self.sync_blocks([mining_node, online_node])
# Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO)
- utxos = online_node.listunspent(addresses=[offline_addr])
- raw = online_node.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}])
- psbt = online_node.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"]
+ utxos = wonline.listunspent(addresses=[offline_addr])
+ raw = wonline.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}])
+ psbt = wonline.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"]
assert "non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0]
# Have the offline node sign the PSBT (which will update the UTXO to segwit)
@@ -72,6 +77,8 @@ class PSBTTest(BitcoinTestFramework):
self.sync_blocks([mining_node, online_node])
assert_equal(online_node.gettxout(txid,0)["confirmations"], 1)
+ wonline.unloadwallet()
+
# Reconnect
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[0], 2)
@@ -89,13 +96,23 @@ class PSBTTest(BitcoinTestFramework):
final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex']
self.nodes[0].sendrawtransaction(final_tx)
- # Create p2sh, p2wpkh, and p2wsh addresses
+ # Get pubkeys
pubkey0 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())['pubkey']
pubkey1 = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
pubkey2 = self.nodes[2].getaddressinfo(self.nodes[2].getnewaddress())['pubkey']
- p2sh = self.nodes[1].addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "legacy")['address']
- p2wsh = self.nodes[1].addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "bech32")['address']
- p2sh_p2wsh = self.nodes[1].addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "p2sh-segwit")['address']
+
+ # Setup watchonly wallets
+ self.nodes[2].createwallet(wallet_name='wmulti', disable_private_keys=True)
+ wmulti = self.nodes[2].get_wallet_rpc('wmulti')
+
+ # Create all the addresses
+ p2sh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "legacy")['address']
+ p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "bech32")['address']
+ p2sh_p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "p2sh-segwit")['address']
+ if not self.options.descriptors:
+ wmulti.importaddress(p2sh)
+ wmulti.importaddress(p2wsh)
+ wmulti.importaddress(p2sh_p2wsh)
p2wpkh = self.nodes[1].getnewaddress("", "bech32")
p2pkh = self.nodes[1].getnewaddress("", "legacy")
p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit")
@@ -146,11 +163,14 @@ class PSBTTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "Fee exceeds maximum configured by -maxtxfee", 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})
# partially sign multisig things with node 1
- psbtx = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wsh_pos},{"txid":txid,"vout":p2sh_pos},{"txid":txid,"vout":p2sh_p2wsh_pos}], {self.nodes[1].getnewaddress():29.99})['psbt']
+ 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)
psbtx = walletprocesspsbt_out['psbt']
assert_equal(walletprocesspsbt_out['complete'], False)
+ # Unload wmulti, we don't need it anymore
+ wmulti.unloadwallet()
+
# partially sign with node 2. This should be complete and sendable
walletprocesspsbt_out = self.nodes[2].walletprocesspsbt(psbtx)
assert_equal(walletprocesspsbt_out['complete'], True)
@@ -193,12 +213,20 @@ class PSBTTest(BitcoinTestFramework):
psbt_orig = self.nodes[0].createpsbt([{"txid":txid1, "vout":vout1}, {"txid":txid2, "vout":vout2}], {self.nodes[0].getnewaddress():25.999})
# Update psbts, should only have data for one input and not the other
- psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig)['psbt']
+ psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig, False, "ALL")['psbt']
psbt1_decoded = self.nodes[0].decodepsbt(psbt1)
assert psbt1_decoded['inputs'][0] and not psbt1_decoded['inputs'][1]
- psbt2 = self.nodes[2].walletprocesspsbt(psbt_orig)['psbt']
+ # Check that BIP32 path was added
+ assert "bip32_derivs" in psbt1_decoded['inputs'][0]
+ psbt2 = self.nodes[2].walletprocesspsbt(psbt_orig, False, "ALL", False)['psbt']
psbt2_decoded = self.nodes[0].decodepsbt(psbt2)
assert not psbt2_decoded['inputs'][0] and psbt2_decoded['inputs'][1]
+ # Check that BIP32 paths were not added
+ assert "bip32_derivs" not in psbt2_decoded['inputs'][1]
+
+ # Sign PSBTs (workaround issue #18039)
+ psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig)['psbt']
+ psbt2 = self.nodes[2].walletprocesspsbt(psbt_orig)['psbt']
# Combine, finalize, and send the psbts
combined = self.nodes[0].combinepsbt([psbt1, psbt2])
@@ -231,16 +259,18 @@ class PSBTTest(BitcoinTestFramework):
# Same construction without optional arguments
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}])
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
- for tx_in in decoded_psbt["tx"]["vin"]:
+ for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
+ assert "bip32_derivs" in psbt_in
assert_equal(decoded_psbt["tx"]["locktime"], 0)
# Same construction without optional arguments, for a node with -walletrbf=0
unspent1 = self.nodes[1].listunspent()[0]
psbtx_info = self.nodes[1].walletcreatefundedpsbt([{"txid":unspent1["txid"], "vout":unspent1["vout"]}], [{self.nodes[2].getnewaddress():unspent1["amount"]+1}], block_height)
decoded_psbt = self.nodes[1].decodepsbt(psbtx_info["psbt"])
- for tx_in in decoded_psbt["tx"]["vin"]:
+ for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
assert_greater_than(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
+ assert "bip32_derivs" in psbt_in
# Make sure change address wallet does not have P2SH innerscript access to results in success
# when attempting BnB coin selection
@@ -287,7 +317,7 @@ class PSBTTest(BitcoinTestFramework):
# Signer tests
for i, signer in enumerate(signers):
- self.nodes[2].createwallet("wallet{}".format(i))
+ self.nodes[2].createwallet(wallet_name="wallet{}".format(i))
wrpc = self.nodes[2].get_wallet_rpc("wallet{}".format(i))
for key in signer['privkeys']:
wrpc.importprivkey(key)
@@ -427,6 +457,10 @@ class PSBTTest(BitcoinTestFramework):
assert_equal(analysis['next'], 'creator')
assert_equal(analysis['error'], 'PSBT is not valid. Input 0 has invalid value')
+ self.log.info("PSBT with signed, but not finalized, inputs should have Finalizer as next")
+ analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAZYezcxdnbXoQCmrD79t/LzDgtUo9ERqixk8wgioAobrAAAAAAD9////AlDDAAAAAAAAFgAUy/UxxZuzZswcmFnN/E9DGSiHLUsuGPUFAAAAABYAFLsH5o0R38wXx+X2cCosTMCZnQ4baAAAAAABAR8A4fUFAAAAABYAFOBI2h5thf3+Lflb2LGCsVSZwsltIgIC/i4dtVARCRWtROG0HHoGcaVklzJUcwo5homgGkSNAnJHMEQCIGx7zKcMIGr7cEES9BR4Kdt/pzPTK3fKWcGyCJXb7MVnAiALOBgqlMH4GbC1HDh/HmylmO54fyEy4lKde7/BT/PWxwEBAwQBAAAAIgYC/i4dtVARCRWtROG0HHoGcaVklzJUcwo5homgGkSNAnIYDwVpQ1QAAIABAACAAAAAgAAAAAAAAAAAAAAiAgL+CIiB59NSCssOJRGiMYQK1chahgAaaJpIXE41Cyir+xgPBWlDVAAAgAEAAIAAAACAAQAAAAAAAAAA')
+ assert_equal(analysis['next'], 'finalizer')
+
analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAfA00BFgAm6tp86RowwH6BMImQNL5zXUcTT97XoLGz0BAAAAAAD/////AgCAgWrj0AcAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAR8A8gUqAQAAABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA')
assert_equal(analysis['next'], 'creator')
assert_equal(analysis['error'], 'PSBT is not valid. Output amount invalid')
diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py
index c3d34be0dd..861b394e70 100755
--- a/test/functional/rpc_scantxoutset.py
+++ b/test/functional/rpc_scantxoutset.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
"""Test the scantxoutset rpc call."""
diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py
index 780758e219..3d08202724 100755
--- a/test/functional/rpc_signrawtransaction.py
+++ b/test/functional/rpc_signrawtransaction.py
@@ -1,13 +1,14 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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 transaction signing using the signrawtransaction* RPCs."""
+from test_framework.address import check_script, script_to_p2sh
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal, assert_raises_rpc_error, hex_str_to_bytes
+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
+from test_framework.script import CScript, OP_0, OP_CHECKSIG
from decimal import Decimal
@@ -26,6 +27,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
1) The transaction has a complete set of signatures
2) No script verification error occurred"""
+ self.log.info("Test valid raw transaction with one input")
privKeys = ['cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N', 'cVKpPfVKSJxKqVpE9awvXNWuLHCa5j5tiE7K6zbUSptFpTEtiFrA']
inputs = [
@@ -48,7 +50,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
assert 'errors' not in rawTxSigned
def test_with_lock_outputs(self):
- """Test correct error reporting when trying to sign a locked output"""
+ self.log.info("Test correct error reporting when trying to sign a locked output")
self.nodes[0].encryptwallet("password")
rawTx = '020000000156b958f78e3f24e0b2f4e4db1255426b0902027cb37e3ddadb52e37c3557dddb0000000000ffffffff01c0a6b929010000001600149a2ee8c77140a053f36018ac8124a6ececc1668a00000000'
@@ -64,6 +66,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
4) Two script verification errors occurred
5) Script verification errors have certain properties ("txid", "vout", "scriptSig", "sequence", "error")
6) The verification errors refer to the invalid (vin 1) and missing input (vin 2)"""
+ self.log.info("Test script verification errors")
privKeys = ['cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N']
inputs = [
@@ -146,7 +149,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
assert not rawTxSigned['errors'][0]['witness']
def witness_script_test(self):
- # Now test signing transaction to P2SH-P2WSH addresses without wallet
+ 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"])
@@ -168,6 +171,33 @@ class SignRawTransactionsTest(BitcoinTestFramework):
assert 'complete' in spending_tx_signed
assert_equal(spending_tx_signed['complete'], True)
+ # Now test with P2PKH and P2PK scripts as the witnessScript
+ for tx_type in ['P2PKH', 'P2PK']: # these tests are order-independent
+ self.verify_txn_with_witness_script(tx_type)
+
+ def verify_txn_with_witness_script(self, tx_type):
+ self.log.info("Test with a {} script as the witnessScript".format(tx_type))
+ embedded_addr_info = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress('', 'legacy'))
+ embedded_privkey = self.nodes[1].dumpprivkey(embedded_addr_info['address'])
+ witness_script = {
+ 'P2PKH': embedded_addr_info['scriptPubKey'],
+ 'P2PK': CScript([hex_str_to_bytes(embedded_addr_info['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)
+ script_pub_key = self.nodes[1].validateaddress(addr)['scriptPubKey']
+ # Fund that address
+ txid = self.nodes[0].sendtoaddress(addr, 10)
+ vout = find_vout_for_address(self.nodes[0], txid, addr)
+ self.nodes[0].generate(1)
+ # Now create and sign a transaction spending that output on node[0], which doesn't know the scripts or keys
+ spending_tx = self.nodes[0].createrawtransaction([{'txid': txid, 'vout': vout}], {self.nodes[1].getnewaddress(): Decimal("9.999")})
+ spending_tx_signed = self.nodes[0].signrawtransactionwithkey(spending_tx, [embedded_privkey], [{'txid': txid, 'vout': vout, 'scriptPubKey': script_pub_key, 'redeemScript': redeem_script, 'witnessScript': witness_script, 'amount': 10}])
+ # Check the signing completed successfully
+ assert 'complete' in spending_tx_signed
+ assert_equal(spending_tx_signed['complete'], True)
+ self.nodes[0].sendrawtransaction(spending_tx_signed['hex'])
+
def run_test(self):
self.successful_signing_test()
self.script_verification_error_test()
diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py
index 6a7e91216a..8f410f233e 100644
--- a/test/functional/test_framework/address.py
+++ b/test/functional/test_framework/address.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2019 The Bitcoin Core developers
+# Copyright (c) 2016-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.
"""Encode and decode BASE58, P2PKH and P2SH addresses."""
diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py
index 4ba6ac1db2..05308931e3 100644
--- a/test/functional/test_framework/authproxy.py
+++ b/test/functional/test_framework/authproxy.py
@@ -101,23 +101,26 @@ class AuthServiceProxy():
if os.name == 'nt':
# Windows somehow does not like to re-use connections
# TODO: Find out why the connection would disconnect occasionally and make it reusable on Windows
+ # Avoid "ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine"
self._set_conn()
try:
self.__conn.request(method, path, postdata, headers)
return self._get_response()
- except http.client.BadStatusLine as e:
- if e.line == "''": # if connection was closed, try again
+ except (BrokenPipeError, ConnectionResetError):
+ # Python 3.5+ raises BrokenPipeError when the connection was reset
+ # ConnectionResetError happens on FreeBSD
+ self.__conn.close()
+ self.__conn.request(method, path, postdata, headers)
+ return self._get_response()
+ except OSError as e:
+ retry = (
+ '[WinError 10053] An established connection was aborted by the software in your host machine' in str(e))
+ if retry:
self.__conn.close()
self.__conn.request(method, path, postdata, headers)
return self._get_response()
else:
raise
- except (BrokenPipeError, ConnectionResetError):
- # Python 3.5+ raises BrokenPipeError instead of BadStatusLine when the connection was reset
- # ConnectionResetError happens on FreeBSD with Python 3.4
- self.__conn.close()
- self.__conn.request(method, path, postdata, headers)
- return self._get_response()
def get_request(self, *args, **argsn):
AuthServiceProxy.__id_count += 1
diff --git a/test/functional/test_framework/bignum.py b/test/functional/test_framework/bignum.py
deleted file mode 100644
index db5ccd62c2..0000000000
--- a/test/functional/test_framework/bignum.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-#
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Big number routines.
-
-This file is copied from python-bitcoinlib.
-"""
-
-import struct
-
-
-# generic big endian MPI format
-
-def bn_bytes(v, have_ext=False):
- ext = 0
- if have_ext:
- ext = 1
- return ((v.bit_length()+7)//8) + ext
-
-def bn2bin(v):
- s = bytearray()
- i = bn_bytes(v)
- while i > 0:
- s.append((v >> ((i-1) * 8)) & 0xff)
- i -= 1
- return s
-
-def bn2mpi(v):
- have_ext = False
- if v.bit_length() > 0:
- have_ext = (v.bit_length() & 0x07) == 0
-
- neg = False
- if v < 0:
- neg = True
- v = -v
-
- s = struct.pack(b">I", bn_bytes(v, have_ext))
- ext = bytearray()
- if have_ext:
- ext.append(0)
- v_bin = bn2bin(v)
- if neg:
- if have_ext:
- ext[0] |= 0x80
- else:
- v_bin[0] |= 0x80
- return s + ext + v_bin
-
-# bitcoin-specific little endian format, with implicit size
-def mpi2vch(s):
- r = s[4:] # strip size
- r = r[::-1] # reverse string, converting BE->LE
- return r
-
-def bn2vch(v):
- return bytes(mpi2vch(bn2mpi(v)))
diff --git a/test/functional/test_framework/descriptors.py b/test/functional/test_framework/descriptors.py
index 29482ce01e..46b405749b 100644
--- a/test/functional/test_framework/descriptors.py
+++ b/test/functional/test_framework/descriptors.py
@@ -4,6 +4,8 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Utility functions related to output descriptors"""
+import re
+
INPUT_CHARSET = "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ "
CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
GENERATOR = [0xf5dee51989, 0xa9fdca3312, 0x1bab10e32d, 0x3706b1677a, 0x644d626ffd]
@@ -53,3 +55,10 @@ def descsum_check(s, require=True):
return False
symbols = descsum_expand(s[:-9]) + [CHECKSUM_CHARSET.find(x) for x in s[-8:]]
return descsum_polymod(symbols) == 1
+
+def drop_origins(s):
+ '''Drop the key origins from a descriptor'''
+ desc = re.sub(r'\[.+?\]', '', s)
+ if '#' in s:
+ desc = desc[:desc.index('#')]
+ return descsum_create(desc)
diff --git a/test/functional/test_framework/key.py b/test/functional/test_framework/key.py
index 912c0ca978..f2d6fba4a6 100644
--- a/test/functional/test_framework/key.py
+++ b/test/functional/test_framework/key.py
@@ -8,6 +8,8 @@ keys, and is trivially vulnerable to side channel attacks. Do not use for
anything but tests."""
import random
+from .address import byte_to_base58
+
def modinv(a, n):
"""Compute the modular inverse of a modulo n
@@ -384,3 +386,14 @@ class ECKey():
rb = r.to_bytes((r.bit_length() + 8) // 8, 'big')
sb = s.to_bytes((s.bit_length() + 8) // 8, 'big')
return b'\x30' + bytes([4 + len(rb) + len(sb), 2, len(rb)]) + rb + bytes([2, len(sb)]) + sb
+
+def bytes_to_wif(b, compressed=True):
+ if compressed:
+ b += b'\x01'
+ return byte_to_base58(b, 239)
+
+def generate_wif_key():
+ # Makes a WIF privkey for imports
+ k = ECKey()
+ k.generate()
+ return bytes_to_wif(k.get_bytes(), k.is_compressed)
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index 4f7a9a8b13..4855f62a8f 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# Copyright (c) 2010 ArtForz -- public domain half-a-node
# Copyright (c) 2012 Jeff Garzik
-# Copyright (c) 2010-2019 The Bitcoin Core developers
+# Copyright (c) 2010-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.
"""Bitcoin test framework primitive and message structures
@@ -37,8 +37,11 @@ MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version
MAX_LOCATOR_SZ = 101
MAX_BLOCK_BASE_SIZE = 1000000
+MAX_BLOOM_FILTER_SIZE = 36000
+MAX_BLOOM_HASH_FUNCS = 50
COIN = 100000000 # 1 btc in satoshis
+MAX_MONEY = 21000000 * COIN
BIP125_SEQUENCE_NUMBER = 0xfffffffd # Sequence number that is BIP 125 opt-in and BIP 68-opt-out
@@ -50,6 +53,7 @@ NODE_NETWORK_LIMITED = (1 << 10)
MSG_TX = 1
MSG_BLOCK = 2
+MSG_FILTERED_BLOCK = 3
MSG_WITNESS_FLAG = 1 << 30
MSG_TYPE_MASK = 0xffffffff >> 2
@@ -224,10 +228,11 @@ class CInv:
typemap = {
0: "Error",
- 1: "TX",
- 2: "Block",
- 1|MSG_WITNESS_FLAG: "WitnessTx",
- 2|MSG_WITNESS_FLAG : "WitnessBlock",
+ MSG_TX: "TX",
+ MSG_BLOCK: "Block",
+ MSG_TX | MSG_WITNESS_FLAG: "WitnessTx",
+ MSG_BLOCK | MSG_WITNESS_FLAG: "WitnessBlock",
+ MSG_FILTERED_BLOCK: "filtered Block",
4: "CompactBlock"
}
@@ -598,16 +603,16 @@ class CBlock(CBlockHeader):
__slots__ = ("vtx",)
def __init__(self, header=None):
- super(CBlock, self).__init__(header)
+ super().__init__(header)
self.vtx = []
def deserialize(self, f):
- super(CBlock, self).deserialize(f)
+ super().deserialize(f)
self.vtx = deser_vector(f, CTransaction)
def serialize(self, with_witness=True):
r = b""
- r += super(CBlock, self).serialize()
+ r += super().serialize()
if with_witness:
r += ser_vector(self.vtx, "serialize_with_witness")
else:
@@ -747,7 +752,7 @@ class P2PHeaderAndShortIDs:
class P2PHeaderAndShortWitnessIDs(P2PHeaderAndShortIDs):
__slots__ = ()
def serialize(self):
- return super(P2PHeaderAndShortWitnessIDs, self).serialize(with_witness=True)
+ return super().serialize(with_witness=True)
# Calculate the BIP 152-compact blocks shortid for a given transaction hash
def calculate_shortid(k0, k1, tx_hash):
@@ -943,7 +948,7 @@ class CMerkleBlock:
class msg_version:
__slots__ = ("addrFrom", "addrTo", "nNonce", "nRelay", "nServices",
"nStartingHeight", "nTime", "nVersion", "strSubVer")
- command = b"version"
+ msgtype = b"version"
def __init__(self):
self.nVersion = MY_VERSION
@@ -1001,7 +1006,7 @@ class msg_version:
class msg_verack:
__slots__ = ()
- command = b"verack"
+ msgtype = b"verack"
def __init__(self):
pass
@@ -1018,7 +1023,7 @@ class msg_verack:
class msg_addr:
__slots__ = ("addrs",)
- command = b"addr"
+ msgtype = b"addr"
def __init__(self):
self.addrs = []
@@ -1035,7 +1040,7 @@ class msg_addr:
class msg_inv:
__slots__ = ("inv",)
- command = b"inv"
+ msgtype = b"inv"
def __init__(self, inv=None):
if inv is None:
@@ -1055,7 +1060,7 @@ class msg_inv:
class msg_getdata:
__slots__ = ("inv",)
- command = b"getdata"
+ msgtype = b"getdata"
def __init__(self, inv=None):
self.inv = inv if inv is not None else []
@@ -1072,7 +1077,7 @@ class msg_getdata:
class msg_getblocks:
__slots__ = ("locator", "hashstop")
- command = b"getblocks"
+ msgtype = b"getblocks"
def __init__(self):
self.locator = CBlockLocator()
@@ -1096,7 +1101,7 @@ class msg_getblocks:
class msg_tx:
__slots__ = ("tx",)
- command = b"tx"
+ msgtype = b"tx"
def __init__(self, tx=CTransaction()):
self.tx = tx
@@ -1120,7 +1125,7 @@ class msg_no_witness_tx(msg_tx):
class msg_block:
__slots__ = ("block",)
- command = b"block"
+ msgtype = b"block"
def __init__(self, block=None):
if block is None:
@@ -1139,12 +1144,12 @@ class msg_block:
# for cases where a user needs tighter control over what is sent over the wire
-# note that the user must supply the name of the command, and the data
+# note that the user must supply the name of the msgtype, and the data
class msg_generic:
- __slots__ = ("command", "data")
+ __slots__ = ("msgtype", "data")
- def __init__(self, command, data=None):
- self.command = command
+ def __init__(self, msgtype, data=None):
+ self.msgtype = msgtype
self.data = data
def serialize(self):
@@ -1162,7 +1167,7 @@ class msg_no_witness_block(msg_block):
class msg_getaddr:
__slots__ = ()
- command = b"getaddr"
+ msgtype = b"getaddr"
def __init__(self):
pass
@@ -1179,7 +1184,7 @@ class msg_getaddr:
class msg_ping:
__slots__ = ("nonce",)
- command = b"ping"
+ msgtype = b"ping"
def __init__(self, nonce=0):
self.nonce = nonce
@@ -1198,7 +1203,7 @@ class msg_ping:
class msg_pong:
__slots__ = ("nonce",)
- command = b"pong"
+ msgtype = b"pong"
def __init__(self, nonce=0):
self.nonce = nonce
@@ -1217,7 +1222,7 @@ class msg_pong:
class msg_mempool:
__slots__ = ()
- command = b"mempool"
+ msgtype = b"mempool"
def __init__(self):
pass
@@ -1234,7 +1239,7 @@ class msg_mempool:
class msg_notfound:
__slots__ = ("vec", )
- command = b"notfound"
+ msgtype = b"notfound"
def __init__(self, vec=None):
self.vec = vec or []
@@ -1251,7 +1256,7 @@ class msg_notfound:
class msg_sendheaders:
__slots__ = ()
- command = b"sendheaders"
+ msgtype = b"sendheaders"
def __init__(self):
pass
@@ -1272,7 +1277,7 @@ class msg_sendheaders:
# hash_stop (hash of last desired block header, 0 to get as many as possible)
class msg_getheaders:
__slots__ = ("hashstop", "locator",)
- command = b"getheaders"
+ msgtype = b"getheaders"
def __init__(self):
self.locator = CBlockLocator()
@@ -1298,7 +1303,7 @@ class msg_getheaders:
# <count> <vector of block headers>
class msg_headers:
__slots__ = ("headers",)
- command = b"headers"
+ msgtype = b"headers"
def __init__(self, headers=None):
self.headers = headers if headers is not None else []
@@ -1317,10 +1322,94 @@ class msg_headers:
return "msg_headers(headers=%s)" % repr(self.headers)
+class msg_merkleblock:
+ __slots__ = ("merkleblock",)
+ msgtype = b"merkleblock"
+
+ def __init__(self, merkleblock=None):
+ if merkleblock is None:
+ self.merkleblock = CMerkleBlock()
+ else:
+ self.merkleblock = merkleblock
+
+ def deserialize(self, f):
+ self.merkleblock.deserialize(f)
+
+ def serialize(self):
+ return self.merkleblock.serialize()
+
+ def __repr__(self):
+ return "msg_merkleblock(merkleblock=%s)" % (repr(self.merkleblock))
+
+
+class msg_filterload:
+ __slots__ = ("data", "nHashFuncs", "nTweak", "nFlags")
+ msgtype = b"filterload"
+
+ def __init__(self, data=b'00', nHashFuncs=0, nTweak=0, nFlags=0):
+ self.data = data
+ self.nHashFuncs = nHashFuncs
+ self.nTweak = nTweak
+ self.nFlags = nFlags
+
+ def deserialize(self, f):
+ self.data = deser_string(f)
+ self.nHashFuncs = struct.unpack("<I", f.read(4))[0]
+ self.nTweak = struct.unpack("<I", f.read(4))[0]
+ self.nFlags = struct.unpack("<B", f.read(1))[0]
+
+ def serialize(self):
+ r = b""
+ r += ser_string(self.data)
+ r += struct.pack("<I", self.nHashFuncs)
+ r += struct.pack("<I", self.nTweak)
+ r += struct.pack("<B", self.nFlags)
+ return r
+
+ def __repr__(self):
+ return "msg_filterload(data={}, nHashFuncs={}, nTweak={}, nFlags={})".format(
+ self.data, self.nHashFuncs, self.nTweak, self.nFlags)
+
+
+class msg_filteradd:
+ __slots__ = ("data")
+ msgtype = b"filteradd"
+
+ def __init__(self, data):
+ self.data = data
+
+ def deserialize(self, f):
+ self.data = deser_string(f)
+
+ def serialize(self):
+ r = b""
+ r += ser_string(self.data)
+ return r
+
+ def __repr__(self):
+ return "msg_filteradd(data={})".format(self.data)
+
+
+class msg_filterclear:
+ __slots__ = ()
+ msgtype = b"filterclear"
+
+ def __init__(self):
+ pass
+
+ def deserialize(self, f):
+ pass
+
+ def serialize(self):
+ return b""
+
+ def __repr__(self):
+ return "msg_filterclear()"
+
class msg_feefilter:
__slots__ = ("feerate",)
- command = b"feefilter"
+ msgtype = b"feefilter"
def __init__(self, feerate=0):
self.feerate = feerate
@@ -1339,7 +1428,7 @@ class msg_feefilter:
class msg_sendcmpct:
__slots__ = ("announce", "version")
- command = b"sendcmpct"
+ msgtype = b"sendcmpct"
def __init__(self):
self.announce = False
@@ -1361,7 +1450,7 @@ class msg_sendcmpct:
class msg_cmpctblock:
__slots__ = ("header_and_shortids",)
- command = b"cmpctblock"
+ msgtype = b"cmpctblock"
def __init__(self, header_and_shortids = None):
self.header_and_shortids = header_and_shortids
@@ -1381,7 +1470,7 @@ class msg_cmpctblock:
class msg_getblocktxn:
__slots__ = ("block_txn_request",)
- command = b"getblocktxn"
+ msgtype = b"getblocktxn"
def __init__(self):
self.block_txn_request = None
@@ -1401,7 +1490,7 @@ class msg_getblocktxn:
class msg_blocktxn:
__slots__ = ("block_transactions",)
- command = b"blocktxn"
+ msgtype = b"blocktxn"
def __init__(self):
self.block_transactions = BlockTransactions()
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index a9e669fea9..31cec66ee7 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# Copyright (c) 2010 ArtForz -- public domain half-a-node
# Copyright (c) 2012 Jeff Garzik
-# Copyright (c) 2010-2019 The Bitcoin Core developers
+# Copyright (c) 2010-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.
"""Bitcoin P2P network half-a-node.
@@ -12,7 +12,10 @@ found in the mini-node branch of http://github.com/jgarzik/pynode.
P2PConnection: A low-level connection object to a node's P2P interface
P2PInterface: A high-level interface object for communicating to a node over P2P
P2PDataStore: A p2p interface class that keeps a store of transactions and blocks
- and can respond correctly to getdata and getheaders messages"""
+ and can respond correctly to getdata and getheaders messages
+P2PTxInvStore: A p2p interface class that inherits from P2PDataStore, and keeps
+ a count of how many times each txid has been announced."""
+
import asyncio
from collections import defaultdict
from io import BytesIO
@@ -30,6 +33,9 @@ from test_framework.messages import (
msg_blocktxn,
msg_cmpctblock,
msg_feefilter,
+ msg_filteradd,
+ msg_filterclear,
+ msg_filterload,
msg_getaddr,
msg_getblocks,
msg_getblocktxn,
@@ -38,6 +44,7 @@ from test_framework.messages import (
msg_headers,
msg_inv,
msg_mempool,
+ msg_merkleblock,
msg_notfound,
msg_ping,
msg_pong,
@@ -62,6 +69,9 @@ MESSAGEMAP = {
b"blocktxn": msg_blocktxn,
b"cmpctblock": msg_cmpctblock,
b"feefilter": msg_feefilter,
+ b"filteradd": msg_filteradd,
+ b"filterclear": msg_filterclear,
+ b"filterload": msg_filterload,
b"getaddr": msg_getaddr,
b"getblocks": msg_getblocks,
b"getblocktxn": msg_getblocktxn,
@@ -70,6 +80,7 @@ MESSAGEMAP = {
b"headers": msg_headers,
b"inv": msg_inv,
b"mempool": msg_mempool,
+ b"merkleblock": msg_merkleblock,
b"notfound": msg_notfound,
b"ping": msg_ping,
b"pong": msg_pong,
@@ -109,8 +120,9 @@ class P2PConnection(asyncio.Protocol):
def is_connected(self):
return self._transport is not None
- def peer_connect(self, dstaddr, dstport, *, net):
+ def peer_connect(self, dstaddr, dstport, *, net, factor):
assert not self.is_connected
+ self.factor = factor
self.dstaddr = dstaddr
self.dstport = dstport
# The initial message to send after the connection was made:
@@ -172,7 +184,7 @@ class P2PConnection(asyncio.Protocol):
raise ValueError("magic bytes mismatch: {} != {}".format(repr(self.magic_bytes), repr(self.recvbuf)))
if len(self.recvbuf) < 4 + 12 + 4 + 4:
return
- command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
+ msgtype = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
checksum = self.recvbuf[4+12+4:4+12+4+4]
if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen:
@@ -183,10 +195,10 @@ class P2PConnection(asyncio.Protocol):
if checksum != h[:4]:
raise ValueError("got bad checksum " + repr(self.recvbuf))
self.recvbuf = self.recvbuf[4+12+4+4+msglen:]
- if command not in MESSAGEMAP:
- raise ValueError("Received unknown command from %s:%d: '%s' %s" % (self.dstaddr, self.dstport, command, repr(msg)))
+ if msgtype not in MESSAGEMAP:
+ raise ValueError("Received unknown msgtype from %s:%d: '%s' %s" % (self.dstaddr, self.dstport, msgtype, repr(msg)))
f = BytesIO(msg)
- t = MESSAGEMAP[command]()
+ t = MESSAGEMAP[msgtype]()
t.deserialize(f)
self._log_message("receive", t)
self.on_message(t)
@@ -225,11 +237,11 @@ class P2PConnection(asyncio.Protocol):
def build_message(self, message):
"""Build a serialized P2P message"""
- command = message.command
+ msgtype = message.msgtype
data = message.serialize()
tmsg = self.magic_bytes
- tmsg += command
- tmsg += b"\x00" * (12 - len(command))
+ tmsg += msgtype
+ tmsg += b"\x00" * (12 - len(msgtype))
tmsg += struct.pack("<I", len(data))
th = sha256(data)
h = sha256(th)
@@ -296,10 +308,10 @@ class P2PInterface(P2PConnection):
and the most recent message of each type."""
with mininode_lock:
try:
- command = message.command.decode('ascii')
- self.message_count[command] += 1
- self.last_message[command] = message
- getattr(self, 'on_' + command)(message)
+ msgtype = message.msgtype.decode('ascii')
+ self.message_count[msgtype] += 1
+ self.last_message[msgtype] = message
+ getattr(self, 'on_' + msgtype)(message)
except:
print("ERROR delivering %s (%s)" % (repr(message), sys.exc_info()[0]))
raise
@@ -318,6 +330,9 @@ class P2PInterface(P2PConnection):
def on_blocktxn(self, message): pass
def on_cmpctblock(self, message): pass
def on_feefilter(self, message): pass
+ def on_filteradd(self, message): pass
+ def on_filterclear(self, message): pass
+ def on_filterload(self, message): pass
def on_getaddr(self, message): pass
def on_getblocks(self, message): pass
def on_getblocktxn(self, message): pass
@@ -325,9 +340,9 @@ class P2PInterface(P2PConnection):
def on_getheaders(self, message): pass
def on_headers(self, message): pass
def on_mempool(self, message): pass
+ def on_merkleblock(self, message): pass
def on_notfound(self, message): pass
def on_pong(self, message): pass
- def on_reject(self, message): pass
def on_sendcmpct(self, message): pass
def on_sendheaders(self, message): pass
def on_tx(self, message): pass
@@ -353,9 +368,12 @@ class P2PInterface(P2PConnection):
# Connection helper methods
+ def wait_until(self, test_function, timeout):
+ wait_until(test_function, timeout=timeout, lock=mininode_lock, factor=self.factor)
+
def wait_for_disconnect(self, timeout=60):
test_function = lambda: not self.is_connected
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
+ self.wait_until(test_function, timeout=timeout)
# Message receiving helper methods
@@ -366,14 +384,14 @@ class P2PInterface(P2PConnection):
return False
return self.last_message['tx'].tx.rehash() == txid
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
+ self.wait_until(test_function, timeout=timeout)
def wait_for_block(self, blockhash, timeout=60):
def test_function():
assert self.is_connected
return self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
+ self.wait_until(test_function, timeout=timeout)
def wait_for_header(self, blockhash, timeout=60):
def test_function():
@@ -381,23 +399,33 @@ class P2PInterface(P2PConnection):
last_headers = self.last_message.get('headers')
if not last_headers:
return False
- return last_headers.headers[0].rehash() == blockhash
+ return last_headers.headers[0].rehash() == int(blockhash, 16)
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
+ self.wait_until(test_function, timeout=timeout)
- def wait_for_getdata(self, timeout=60):
+ def wait_for_merkleblock(self, blockhash, timeout=60):
+ def test_function():
+ assert self.is_connected
+ last_filtered_block = self.last_message.get('merkleblock')
+ if not last_filtered_block:
+ return False
+ return last_filtered_block.merkleblock.header.rehash() == int(blockhash, 16)
+
+ self.wait_until(test_function, timeout=timeout)
+
+ def wait_for_getdata(self, hash_list, timeout=60):
"""Waits for a getdata message.
- Receiving any getdata message will satisfy the predicate. the last_message["getdata"]
- value must be explicitly cleared before calling this method, or this will return
- immediately with success. TODO: change this method to take a hash value and only
- return true if the correct block/tx has been requested."""
+ The object hashes in the inventory vector must match the provided hash_list."""
def test_function():
assert self.is_connected
- return self.last_message.get("getdata")
+ last_data = self.last_message.get("getdata")
+ if not last_data:
+ return False
+ return [x.hash for x in last_data.inv] == hash_list
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
+ self.wait_until(test_function, timeout=timeout)
def wait_for_getheaders(self, timeout=60):
"""Waits for a getheaders message.
@@ -411,7 +439,7 @@ class P2PInterface(P2PConnection):
assert self.is_connected
return self.last_message.get("getheaders")
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
+ self.wait_until(test_function, timeout=timeout)
def wait_for_inv(self, expected_inv, timeout=60):
"""Waits for an INV message and checks that the first inv object in the message was as expected."""
@@ -424,13 +452,13 @@ class P2PInterface(P2PConnection):
self.last_message["inv"].inv[0].type == expected_inv[0].type and \
self.last_message["inv"].inv[0].hash == expected_inv[0].hash
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
+ self.wait_until(test_function, timeout=timeout)
def wait_for_verack(self, timeout=60):
def test_function():
return self.message_count["verack"]
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
+ self.wait_until(test_function, timeout=timeout)
# Message sending helper functions
@@ -446,7 +474,7 @@ class P2PInterface(P2PConnection):
assert self.is_connected
return self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter
- wait_until(test_function, timeout=timeout, lock=mininode_lock)
+ self.wait_until(test_function, timeout=timeout)
self.ping_counter += 1
@@ -562,7 +590,7 @@ class P2PDataStore(P2PInterface):
self.send_message(msg_block(block=b))
else:
self.send_message(msg_headers([CBlockHeader(block) for block in blocks]))
- wait_until(lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout, lock=mininode_lock)
+ self.wait_until(lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout)
if expect_disconnect:
self.wait_for_disconnect(timeout=timeout)
@@ -570,7 +598,7 @@ class P2PDataStore(P2PInterface):
self.sync_with_ping(timeout=timeout)
if success:
- wait_until(lambda: node.getbestblockhash() == blocks[-1].hash, timeout=timeout)
+ self.wait_until(lambda: node.getbestblockhash() == blocks[-1].hash, timeout=timeout)
else:
assert node.getbestblockhash() != blocks[-1].hash
@@ -606,3 +634,20 @@ class P2PDataStore(P2PInterface):
# Check that none of the txs are now in the mempool
for tx in txs:
assert tx.hash not in raw_mempool, "{} tx found in mempool".format(tx.hash)
+
+class P2PTxInvStore(P2PInterface):
+ """A P2PInterface which stores a count of how many times each txid has been announced."""
+ def __init__(self):
+ super().__init__()
+ self.tx_invs_received = defaultdict(int)
+
+ def on_inv(self, message):
+ # Store how many times invs have been received for each tx.
+ for i in message.inv:
+ if i.type == MSG_TX:
+ # save txid
+ self.tx_invs_received[i.hash] += 1
+
+ def get_invs(self):
+ with mininode_lock:
+ return list(self.tx_invs_received.keys())
diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py
index 51aa9057f7..9102266456 100644
--- a/test/functional/test_framework/script.py
+++ b/test/functional/test_framework/script.py
@@ -1,26 +1,41 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2019 The Bitcoin Core developers
+# Copyright (c) 2015-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.
"""Functionality to build scripts, as well as signature hash functions.
This file is modified from python-bitcoinlib.
"""
-
-from .messages import CTransaction, CTxOut, sha256, hash256, uint256_from_str, ser_uint256, ser_string
-
import hashlib
import struct
-
-from .bignum import bn2vch
+import unittest
+
+from .messages import (
+ CTransaction,
+ CTxOut,
+ hash256,
+ ser_string,
+ ser_uint256,
+ sha256,
+ uint256_from_str,
+)
MAX_SCRIPT_ELEMENT_SIZE = 520
-
OPCODE_NAMES = {}
def hash160(s):
return hashlib.new('ripemd160', sha256(s)).digest()
+def bn2vch(v):
+ """Convert number to bitcoin-specific little endian format."""
+ # We need v.bit_length() bits, plus a sign bit for every nonzero number.
+ n_bits = v.bit_length() + (v != 0)
+ # The number of bytes for that is:
+ n_bytes = (n_bits + 7) // 8
+ # Convert number to absolute value + sign in top bit.
+ encoded_v = 0 if v == 0 else abs(v) | ((v < 0) << (n_bytes * 8 - 1))
+ # Serialize to bytes
+ return encoded_v.to_bytes(n_bytes, 'little')
_opcode_instances = []
class CScriptOp(int):
@@ -31,13 +46,13 @@ class CScriptOp(int):
def encode_op_pushdata(d):
"""Encode a PUSHDATA op, returning bytes"""
if len(d) < 0x4c:
- return b'' + bytes([len(d)]) + d # OP_PUSHDATA
+ return b'' + bytes([len(d)]) + d # OP_PUSHDATA
elif len(d) <= 0xff:
- return b'\x4c' + bytes([len(d)]) + d # OP_PUSHDATA1
+ return b'\x4c' + bytes([len(d)]) + d # OP_PUSHDATA1
elif len(d) <= 0xffff:
- return b'\x4d' + struct.pack(b'<H', len(d)) + d # OP_PUSHDATA2
+ return b'\x4d' + struct.pack(b'<H', len(d)) + d # OP_PUSHDATA2
elif len(d) <= 0xffffffff:
- return b'\x4e' + struct.pack(b'<I', len(d)) + d # OP_PUSHDATA4
+ return b'\x4e' + struct.pack(b'<I', len(d)) + d # OP_PUSHDATA4
else:
raise ValueError("Data too long to encode in a PUSHDATA op")
@@ -50,7 +65,7 @@ class CScriptOp(int):
if n == 0:
return OP_0
else:
- return CScriptOp(OP_1 + n-1)
+ return CScriptOp(OP_1 + n - 1)
def decode_op_n(self):
"""Decode a small integer opcode, returning an integer"""
@@ -60,7 +75,7 @@ class CScriptOp(int):
if not (self == OP_0 or OP_1 <= self <= OP_16):
raise ValueError('op %r is not an OP_N' % self)
- return int(self - OP_1+1)
+ return int(self - OP_1 + 1)
def is_small_int(self):
"""Return true if the op pushes a small integer to the stack"""
@@ -83,11 +98,11 @@ class CScriptOp(int):
return _opcode_instances[n]
except IndexError:
assert len(_opcode_instances) == n
- _opcode_instances.append(super(CScriptOp, cls).__new__(cls, n))
+ _opcode_instances.append(super().__new__(cls, n))
return _opcode_instances[n]
# Populate opcode instance table
-for n in range(0xff+1):
+for n in range(0xff + 1):
CScriptOp(n)
@@ -100,7 +115,7 @@ OP_PUSHDATA4 = CScriptOp(0x4e)
OP_1NEGATE = CScriptOp(0x4f)
OP_RESERVED = CScriptOp(0x50)
OP_1 = CScriptOp(0x51)
-OP_TRUE=OP_1
+OP_TRUE = OP_1
OP_2 = CScriptOp(0x52)
OP_3 = CScriptOp(0x53)
OP_4 = CScriptOp(0x54)
@@ -232,122 +247,122 @@ OP_PUBKEY = CScriptOp(0xfe)
OP_INVALIDOPCODE = CScriptOp(0xff)
OPCODE_NAMES.update({
- OP_0 : 'OP_0',
- OP_PUSHDATA1 : 'OP_PUSHDATA1',
- OP_PUSHDATA2 : 'OP_PUSHDATA2',
- OP_PUSHDATA4 : 'OP_PUSHDATA4',
- OP_1NEGATE : 'OP_1NEGATE',
- OP_RESERVED : 'OP_RESERVED',
- OP_1 : 'OP_1',
- OP_2 : 'OP_2',
- OP_3 : 'OP_3',
- OP_4 : 'OP_4',
- OP_5 : 'OP_5',
- OP_6 : 'OP_6',
- OP_7 : 'OP_7',
- OP_8 : 'OP_8',
- OP_9 : 'OP_9',
- OP_10 : 'OP_10',
- OP_11 : 'OP_11',
- OP_12 : 'OP_12',
- OP_13 : 'OP_13',
- OP_14 : 'OP_14',
- OP_15 : 'OP_15',
- OP_16 : 'OP_16',
- OP_NOP : 'OP_NOP',
- OP_VER : 'OP_VER',
- OP_IF : 'OP_IF',
- OP_NOTIF : 'OP_NOTIF',
- OP_VERIF : 'OP_VERIF',
- OP_VERNOTIF : 'OP_VERNOTIF',
- OP_ELSE : 'OP_ELSE',
- OP_ENDIF : 'OP_ENDIF',
- OP_VERIFY : 'OP_VERIFY',
- OP_RETURN : 'OP_RETURN',
- OP_TOALTSTACK : 'OP_TOALTSTACK',
- OP_FROMALTSTACK : 'OP_FROMALTSTACK',
- OP_2DROP : 'OP_2DROP',
- OP_2DUP : 'OP_2DUP',
- OP_3DUP : 'OP_3DUP',
- OP_2OVER : 'OP_2OVER',
- OP_2ROT : 'OP_2ROT',
- OP_2SWAP : 'OP_2SWAP',
- OP_IFDUP : 'OP_IFDUP',
- OP_DEPTH : 'OP_DEPTH',
- OP_DROP : 'OP_DROP',
- OP_DUP : 'OP_DUP',
- OP_NIP : 'OP_NIP',
- OP_OVER : 'OP_OVER',
- OP_PICK : 'OP_PICK',
- OP_ROLL : 'OP_ROLL',
- OP_ROT : 'OP_ROT',
- OP_SWAP : 'OP_SWAP',
- OP_TUCK : 'OP_TUCK',
- OP_CAT : 'OP_CAT',
- OP_SUBSTR : 'OP_SUBSTR',
- OP_LEFT : 'OP_LEFT',
- OP_RIGHT : 'OP_RIGHT',
- OP_SIZE : 'OP_SIZE',
- OP_INVERT : 'OP_INVERT',
- OP_AND : 'OP_AND',
- OP_OR : 'OP_OR',
- OP_XOR : 'OP_XOR',
- OP_EQUAL : 'OP_EQUAL',
- OP_EQUALVERIFY : 'OP_EQUALVERIFY',
- OP_RESERVED1 : 'OP_RESERVED1',
- OP_RESERVED2 : 'OP_RESERVED2',
- OP_1ADD : 'OP_1ADD',
- OP_1SUB : 'OP_1SUB',
- OP_2MUL : 'OP_2MUL',
- OP_2DIV : 'OP_2DIV',
- OP_NEGATE : 'OP_NEGATE',
- OP_ABS : 'OP_ABS',
- OP_NOT : 'OP_NOT',
- OP_0NOTEQUAL : 'OP_0NOTEQUAL',
- OP_ADD : 'OP_ADD',
- OP_SUB : 'OP_SUB',
- OP_MUL : 'OP_MUL',
- OP_DIV : 'OP_DIV',
- OP_MOD : 'OP_MOD',
- OP_LSHIFT : 'OP_LSHIFT',
- OP_RSHIFT : 'OP_RSHIFT',
- OP_BOOLAND : 'OP_BOOLAND',
- OP_BOOLOR : 'OP_BOOLOR',
- OP_NUMEQUAL : 'OP_NUMEQUAL',
- OP_NUMEQUALVERIFY : 'OP_NUMEQUALVERIFY',
- OP_NUMNOTEQUAL : 'OP_NUMNOTEQUAL',
- OP_LESSTHAN : 'OP_LESSTHAN',
- OP_GREATERTHAN : 'OP_GREATERTHAN',
- OP_LESSTHANOREQUAL : 'OP_LESSTHANOREQUAL',
- OP_GREATERTHANOREQUAL : 'OP_GREATERTHANOREQUAL',
- OP_MIN : 'OP_MIN',
- OP_MAX : 'OP_MAX',
- OP_WITHIN : 'OP_WITHIN',
- OP_RIPEMD160 : 'OP_RIPEMD160',
- OP_SHA1 : 'OP_SHA1',
- OP_SHA256 : 'OP_SHA256',
- OP_HASH160 : 'OP_HASH160',
- OP_HASH256 : 'OP_HASH256',
- OP_CODESEPARATOR : 'OP_CODESEPARATOR',
- OP_CHECKSIG : 'OP_CHECKSIG',
- OP_CHECKSIGVERIFY : 'OP_CHECKSIGVERIFY',
- OP_CHECKMULTISIG : 'OP_CHECKMULTISIG',
- OP_CHECKMULTISIGVERIFY : 'OP_CHECKMULTISIGVERIFY',
- OP_NOP1 : 'OP_NOP1',
- OP_CHECKLOCKTIMEVERIFY : 'OP_CHECKLOCKTIMEVERIFY',
- OP_CHECKSEQUENCEVERIFY : 'OP_CHECKSEQUENCEVERIFY',
- OP_NOP4 : 'OP_NOP4',
- OP_NOP5 : 'OP_NOP5',
- OP_NOP6 : 'OP_NOP6',
- OP_NOP7 : 'OP_NOP7',
- OP_NOP8 : 'OP_NOP8',
- OP_NOP9 : 'OP_NOP9',
- OP_NOP10 : 'OP_NOP10',
- OP_SMALLINTEGER : 'OP_SMALLINTEGER',
- OP_PUBKEYS : 'OP_PUBKEYS',
- OP_PUBKEYHASH : 'OP_PUBKEYHASH',
- OP_PUBKEY : 'OP_PUBKEY',
- OP_INVALIDOPCODE : 'OP_INVALIDOPCODE',
+ OP_0: 'OP_0',
+ OP_PUSHDATA1: 'OP_PUSHDATA1',
+ OP_PUSHDATA2: 'OP_PUSHDATA2',
+ OP_PUSHDATA4: 'OP_PUSHDATA4',
+ OP_1NEGATE: 'OP_1NEGATE',
+ OP_RESERVED: 'OP_RESERVED',
+ OP_1: 'OP_1',
+ OP_2: 'OP_2',
+ OP_3: 'OP_3',
+ OP_4: 'OP_4',
+ OP_5: 'OP_5',
+ OP_6: 'OP_6',
+ OP_7: 'OP_7',
+ OP_8: 'OP_8',
+ OP_9: 'OP_9',
+ OP_10: 'OP_10',
+ OP_11: 'OP_11',
+ OP_12: 'OP_12',
+ OP_13: 'OP_13',
+ OP_14: 'OP_14',
+ OP_15: 'OP_15',
+ OP_16: 'OP_16',
+ OP_NOP: 'OP_NOP',
+ OP_VER: 'OP_VER',
+ OP_IF: 'OP_IF',
+ OP_NOTIF: 'OP_NOTIF',
+ OP_VERIF: 'OP_VERIF',
+ OP_VERNOTIF: 'OP_VERNOTIF',
+ OP_ELSE: 'OP_ELSE',
+ OP_ENDIF: 'OP_ENDIF',
+ OP_VERIFY: 'OP_VERIFY',
+ OP_RETURN: 'OP_RETURN',
+ OP_TOALTSTACK: 'OP_TOALTSTACK',
+ OP_FROMALTSTACK: 'OP_FROMALTSTACK',
+ OP_2DROP: 'OP_2DROP',
+ OP_2DUP: 'OP_2DUP',
+ OP_3DUP: 'OP_3DUP',
+ OP_2OVER: 'OP_2OVER',
+ OP_2ROT: 'OP_2ROT',
+ OP_2SWAP: 'OP_2SWAP',
+ OP_IFDUP: 'OP_IFDUP',
+ OP_DEPTH: 'OP_DEPTH',
+ OP_DROP: 'OP_DROP',
+ OP_DUP: 'OP_DUP',
+ OP_NIP: 'OP_NIP',
+ OP_OVER: 'OP_OVER',
+ OP_PICK: 'OP_PICK',
+ OP_ROLL: 'OP_ROLL',
+ OP_ROT: 'OP_ROT',
+ OP_SWAP: 'OP_SWAP',
+ OP_TUCK: 'OP_TUCK',
+ OP_CAT: 'OP_CAT',
+ OP_SUBSTR: 'OP_SUBSTR',
+ OP_LEFT: 'OP_LEFT',
+ OP_RIGHT: 'OP_RIGHT',
+ OP_SIZE: 'OP_SIZE',
+ OP_INVERT: 'OP_INVERT',
+ OP_AND: 'OP_AND',
+ OP_OR: 'OP_OR',
+ OP_XOR: 'OP_XOR',
+ OP_EQUAL: 'OP_EQUAL',
+ OP_EQUALVERIFY: 'OP_EQUALVERIFY',
+ OP_RESERVED1: 'OP_RESERVED1',
+ OP_RESERVED2: 'OP_RESERVED2',
+ OP_1ADD: 'OP_1ADD',
+ OP_1SUB: 'OP_1SUB',
+ OP_2MUL: 'OP_2MUL',
+ OP_2DIV: 'OP_2DIV',
+ OP_NEGATE: 'OP_NEGATE',
+ OP_ABS: 'OP_ABS',
+ OP_NOT: 'OP_NOT',
+ OP_0NOTEQUAL: 'OP_0NOTEQUAL',
+ OP_ADD: 'OP_ADD',
+ OP_SUB: 'OP_SUB',
+ OP_MUL: 'OP_MUL',
+ OP_DIV: 'OP_DIV',
+ OP_MOD: 'OP_MOD',
+ OP_LSHIFT: 'OP_LSHIFT',
+ OP_RSHIFT: 'OP_RSHIFT',
+ OP_BOOLAND: 'OP_BOOLAND',
+ OP_BOOLOR: 'OP_BOOLOR',
+ OP_NUMEQUAL: 'OP_NUMEQUAL',
+ OP_NUMEQUALVERIFY: 'OP_NUMEQUALVERIFY',
+ OP_NUMNOTEQUAL: 'OP_NUMNOTEQUAL',
+ OP_LESSTHAN: 'OP_LESSTHAN',
+ OP_GREATERTHAN: 'OP_GREATERTHAN',
+ OP_LESSTHANOREQUAL: 'OP_LESSTHANOREQUAL',
+ OP_GREATERTHANOREQUAL: 'OP_GREATERTHANOREQUAL',
+ OP_MIN: 'OP_MIN',
+ OP_MAX: 'OP_MAX',
+ OP_WITHIN: 'OP_WITHIN',
+ OP_RIPEMD160: 'OP_RIPEMD160',
+ OP_SHA1: 'OP_SHA1',
+ OP_SHA256: 'OP_SHA256',
+ OP_HASH160: 'OP_HASH160',
+ OP_HASH256: 'OP_HASH256',
+ OP_CODESEPARATOR: 'OP_CODESEPARATOR',
+ OP_CHECKSIG: 'OP_CHECKSIG',
+ OP_CHECKSIGVERIFY: 'OP_CHECKSIGVERIFY',
+ OP_CHECKMULTISIG: 'OP_CHECKMULTISIG',
+ OP_CHECKMULTISIGVERIFY: 'OP_CHECKMULTISIGVERIFY',
+ OP_NOP1: 'OP_NOP1',
+ OP_CHECKLOCKTIMEVERIFY: 'OP_CHECKLOCKTIMEVERIFY',
+ OP_CHECKSEQUENCEVERIFY: 'OP_CHECKSEQUENCEVERIFY',
+ OP_NOP4: 'OP_NOP4',
+ OP_NOP5: 'OP_NOP5',
+ OP_NOP6: 'OP_NOP6',
+ OP_NOP7: 'OP_NOP7',
+ OP_NOP8: 'OP_NOP8',
+ OP_NOP9: 'OP_NOP9',
+ OP_NOP10: 'OP_NOP10',
+ OP_SMALLINTEGER: 'OP_SMALLINTEGER',
+ OP_PUBKEYS: 'OP_PUBKEYS',
+ OP_PUBKEYHASH: 'OP_PUBKEYHASH',
+ OP_PUBKEY: 'OP_PUBKEY',
+ OP_INVALIDOPCODE: 'OP_INVALIDOPCODE',
})
class CScriptInvalidError(Exception):
@@ -358,7 +373,7 @@ class CScriptTruncatedPushDataError(CScriptInvalidError):
"""Invalid pushdata due to truncation"""
def __init__(self, msg, data):
self.data = data
- super(CScriptTruncatedPushDataError, self).__init__(msg)
+ super().__init__(msg)
# This is used, eg, for blockchain heights in coinbase scripts (bip34)
@@ -392,10 +407,10 @@ class CScriptNum:
if len(value) == 0:
return result
for i, byte in enumerate(value):
- result |= int(byte) << 8*i
+ result |= int(byte) << 8 * i
if value[-1] >= 0x80:
# Mask for all but the highest result bit
- num_mask = (2**(len(value)*8) - 1) >> 1
+ num_mask = (2**(len(value) * 8) - 1) >> 1
result &= num_mask
result *= -1
return result
@@ -435,15 +450,8 @@ class CScript(bytes):
return other
def __add__(self, other):
- # Do the coercion outside of the try block so that errors in it are
- # noticed.
- other = self.__coerce_instance(other)
-
- try:
- # bytes.__add__ always returns bytes instances unfortunately
- return CScript(super(CScript, self).__add__(other))
- except TypeError:
- raise TypeError('Can not add a %r instance to a CScript' % other.__class__)
+ # add makes no sense for a CScript()
+ raise NotImplementedError
def join(self, iterable):
# join makes no sense for a CScript()
@@ -451,14 +459,14 @@ class CScript(bytes):
def __new__(cls, value=b''):
if isinstance(value, bytes) or isinstance(value, bytearray):
- return super(CScript, cls).__new__(cls, value)
+ return super().__new__(cls, value)
else:
def coerce_iterable(iterable):
for instance in iterable:
yield cls.__coerce_instance(instance)
# Annoyingly on both python2 and python3 bytes.join() always
# returns a bytes instance even when subclassed.
- return super(CScript, cls).__new__(cls, b''.join(coerce_iterable(value)))
+ return super().__new__(cls, b''.join(coerce_iterable(value)))
def raw_iter(self):
"""Raw iteration
@@ -493,21 +501,20 @@ class CScript(bytes):
pushdata_type = 'PUSHDATA2'
if i + 1 >= len(self):
raise CScriptInvalidError('PUSHDATA2: missing data length')
- datasize = self[i] + (self[i+1] << 8)
+ datasize = self[i] + (self[i + 1] << 8)
i += 2
elif opcode == OP_PUSHDATA4:
pushdata_type = 'PUSHDATA4'
if i + 3 >= len(self):
raise CScriptInvalidError('PUSHDATA4: missing data length')
- datasize = self[i] + (self[i+1] << 8) + (self[i+2] << 16) + (self[i+3] << 24)
+ datasize = self[i] + (self[i + 1] << 8) + (self[i + 2] << 16) + (self[i + 3] << 24)
i += 4
else:
- assert False # shouldn't happen
+ assert False # shouldn't happen
-
- data = bytes(self[i:i+datasize])
+ data = bytes(self[i:i + datasize])
# Check for truncation
if len(data) < datasize:
@@ -702,3 +709,25 @@ def SegwitV0SignatureHash(script, txTo, inIdx, hashtype, amount):
ss += struct.pack("<I", hashtype)
return hash256(ss)
+
+class TestFrameworkScript(unittest.TestCase):
+ def test_bn2vch(self):
+ self.assertEqual(bn2vch(0), bytes([]))
+ self.assertEqual(bn2vch(1), bytes([0x01]))
+ self.assertEqual(bn2vch(-1), bytes([0x81]))
+ self.assertEqual(bn2vch(0x7F), bytes([0x7F]))
+ self.assertEqual(bn2vch(-0x7F), bytes([0xFF]))
+ self.assertEqual(bn2vch(0x80), bytes([0x80, 0x00]))
+ self.assertEqual(bn2vch(-0x80), bytes([0x80, 0x80]))
+ self.assertEqual(bn2vch(0xFF), bytes([0xFF, 0x00]))
+ self.assertEqual(bn2vch(-0xFF), bytes([0xFF, 0x80]))
+ self.assertEqual(bn2vch(0x100), bytes([0x00, 0x01]))
+ self.assertEqual(bn2vch(-0x100), bytes([0x00, 0x81]))
+ self.assertEqual(bn2vch(0x7FFF), bytes([0xFF, 0x7F]))
+ self.assertEqual(bn2vch(-0x8000), bytes([0x00, 0x80, 0x80]))
+ self.assertEqual(bn2vch(-0x7FFFFF), bytes([0xFF, 0xFF, 0xFF]))
+ self.assertEqual(bn2vch(0x80000000), bytes([0x00, 0x00, 0x00, 0x80, 0x00]))
+ self.assertEqual(bn2vch(-0x80000000), bytes([0x00, 0x00, 0x00, 0x80, 0x80]))
+ self.assertEqual(bn2vch(0xFFFFFFFF), bytes([0xFF, 0xFF, 0xFF, 0xFF, 0x00]))
+ self.assertEqual(bn2vch(123456789), bytes([0x15, 0xCD, 0x5B, 0x07]))
+ self.assertEqual(bn2vch(-54321), bytes([0x31, 0xD4, 0x80]))
diff --git a/test/functional/test_framework/script_util.py b/test/functional/test_framework/script_util.py
index 5ef67226c4..80fbae70bf 100755
--- a/test/functional/test_framework/script_util.py
+++ b/test/functional/test_framework/script_util.py
@@ -23,3 +23,4 @@ from test_framework.script import CScript
# scriptPubKeys are needed, to guarantee that the minimum transaction size is
# met.
DUMMY_P2WPKH_SCRIPT = CScript([b'a' * 21])
+DUMMY_2_P2WPKH_SCRIPT = CScript([b'b' * 21])
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index da92c6325a..11c96deefb 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -6,11 +6,12 @@
import configparser
from enum import Enum
-import logging
import argparse
+import logging
import os
import pdb
import random
+import re
import shutil
import subprocess
import sys
@@ -101,6 +102,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.bind_to_localhost_only = True
self.set_test_params()
self.parse_args()
+ self.rpc_timeout = int(self.rpc_timeout * self.options.factor) # optionally, increase timeout by a factor
def main(self):
"""Main function. This should not be overridden by the subclass test scripts."""
@@ -165,6 +167,9 @@ 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('--factor', type=float, default=1.0, help='adjust test timeouts by a factor')
self.add_options(parser)
self.options = parser.parse_args()
@@ -183,10 +188,11 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.options.bitcoind = os.getenv("BITCOIND", default=config["environment"]["BUILDDIR"] + '/src/bitcoind' + config["environment"]["EXEEXT"])
self.options.bitcoincli = os.getenv("BITCOINCLI", default=config["environment"]["BUILDDIR"] + '/src/bitcoin-cli' + config["environment"]["EXEEXT"])
+ self.options.previous_releases_path = os.getenv("PREVIOUS_RELEASES_DIR") or os.getcwd() + "/releases"
+
os.environ['PATH'] = os.pathsep.join([
os.path.join(config['environment']['BUILDDIR'], 'src'),
- os.path.join(config['environment']['BUILDDIR'], 'src', 'qt'),
- os.environ['PATH']
+ os.path.join(config['environment']['BUILDDIR'], 'src', 'qt'), os.environ['PATH']
])
# Set up temp directory and start logging
@@ -333,11 +339,23 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
def setup_nodes(self):
"""Override this method to customize test node setup"""
- extra_args = None
+ extra_args = [[]] * self.num_nodes
+ wallets = [[]] * self.num_nodes
if hasattr(self, "extra_args"):
extra_args = self.extra_args
+ wallets = [[x for x in eargs if x.startswith('-wallet=')] for eargs in extra_args]
+ extra_args = [x + ['-nowallet'] for x in extra_args]
self.add_nodes(self.num_nodes, extra_args)
self.start_nodes()
+ for i, n in enumerate(self.nodes):
+ n.extra_args.pop()
+ if '-wallet=0' in n.extra_args or '-nowallet' in n.extra_args or '-disablewallet' in n.extra_args or not self.is_wallet_compiled():
+ continue
+ if '-wallet=' not in wallets[i] and not any([x.startswith('-wallet=') for x in wallets[i]]):
+ wallets[i].append('-wallet=')
+ for w in wallets[i]:
+ wallet_name = w.split('=', 1)[1]
+ n.createwallet(wallet_name=wallet_name, descriptors=self.options.descriptors)
self.import_deterministic_coinbase_privkeys()
if not self.setup_clean_chain:
for n in self.nodes:
@@ -369,22 +387,47 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# Public helper methods. These can be accessed by the subclass test scripts.
- def add_nodes(self, num_nodes, extra_args=None, *, rpchost=None, binary=None):
+ def add_nodes(self, num_nodes, extra_args=None, *, rpchost=None, binary=None, binary_cli=None, versions=None):
"""Instantiate TestNode objects.
Should only be called once after the nodes have been specified in
set_test_params()."""
+ def get_bin_from_version(version, bin_name, bin_default):
+ if not version:
+ return bin_default
+ return os.path.join(
+ self.options.previous_releases_path,
+ re.sub(
+ r'\.0$',
+ '', # remove trailing .0 for point releases
+ 'v{}.{}.{}.{}'.format(
+ (version % 100000000) // 1000000,
+ (version % 1000000) // 10000,
+ (version % 10000) // 100,
+ (version % 100) // 1,
+ ),
+ ),
+ 'bin',
+ bin_name,
+ )
+
if self.bind_to_localhost_only:
extra_confs = [["bind=127.0.0.1"]] * num_nodes
else:
extra_confs = [[]] * num_nodes
if extra_args is None:
extra_args = [[]] * num_nodes
+ if versions is None:
+ versions = [None] * num_nodes
if binary is None:
- binary = [self.options.bitcoind] * num_nodes
+ binary = [get_bin_from_version(v, 'bitcoind', self.options.bitcoind) for v in versions]
+ if binary_cli is None:
+ binary_cli = [get_bin_from_version(v, 'bitcoin-cli', self.options.bitcoincli) for v in versions]
assert_equal(len(extra_confs), num_nodes)
assert_equal(len(extra_args), num_nodes)
+ assert_equal(len(versions), num_nodes)
assert_equal(len(binary), num_nodes)
+ assert_equal(len(binary_cli), num_nodes)
for i in range(num_nodes):
self.nodes.append(TestNode(
i,
@@ -392,8 +435,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
chain=self.chain,
rpchost=rpchost,
timewait=self.rpc_timeout,
+ factor=self.options.factor,
bitcoind=binary[i],
- bitcoin_cli=self.options.bitcoincli,
+ bitcoin_cli=binary_cli[i],
+ version=versions[i],
coverage_dir=self.options.coveragedir,
cwd=self.options.tmpdir,
extra_conf=extra_confs[i],
@@ -401,6 +446,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
use_cli=self.options.usecli,
start_perf=self.options.perf,
use_valgrind=self.options.valgrind,
+ descriptors=self.options.descriptors,
))
def start_node(self, i, *args, **kwargs):
@@ -536,15 +582,21 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
extra_args=['-disablewallet'],
rpchost=None,
timewait=self.rpc_timeout,
+ factor=self.options.factor,
bitcoind=self.options.bitcoind,
bitcoin_cli=self.options.bitcoincli,
coverage_dir=None,
cwd=self.options.tmpdir,
+ descriptors=self.options.descriptors,
))
self.start_node(CACHE_NODE_ID)
+ cache_node = self.nodes[CACHE_NODE_ID]
# Wait for RPC connections to be ready
- self.nodes[CACHE_NODE_ID].wait_for_rpc_connection()
+ cache_node.wait_for_rpc_connection()
+
+ # Set a time in the past, so that blocks don't end up in the future
+ cache_node.setmocktime(cache_node.getblockheader(cache_node.getbestblockhash())['time'])
# Create a 199-block-long chain; each of the 4 first nodes
# gets 25 mature blocks and 25 immature.
@@ -553,12 +605,12 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# This is needed so that we are out of IBD when the test starts,
# see the tip age check in IsInitialBlockDownload().
for i in range(8):
- self.nodes[CACHE_NODE_ID].generatetoaddress(
+ cache_node.generatetoaddress(
nblocks=25 if i != 7 else 24,
address=TestNode.PRIV_KEYS[i % 4].address,
)
- assert_equal(self.nodes[CACHE_NODE_ID].getblockchaininfo()["blocks"], 199)
+ assert_equal(cache_node.getblockchaininfo()["blocks"], 199)
# Shut it down, and clean up cache directories:
self.stop_nodes()
@@ -613,6 +665,25 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
if not self.is_cli_compiled():
raise SkipTest("bitcoin-cli has not been compiled.")
+ def skip_if_no_previous_releases(self):
+ """Skip the running test if previous releases are not available."""
+ if not self.has_previous_releases():
+ raise SkipTest("previous releases not available or disabled")
+
+ def has_previous_releases(self):
+ """Checks whether previous releases are present and enabled."""
+ if os.getenv("TEST_PREVIOUS_RELEASES") == "false":
+ # disabled
+ return False
+
+ if not os.path.isdir(self.options.previous_releases_path):
+ if os.getenv("TEST_PREVIOUS_RELEASES") == "true":
+ raise AssertionError("TEST_PREVIOUS_RELEASES=true but releases missing: {}".format(
+ self.options.previous_releases_path))
+ # missing
+ return False
+ return True
+
def is_cli_compiled(self):
"""Checks whether bitcoin-cli was compiled."""
return self.config["components"].getboolean("ENABLE_CLI")
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 0742dbe617..e6ec3c1b2d 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2019 The Bitcoin Core developers
+# Copyright (c) 2017-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.
"""Class for bitcoind node under test"""
@@ -22,10 +22,12 @@ import shlex
import sys
from .authproxy import JSONRPCException
+from .descriptors import descsum_create
from .util import (
MAX_NODES,
append_config,
delete_cookie_file,
+ get_auth_cookie,
get_rpc_proxy,
rpc_url,
wait_until,
@@ -60,7 +62,7 @@ class TestNode():
To make things easier for the test writer, any unrecognised messages will
be dispatched to the RPC connection."""
- def __init__(self, i, datadir, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False):
+ def __init__(self, i, datadir, *, chain, rpchost, timewait, factor, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False, version=None, descriptors=False):
"""
Kwargs:
start_perf (bool): If True, begin profiling the node with `perf` as soon as
@@ -78,12 +80,14 @@ class TestNode():
self.binary = bitcoind
self.coverage_dir = coverage_dir
self.cwd = cwd
+ self.descriptors = descriptors
if extra_conf is not None:
append_config(datadir, extra_conf)
# Most callers will just need to add extra args to the standard list below.
# For those callers that need more flexibility, they can just set the args property directly.
# Note that common args are set in the config file (see initialize_datadir)
self.extra_args = extra_args
+ self.version = version
# Configuration for logging is set as command-line args rather than in the bitcoin.conf file.
# This means that starting a bitcoind using the temp dir to debug a failed test won't
# spam debug.log.
@@ -91,7 +95,6 @@ class TestNode():
self.binary,
"-datadir=" + self.datadir,
"-logtimemicros",
- "-logthreadnames",
"-debug",
"-debugexclude=libevent",
"-debugexclude=leveldb",
@@ -107,6 +110,9 @@ class TestNode():
"--gen-suppressions=all", "--exit-on-first-error=yes",
"--error-exitcode=1", "--quiet"] + self.args
+ if self.version is None or self.version >= 190000:
+ self.args.append("-logthreadnames")
+
self.cli = TestNodeCLI(bitcoin_cli, self.datadir)
self.use_cli = use_cli
self.start_perf = start_perf
@@ -122,6 +128,7 @@ class TestNode():
self.perf_subprocesses = {}
self.p2ps = []
+ self.factor = factor
AddressKeyPair = collections.namedtuple('AddressKeyPair', ['address', 'key'])
PRIV_KEYS = [
@@ -166,10 +173,10 @@ class TestNode():
def __getattr__(self, name):
"""Dispatches any unrecognised messages to the RPC connection or a CLI instance."""
if self.use_cli:
- return getattr(self.cli, name)
+ return getattr(RPCOverloadWrapper(self.cli, True, self.descriptors), name)
else:
assert self.rpc_connected and self.rpc is not None, self._node_msg("Error: no RPC connection")
- return getattr(self.rpc, name)
+ return getattr(RPCOverloadWrapper(self.rpc, descriptors=self.descriptors), name)
def start(self, extra_args=None, *, cwd=None, stdout=None, stderr=None, **kwargs):
"""Start the node."""
@@ -222,19 +229,38 @@ class TestNode():
self.rpc_connected = True
self.url = self.rpc.url
return
- except IOError as e:
- if e.errno != errno.ECONNREFUSED: # Port not yet open?
- raise # unknown IO error
except JSONRPCException as e: # Initialization phase
# -28 RPC in warmup
# -342 Service unavailable, RPC server started but is shutting down due to error
if e.error['code'] != -28 and e.error['code'] != -342:
raise # unknown JSON RPC exception
- except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting
+ except ConnectionResetError:
+ # This might happen when the RPC server is in warmup, but shut down before the call to getblockcount
+ # succeeds. Try again to properly raise the FailedToStartError
+ pass
+ except OSError as e:
+ if e.errno != errno.ECONNREFUSED: # Port not yet open?
+ raise # unknown OS error
+ except ValueError as e: # cookie file not found and no rpcuser or rpcpassword; bitcoind is still starting
if "No RPC credentials" not in str(e):
raise
time.sleep(1.0 / poll_per_s)
- self._raise_assertion_error("Unable to connect to bitcoind")
+ self._raise_assertion_error("Unable to connect to bitcoind after {}s".format(self.rpc_timeout))
+
+ def wait_for_cookie_credentials(self):
+ """Ensures auth cookie credentials can be read, e.g. for testing CLI with -rpcwait before RPC connection is up."""
+ self.log.debug("Waiting for cookie credentials")
+ # Poll at a rate of four times per second.
+ poll_per_s = 4
+ for _ in range(poll_per_s * self.rpc_timeout):
+ try:
+ get_auth_cookie(self.datadir, self.chain)
+ self.log.debug("Cookie credentials successfully retrieved")
+ return
+ except ValueError: # cookie file not found and no rpcuser or rpcpassword; bitcoind is still starting
+ pass # so we continue polling until RPC credentials are retrieved
+ time.sleep(1.0 / poll_per_s)
+ self._raise_assertion_error("Unable to retrieve cookie credentials after {}s".format(self.rpc_timeout))
def generate(self, nblocks, maxtries=1000000):
self.log.debug("TestNode.generate() dispatches `generate` call to `generatetoaddress`")
@@ -242,11 +268,11 @@ class TestNode():
def get_wallet_rpc(self, wallet_name):
if self.use_cli:
- return self.cli("-rpcwallet={}".format(wallet_name))
+ return RPCOverloadWrapper(self.cli("-rpcwallet={}".format(wallet_name)), True, self.descriptors)
else:
assert self.rpc_connected and self.rpc, self._node_msg("RPC not connected")
wallet_path = "wallet/{}".format(urllib.parse.quote(wallet_name))
- return self.rpc / wallet_path
+ return RPCOverloadWrapper(self.rpc / wallet_path, descriptors=self.descriptors)
def stop_node(self, expected_stderr='', wait=0):
"""Stop the node."""
@@ -254,7 +280,11 @@ class TestNode():
return
self.log.debug("Stopping node")
try:
- self.stop(wait=wait)
+ # Do not use wait argument when testing older nodes, e.g. in feature_backwards_compatibility.py
+ if self.version is None or self.version >= 180000:
+ self.stop(wait=wait)
+ else:
+ self.stop()
except http.client.CannotSendRequest:
self.log.exception("Unable to stop node.")
@@ -295,13 +325,13 @@ class TestNode():
return True
def wait_until_stopped(self, timeout=BITCOIND_PROC_WAIT_TIMEOUT):
- wait_until(self.is_node_stopped, timeout=timeout)
+ wait_until(self.is_node_stopped, timeout=timeout, factor=self.factor)
@contextlib.contextmanager
def assert_debug_log(self, expected_msgs, unexpected_msgs=None, timeout=2):
if unexpected_msgs is None:
unexpected_msgs = []
- time_end = time.time() + timeout
+ time_end = time.time() + timeout * self.factor
debug_log = os.path.join(self.datadir, self.chain, 'debug.log')
with open(debug_log, encoding='utf-8') as dl:
dl.seek(0, 2)
@@ -458,10 +488,22 @@ class TestNode():
if 'dstaddr' not in kwargs:
kwargs['dstaddr'] = '127.0.0.1'
- p2p_conn.peer_connect(**kwargs, net=self.chain)()
+ p2p_conn.peer_connect(**kwargs, net=self.chain, factor=self.factor)()
self.p2ps.append(p2p_conn)
if wait_for_verack:
+ # Wait for the node to send us the version and verack
p2p_conn.wait_for_verack()
+ # At this point we have sent our version message and received the version and verack, however the full node
+ # has not yet received the verack from us (in reply to their version). So, the connection is not yet fully
+ # established (fSuccessfullyConnected).
+ #
+ # This shouldn't lead to any issues when sending messages, since the verack will be in-flight before the
+ # message we send. However, it might lead to races where we are expecting to receive a message. E.g. a
+ # transaction that will be added to the mempool as soon as we return here.
+ #
+ # So syncing here is redundant when we only want to send a message, but the cost is low (a few milliseconds)
+ # in comparision to the upside of making tests less fragile and unexpected intermittent errors less likely.
+ p2p_conn.sync_with_ping()
return p2p_conn
@@ -480,6 +522,7 @@ class TestNode():
p.peer_disconnect()
del self.p2ps[:]
+
class TestNodeCLIAttr:
def __init__(self, cli, command):
self.cli = cli
@@ -491,6 +534,7 @@ class TestNodeCLIAttr:
def get_request(self, *args, **kwargs):
return lambda: self(*args, **kwargs)
+
def arg_to_cli(arg):
if isinstance(arg, bool):
return str(arg).lower()
@@ -499,9 +543,9 @@ def arg_to_cli(arg):
else:
return str(arg)
+
class TestNodeCLI():
"""Interface to bitcoin-cli for an individual node"""
-
def __init__(self, binary, datadir):
self.options = []
self.binary = binary
@@ -539,7 +583,7 @@ class TestNodeCLI():
if command is not None:
p_args += [command]
p_args += pos_args + named_args
- self.log.debug("Running bitcoin-cli command: %s" % command)
+ self.log.debug("Running bitcoin-cli {}".format(p_args[2:]))
process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
cli_stdout, cli_stderr = process.communicate(input=self.input)
returncode = process.poll()
@@ -554,3 +598,118 @@ class TestNodeCLI():
return json.loads(cli_stdout, parse_float=decimal.Decimal)
except json.JSONDecodeError:
return cli_stdout.rstrip("\n")
+
+class RPCOverloadWrapper():
+ def __init__(self, rpc, cli=False, descriptors=False):
+ self.rpc = rpc
+ self.is_cli = cli
+ self.descriptors = descriptors
+
+ def __getattr__(self, name):
+ return getattr(self.rpc, name)
+
+ def createwallet(self, wallet_name, disable_private_keys=None, blank=None, passphrase=None, avoid_reuse=None, descriptors=None):
+ if self.is_cli:
+ if disable_private_keys is None:
+ disable_private_keys = 'null'
+ if blank is None:
+ blank = 'null'
+ if passphrase is None:
+ passphrase = ''
+ if avoid_reuse is None:
+ avoid_reuse = 'null'
+ if descriptors is None:
+ descriptors = self.descriptors
+ return self.__getattr__('createwallet')(wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors)
+
+ def importprivkey(self, privkey, label=None, rescan=None):
+ wallet_info = self.getwalletinfo()
+ if self.is_cli:
+ if label is None:
+ label = 'null'
+ if rescan is None:
+ rescan = 'null'
+ if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
+ return self.__getattr__('importprivkey')(privkey, label, rescan)
+ desc = descsum_create('combo(' + privkey + ')')
+ req = [{
+ 'desc': desc,
+ 'timestamp': 0 if rescan else 'now',
+ 'label': label if label else ''
+ }]
+ import_res = self.importdescriptors(req)
+ if not import_res[0]['success']:
+ raise JSONRPCException(import_res[0]['error'])
+
+ def addmultisigaddress(self, nrequired, keys, label=None, address_type=None):
+ wallet_info = self.getwalletinfo()
+ if self.is_cli:
+ if label is None:
+ label = 'null'
+ if address_type is None:
+ address_type = 'null'
+ if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
+ return self.__getattr__('addmultisigaddress')(nrequired, keys, label, address_type)
+ cms = self.createmultisig(nrequired, keys, address_type)
+ req = [{
+ 'desc': cms['descriptor'],
+ 'timestamp': 0,
+ 'label': label if label else ''
+ }]
+ import_res = self.importdescriptors(req)
+ if not import_res[0]['success']:
+ raise JSONRPCException(import_res[0]['error'])
+ return cms
+
+ def importpubkey(self, pubkey, label=None, rescan=None):
+ wallet_info = self.getwalletinfo()
+ if self.is_cli:
+ if label is None:
+ label = 'null'
+ if rescan is None:
+ rescan = 'null'
+ if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
+ return self.__getattr__('importpubkey')(pubkey, label, rescan)
+ desc = descsum_create('combo(' + pubkey + ')')
+ req = [{
+ 'desc': desc,
+ 'timestamp': 0 if rescan else 'now',
+ 'label': label if label else ''
+ }]
+ import_res = self.importdescriptors(req)
+ if not import_res[0]['success']:
+ raise JSONRPCException(import_res[0]['error'])
+
+ def importaddress(self, address, label=None, rescan=None, p2sh=None):
+ wallet_info = self.getwalletinfo()
+ if self.is_cli:
+ if label is None:
+ label = 'null'
+ if rescan is None:
+ rescan = 'null'
+ if p2sh is None:
+ p2sh = 'null'
+ if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
+ return self.__getattr__('importaddress')(address, label, rescan, p2sh)
+ is_hex = False
+ try:
+ int(address ,16)
+ is_hex = True
+ desc = descsum_create('raw(' + address + ')')
+ except:
+ desc = descsum_create('addr(' + address + ')')
+ reqs = [{
+ 'desc': desc,
+ 'timestamp': 0 if rescan else 'now',
+ 'label': label if label else ''
+ }]
+ if is_hex and p2sh:
+ reqs.append({
+ 'desc': descsum_create('p2sh(raw(' + address + '))'),
+ 'timestamp': 0 if rescan else 'now',
+ 'label': label if label else ''
+ })
+ import_res = self.importdescriptors(reqs)
+ for res in import_res:
+ if not res['success']:
+ raise JSONRPCException(res['error'])
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 5bb73aee7e..20ab9ee464 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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.
"""Helpful routines for regression testing."""
@@ -208,9 +208,10 @@ def str_to_b64str(string):
def satoshi_round(amount):
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
-def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=None):
+def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=None, factor=1.0):
if attempts == float('inf') and timeout == float('inf'):
timeout = 60
+ timeout = timeout * factor
attempt = 0
time_end = time.time() + timeout
@@ -265,7 +266,7 @@ def get_rpc_proxy(url, node_number, *, timeout=None, coveragedir=None):
"""
proxy_kwargs = {}
if timeout is not None:
- proxy_kwargs['timeout'] = timeout
+ proxy_kwargs['timeout'] = int(timeout)
proxy = AuthServiceProxy(url, **proxy_kwargs)
proxy.url = url # store URL on proxy for info
@@ -326,6 +327,13 @@ def initialize_datadir(dirname, n, chain):
os.makedirs(os.path.join(datadir, 'stdout'), exist_ok=True)
return datadir
+def adjust_bitcoin_conf_for_pre_17(conf_file):
+ with open(conf_file,'r', encoding='utf8') as conf:
+ conf_data = conf.read()
+ with open(conf_file, 'w', encoding='utf8') as conf:
+ conf_data_changed = conf_data.replace('[regtest]', '')
+ conf.write(conf_data_changed)
+
def get_datadir_path(dirname, n):
return os.path.join(dirname, "node" + str(n))
@@ -393,6 +401,7 @@ def connect_nodes(from_connection, node_num):
# with transaction relaying
wait_until(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo()))
+
def sync_blocks(rpc_connections, *, wait=1, timeout=60):
"""
Wait until everybody has the same tip.
@@ -406,8 +415,14 @@ def sync_blocks(rpc_connections, *, wait=1, timeout=60):
best_hash = [x.getbestblockhash() for x in rpc_connections]
if best_hash.count(best_hash[0]) == len(rpc_connections):
return
+ # Check that each peer has at least one connection
+ assert (all([len(x.getpeerinfo()) for x in rpc_connections]))
time.sleep(wait)
- raise AssertionError("Block sync timed out:{}".format("".join("\n {!r}".format(b) for b in best_hash)))
+ raise AssertionError("Block sync timed out after {}s:{}".format(
+ timeout,
+ "".join("\n {!r}".format(b) for b in best_hash),
+ ))
+
def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True):
"""
@@ -422,12 +437,19 @@ def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True):
for r in rpc_connections:
r.syncwithvalidationinterfacequeue()
return
+ # Check that each peer has at least one connection
+ assert (all([len(x.getpeerinfo()) for x in rpc_connections]))
time.sleep(wait)
- raise AssertionError("Mempool sync timed out:{}".format("".join("\n {!r}".format(m) for m in pool)))
+ raise AssertionError("Mempool sync timed out after {}s:{}".format(
+ timeout,
+ "".join("\n {!r}".format(m) for m in pool),
+ ))
+
# Transaction/Block functions
#############################
+
def find_output(node, txid, amount, *, blockhash=None):
"""
Return index to output of txid with value amount
diff --git a/test/functional/test_framework/wallet_util.py b/test/functional/test_framework/wallet_util.py
index eb537015fb..1b6686ff45 100755
--- a/test/functional/test_framework/wallet_util.py
+++ b/test/functional/test_framework/wallet_util.py
@@ -13,6 +13,10 @@ from test_framework.address import (
script_to_p2sh_p2wsh,
script_to_p2wsh,
)
+from test_framework.key import (
+ bytes_to_wif,
+ ECKey,
+)
from test_framework.script import (
CScript,
OP_0,
@@ -66,6 +70,25 @@ def get_key(node):
p2sh_p2wpkh_redeem_script=CScript([OP_0, pkh]).hex(),
p2sh_p2wpkh_addr=key_to_p2sh_p2wpkh(pubkey))
+def get_generate_key():
+ """Generate a fresh key
+
+ Returns a named tuple of privkey, pubkey and all address and scripts."""
+ eckey = ECKey()
+ eckey.generate()
+ privkey = bytes_to_wif(eckey.get_bytes())
+ pubkey = eckey.get_pubkey().get_bytes().hex()
+ pkh = hash160(hex_str_to_bytes(pubkey))
+ return Key(privkey=privkey,
+ pubkey=pubkey,
+ p2pkh_script=CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG]).hex(),
+ p2pkh_addr=key_to_p2pkh(pubkey),
+ p2wpkh_script=CScript([OP_0, pkh]).hex(),
+ p2wpkh_addr=key_to_p2wpkh(pubkey),
+ p2sh_p2wpkh_script=CScript([OP_HASH160, hash160(CScript([OP_0, pkh])), OP_EQUAL]).hex(),
+ p2sh_p2wpkh_redeem_script=CScript([OP_0, pkh]).hex(),
+ p2sh_p2wpkh_addr=key_to_p2sh_p2wpkh(pubkey))
+
def get_multisig(node):
"""Generate a fresh 2-of-3 multisig on node
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 8b527bcff0..45f591ba4a 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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.
"""Run regression test suite.
@@ -19,12 +19,12 @@ import datetime
import os
import time
import shutil
-import signal
-import sys
import subprocess
+import sys
import tempfile
import re
import logging
+import unittest
# Formatting. Default colors to empty strings.
BOLD, GREEN, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "")
@@ -66,6 +66,10 @@ if os.name != 'nt' or sys.getwindowsversion() >= (10, 0, 14393):
TEST_EXIT_PASSED = 0
TEST_EXIT_SKIPPED = 77
+TEST_FRAMEWORK_MODULES = [
+ "script",
+]
+
EXTENDED_SCRIPTS = [
# These tests are not run by default.
# Longest test should go first, to favor running tests in parallel
@@ -77,6 +81,7 @@ BASE_SCRIPTS = [
# Scripts that are run by default.
# Longest test should go first, to favor running tests in parallel
'wallet_hd.py',
+ 'wallet_hd.py --descriptors',
'wallet_backup.py',
# vv Tests less than 5m vv
'mining_getblocktemplate_longpoll.py',
@@ -87,10 +92,13 @@ BASE_SCRIPTS = [
'feature_segwit.py',
# vv Tests less than 2m vv
'wallet_basic.py',
+ 'wallet_basic.py --descriptors',
'wallet_labels.py',
+ 'wallet_labels.py --descriptors',
'p2p_segwit.py',
'p2p_timeouts.py',
'p2p_tx_download.py',
+ 'mempool_updatefromblock.py',
'wallet_dump.py',
'wallet_listtransactions.py',
# vv Tests less than 60s vv
@@ -110,6 +118,7 @@ BASE_SCRIPTS = [
'feature_abortnode.py',
# vv Tests less than 30s vv
'wallet_keypool_topup.py',
+ 'wallet_keypool_topup.py --descriptors',
'feature_fee_estimation.py',
'interface_zmq.py',
'interface_bitcoin_cli.py',
@@ -123,6 +132,7 @@ BASE_SCRIPTS = [
'interface_rest.py',
'mempool_spend_coinbase.py',
'wallet_avoidreuse.py',
+ 'wallet_avoidreuse.py --descriptors',
'mempool_reorg.py',
'mempool_persist.py',
'wallet_multiwallet.py',
@@ -135,6 +145,7 @@ BASE_SCRIPTS = [
'interface_http.py',
'interface_rpc.py',
'rpc_psbt.py',
+ 'rpc_psbt.py --descriptors',
'rpc_users.py',
'rpc_whitelist.py',
'feature_proxy.py',
@@ -145,9 +156,13 @@ BASE_SCRIPTS = [
'rpc_blockchain.py',
'rpc_deprecated.py',
'wallet_disable.py',
+ 'p2p_addr_relay.py',
'rpc_net.py',
'wallet_keypool.py',
+ 'wallet_keypool.py --descriptors',
+ 'wallet_descriptor.py',
'p2p_mempool.py',
+ 'p2p_filter.py',
'rpc_setban.py',
'p2p_blocksonly.py',
'mining_prioritisetransaction.py',
@@ -158,6 +173,7 @@ BASE_SCRIPTS = [
'feature_assumevalid.py',
'example_test.py',
'wallet_txn_doublespend.py',
+ 'feature_backwards_compatibility.py',
'wallet_txn_clone.py --mineblock',
'feature_notifications.py',
'rpc_getblockfilter.py',
@@ -166,27 +182,32 @@ BASE_SCRIPTS = [
'mempool_packages.py',
'mempool_package_onemore.py',
'rpc_createmultisig.py',
+ 'rpc_createmultisig.py --descriptors',
'feature_versionbits_warning.py',
'rpc_preciousblock.py',
'wallet_importprunedfunds.py',
'p2p_leak_tx.py',
'rpc_signmessage.py',
+ 'rpc_generateblock.py',
'wallet_balance.py',
'feature_nulldummy.py',
'mempool_accept.py',
+ 'mempool_expiry.py',
'wallet_import_rescan.py',
'wallet_import_with_label.py',
+ 'wallet_importdescriptors.py',
+ 'wallet_upgradewallet.py',
'rpc_bind.py --ipv4',
'rpc_bind.py --ipv6',
'rpc_bind.py --nonloopback',
'mining_basic.py',
'wallet_bumpfee.py',
- 'wallet_bumpfee_totalfee_deprecation.py',
'wallet_implicitsegwit.py',
'rpc_named_arguments.py',
'wallet_listsinceblock.py',
'p2p_leak.py',
'wallet_encryption.py',
+ 'wallet_encryption.py --descriptors',
'feature_dersig.py',
'feature_cltv.py',
'rpc_uptime.py',
@@ -194,6 +215,7 @@ BASE_SCRIPTS = [
'wallet_fallbackfee.py',
'rpc_dumptxoutset.py',
'feature_minchainwork.py',
+ 'rpc_estimatefee.py',
'rpc_getblockstats.py',
'wallet_create_tx.py',
'p2p_fingerprint.py',
@@ -204,6 +226,8 @@ BASE_SCRIPTS = [
'p2p_dos_header_tree.py',
'p2p_unrequested_blocks.py',
'feature_includeconf.py',
+ 'feature_asmap.py',
+ 'mempool_unbroadcast.py',
'rpc_deriveaddresses.py',
'rpc_deriveaddresses.py --usecli',
'rpc_scantxoutset.py',
@@ -214,6 +238,7 @@ BASE_SCRIPTS = [
'feature_config_args.py',
'rpc_getaddressinfo_labels_purpose_deprecation.py',
'rpc_getaddressinfo_label_deprecation.py',
+ 'rpc_getdescriptorinfo.py',
'rpc_help.py',
'feature_help.py',
'feature_shutdown.py',
@@ -360,11 +385,10 @@ def main():
args=passon_args,
combined_logs_len=args.combinedlogslen,
failfast=args.failfast,
- runs_ci=args.ci,
use_term_control=args.ansi,
)
-def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False, runs_ci, use_term_control):
+def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False, use_term_control):
args = args or []
# Warn if bitcoind is already running
@@ -380,6 +404,16 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=
if os.path.isdir(cache_dir):
print("%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % (BOLD[1], BOLD[0], cache_dir))
+ # Test Framework Tests
+ print("Running Unit Tests for Test Framework Modules")
+ test_framework_tests = unittest.TestSuite()
+ for module in TEST_FRAMEWORK_MODULES:
+ test_framework_tests.addTest(unittest.TestLoader().loadTestsFromName("test_framework.{}".format(module)))
+ result = unittest.TextTestRunner(verbosity=1, failfast=True).run(test_framework_tests)
+ if not result.wasSuccessful():
+ logging.debug("Early exiting after failure in TestFramework unit tests")
+ sys.exit(False)
+
tests_dir = src_dir + '/test/functional/'
flags = ['--cachedir={}'.format(cache_dir)] + args
@@ -406,7 +440,6 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=
tmpdir=tmpdir,
test_list=test_list,
flags=flags,
- timeout_duration=40 * 60 if runs_ci else float('inf'), # in seconds
use_term_control=use_term_control,
)
start_time = time.time()
@@ -491,12 +524,11 @@ class TestHandler:
Trigger the test scripts passed in via the list.
"""
- def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, timeout_duration, use_term_control):
+ def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, use_term_control):
assert num_tests_parallel >= 1
self.num_jobs = num_tests_parallel
self.tests_dir = tests_dir
self.tmpdir = tmpdir
- self.timeout_duration = timeout_duration
self.test_list = test_list
self.flags = flags
self.num_running = 0
@@ -537,10 +569,6 @@ class TestHandler:
time.sleep(.5)
for job in self.jobs:
(name, start_time, proc, testdir, log_out, log_err) = job
- if int(time.time() - start_time) > self.timeout_duration:
- # Timeout individual tests if timeout is specified (to stop
- # tests hanging and not providing useful output).
- proc.send_signal(signal.SIGINT)
if proc.poll() is not None:
log_out.seek(0), log_err.seek(0)
[stdout, stderr] = [log_file.read().decode('utf-8') for log_file in (log_out, log_err)]
@@ -609,7 +637,7 @@ class TestResult():
def check_script_prefixes():
"""Check that test scripts start with one of the allowed name prefixes."""
- good_prefixes_re = re.compile("(example|feature|interface|mempool|mining|p2p|rpc|wallet|tool)_")
+ good_prefixes_re = re.compile("^(example|feature|interface|mempool|mining|p2p|rpc|wallet|tool)_")
bad_script_names = [script for script in ALL_SCRIPTS if good_prefixes_re.match(script) is None]
if bad_script_names:
diff --git a/test/functional/tool_wallet.py b/test/functional/tool_wallet.py
index d2629ff1ed..b3d496dd51 100755
--- a/test/functional/tool_wallet.py
+++ b/test/functional/tool_wallet.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
"""Test bitcoin-wallet."""
diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py
index 1122daaf83..c7b19081c8 100755
--- a/test/functional/wallet_abandonconflict.py
+++ b/test/functional/wallet_abandonconflict.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 the abandontransaction RPC.
@@ -110,8 +110,8 @@ class AbandonConflictTest(BitcoinTestFramework):
assert_equal(newbalance, balance - signed3_change)
# Unconfirmed received funds that are not in mempool, also shouldn't show
# up in unconfirmed balance
- unconfbalance = self.nodes[0].getunconfirmedbalance() + self.nodes[0].getbalance()
- assert_equal(unconfbalance, newbalance)
+ balances = self.nodes[0].getbalances()['mine']
+ assert_equal(balances['untrusted_pending'] + balances['trusted'], newbalance)
# Also shouldn't show up in listunspent
assert not txABC2 in [utxo["txid"] for utxo in self.nodes[0].listunspent(0)]
balance = newbalance
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index f08606e622..68e22b7e86 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2019 The Bitcoin Core developers
+# Copyright (c) 2017-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 that the wallet can send and receive using all combinations of address types.
@@ -82,7 +82,7 @@ class AddressTypeTest(BitcoinTestFramework):
]
# whitelist all peers to speed up tx relay / mempool sync
for args in self.extra_args:
- args.append("-whitelist=127.0.0.1")
+ args.append("-whitelist=noban@127.0.0.1")
self.supports_cli = False
def skip_test_if_missing_module(self):
@@ -97,12 +97,9 @@ class AddressTypeTest(BitcoinTestFramework):
connect_nodes(self.nodes[i], j)
self.sync_all()
- def get_balances(self, confirmed=True):
- """Return a list of confirmed or unconfirmed balances."""
- if confirmed:
- return [self.nodes[i].getbalance() for i in range(4)]
- else:
- return [self.nodes[i].getunconfirmedbalance() for i in range(4)]
+ def get_balances(self, key='trusted'):
+ """Return a list of balances."""
+ return [self.nodes[i].getbalances()['mine'][key] for i in range(4)]
# Quick test of python bech32 implementation
def test_python_bech32(self, addr):
@@ -307,7 +304,7 @@ class AddressTypeTest(BitcoinTestFramework):
self.nodes[from_node].sendmany("", sends)
self.sync_mempools()
- unconf_balances = self.get_balances(False)
+ unconf_balances = self.get_balances('untrusted_pending')
self.log.debug("Check unconfirmed balances: {}".format(unconf_balances))
assert_equal(unconf_balances[from_node], 0)
for n, to_node in enumerate(range(from_node + 1, from_node + 4)):
diff --git a/test/functional/wallet_avoidreuse.py b/test/functional/wallet_avoidreuse.py
index 1ca02a695c..780cce9d02 100755
--- a/test/functional/wallet_avoidreuse.py
+++ b/test/functional/wallet_avoidreuse.py
@@ -70,7 +70,7 @@ class AvoidReuseTest(BitcoinTestFramework):
self.num_nodes = 2
# This test isn't testing txn relay/timing, so set whitelist on the
# peers for instant txn relay. This speeds up the test run time 2-3x.
- self.extra_args = [["-whitelist=127.0.0.1"]] * self.num_nodes
+ self.extra_args = [["-whitelist=noban@127.0.0.1"]] * self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -83,16 +83,21 @@ class AvoidReuseTest(BitcoinTestFramework):
self.nodes[0].generate(110)
self.sync_all()
+ self.test_change_remains_change(self.nodes[1])
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
- self.test_fund_send_fund_senddirty()
+ self.test_sending_from_reused_address_without_avoid_reuse()
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
- self.test_fund_send_fund_send("legacy")
+ self.test_sending_from_reused_address_fails("legacy")
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
- self.test_fund_send_fund_send("p2sh-segwit")
+ self.test_sending_from_reused_address_fails("p2sh-segwit")
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
- self.test_fund_send_fund_send("bech32")
+ self.test_sending_from_reused_address_fails("bech32")
reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
self.test_getbalances_used()
+ reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
+ self.test_full_destination_group_is_preferred()
+ reset_balance(self.nodes[1], self.nodes[0].getnewaddress())
+ self.test_all_destination_groups_are_used()
def test_persistence(self):
'''Test that wallet files persist the avoid_reuse flag.'''
@@ -128,7 +133,7 @@ class AvoidReuseTest(BitcoinTestFramework):
tempwallet = ".wallet_avoidreuse.py_test_immutable_wallet.dat"
# Create a wallet with disable_private_keys set; this should work
- self.nodes[1].createwallet(tempwallet, True)
+ self.nodes[1].createwallet(wallet_name=tempwallet, disable_private_keys=True)
w = self.nodes[1].get_wallet_rpc(tempwallet)
# Attempt to unset the disable_private_keys flag; this should not work
@@ -137,13 +142,37 @@ class AvoidReuseTest(BitcoinTestFramework):
# Unload temp wallet
self.nodes[1].unloadwallet(tempwallet)
- def test_fund_send_fund_senddirty(self):
+ def test_change_remains_change(self, node):
+ self.log.info("Test that change doesn't turn into non-change when spent")
+
+ reset_balance(node, node.getnewaddress())
+ addr = node.getnewaddress()
+ txid = node.sendtoaddress(addr, 1)
+ out = node.listunspent(minconf=0, query_options={'minimumAmount': 2})
+ assert_equal(len(out), 1)
+ assert_equal(out[0]['txid'], txid)
+ changeaddr = out[0]['address']
+
+ # Make sure it's starting out as change as expected
+ assert node.getaddressinfo(changeaddr)['ischange']
+ for logical_tx in node.listtransactions():
+ assert logical_tx.get('address') != changeaddr
+
+ # Spend it
+ reset_balance(node, node.getnewaddress())
+
+ # It should still be change
+ assert node.getaddressinfo(changeaddr)['ischange']
+ for logical_tx in node.listtransactions():
+ assert logical_tx.get('address') != changeaddr
+
+ def test_sending_from_reused_address_without_avoid_reuse(self):
'''
- Test the same as test_fund_send_fund_send, except send the 10 BTC with
+ Test the same as test_sending_from_reused_address_fails, except send the 10 BTC with
the avoid_reuse flag set to false. This means the 10 BTC send should succeed,
- where it fails in test_fund_send_fund_send.
+ where it fails in test_sending_from_reused_address_fails.
'''
- self.log.info("Test fund send fund send dirty")
+ self.log.info("Test sending from reused address with avoid_reuse=false")
fundaddr = self.nodes[1].getnewaddress()
retaddr = self.nodes[0].getnewaddress()
@@ -188,7 +217,7 @@ class AvoidReuseTest(BitcoinTestFramework):
assert_approx(self.nodes[1].getbalance(), 5, 0.001)
assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 5, 0.001)
- def test_fund_send_fund_send(self, second_addr_type):
+ def test_sending_from_reused_address_fails(self, second_addr_type):
'''
Test the simple case where [1] generates a new address A, then
[0] sends 10 BTC to A.
@@ -197,7 +226,7 @@ class AvoidReuseTest(BitcoinTestFramework):
[1] tries to spend 10 BTC (fails; dirty).
[1] tries to spend 4 BTC (succeeds; change address sufficient)
'''
- self.log.info("Test fund send fund send")
+ self.log.info("Test sending from reused {} address fails".format(second_addr_type))
fundaddr = self.nodes[1].getnewaddress(label="", address_type="legacy")
retaddr = self.nodes[0].getnewaddress()
@@ -220,43 +249,44 @@ class AvoidReuseTest(BitcoinTestFramework):
# getbalances should show no used, 5 btc trusted
assert_balances(self.nodes[1], mine={"used": 0, "trusted": 5})
- # For the second send, we transmute it to a related single-key address
- # to make sure it's also detected as re-use
- fund_spk = self.nodes[0].getaddressinfo(fundaddr)["scriptPubKey"]
- fund_decoded = self.nodes[0].decodescript(fund_spk)
- if second_addr_type == "p2sh-segwit":
- new_fundaddr = fund_decoded["segwit"]["p2sh-segwit"]
- elif second_addr_type == "bech32":
- new_fundaddr = fund_decoded["segwit"]["addresses"][0]
- else:
- new_fundaddr = fundaddr
- assert_equal(second_addr_type, "legacy")
-
- self.nodes[0].sendtoaddress(new_fundaddr, 10)
- self.nodes[0].generate(1)
- self.sync_all()
-
- # listunspent should show 2 total outputs (5, 10 btc), one unused (5), one reused (10)
- assert_unspent(self.nodes[1], total_count=2, total_sum=15, reused_count=1, reused_sum=10)
- # getbalances should show 10 used, 5 btc trusted
- assert_balances(self.nodes[1], mine={"used": 10, "trusted": 5})
-
- # node 1 should now have a balance of 5 (no dirty) or 15 (including dirty)
- assert_approx(self.nodes[1].getbalance(), 5, 0.001)
- assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 15, 0.001)
-
- assert_raises_rpc_error(-6, "Insufficient funds", self.nodes[1].sendtoaddress, retaddr, 10)
-
- self.nodes[1].sendtoaddress(retaddr, 4)
-
- # listunspent should show 2 total outputs (1, 10 btc), one unused (1), one reused (10)
- assert_unspent(self.nodes[1], total_count=2, total_sum=11, reused_count=1, reused_sum=10)
- # getbalances should show 10 used, 1 btc trusted
- assert_balances(self.nodes[1], mine={"used": 10, "trusted": 1})
-
- # node 1 should now have about 1 btc left (no dirty) and 11 (including dirty)
- assert_approx(self.nodes[1].getbalance(), 1, 0.001)
- assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 11, 0.001)
+ if not self.options.descriptors:
+ # For the second send, we transmute it to a related single-key address
+ # to make sure it's also detected as re-use
+ fund_spk = self.nodes[0].getaddressinfo(fundaddr)["scriptPubKey"]
+ fund_decoded = self.nodes[0].decodescript(fund_spk)
+ if second_addr_type == "p2sh-segwit":
+ new_fundaddr = fund_decoded["segwit"]["p2sh-segwit"]
+ elif second_addr_type == "bech32":
+ new_fundaddr = fund_decoded["segwit"]["addresses"][0]
+ else:
+ new_fundaddr = fundaddr
+ assert_equal(second_addr_type, "legacy")
+
+ self.nodes[0].sendtoaddress(new_fundaddr, 10)
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ # listunspent should show 2 total outputs (5, 10 btc), one unused (5), one reused (10)
+ assert_unspent(self.nodes[1], total_count=2, total_sum=15, reused_count=1, reused_sum=10)
+ # getbalances should show 10 used, 5 btc trusted
+ assert_balances(self.nodes[1], mine={"used": 10, "trusted": 5})
+
+ # node 1 should now have a balance of 5 (no dirty) or 15 (including dirty)
+ assert_approx(self.nodes[1].getbalance(), 5, 0.001)
+ assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 15, 0.001)
+
+ assert_raises_rpc_error(-6, "Insufficient funds", self.nodes[1].sendtoaddress, retaddr, 10)
+
+ self.nodes[1].sendtoaddress(retaddr, 4)
+
+ # listunspent should show 2 total outputs (1, 10 btc), one unused (1), one reused (10)
+ assert_unspent(self.nodes[1], total_count=2, total_sum=11, reused_count=1, reused_sum=10)
+ # getbalances should show 10 used, 1 btc trusted
+ assert_balances(self.nodes[1], mine={"used": 10, "trusted": 1})
+
+ # node 1 should now have about 1 btc left (no dirty) and 11 (including dirty)
+ assert_approx(self.nodes[1].getbalance(), 1, 0.001)
+ assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 11, 0.001)
def test_getbalances_used(self):
'''
@@ -288,5 +318,66 @@ class AvoidReuseTest(BitcoinTestFramework):
assert_unspent(self.nodes[1], total_count=2, total_sum=6, reused_count=1, reused_sum=1)
assert_balances(self.nodes[1], mine={"used": 1, "trusted": 5})
+ def test_full_destination_group_is_preferred(self):
+ '''
+ Test the case where [1] only has 11 outputs of 1 BTC in the same reused
+ address and tries to send a small payment of 0.5 BTC. The wallet
+ should use 10 outputs from the reused address as inputs and not a
+ single 1 BTC input, in order to join several outputs from the reused
+ address.
+ '''
+ self.log.info("Test that full destination groups are preferred in coin selection")
+
+ # Node under test should be empty
+ assert_equal(self.nodes[1].getbalance(avoid_reuse=False), 0)
+
+ new_addr = self.nodes[1].getnewaddress()
+ ret_addr = self.nodes[0].getnewaddress()
+
+ # Send 11 outputs of 1 BTC to the same, reused address in the wallet
+ for _ in range(11):
+ self.nodes[0].sendtoaddress(new_addr, 1)
+
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ # Sending a transaction that is smaller than each one of the
+ # available outputs
+ txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=0.5)
+ inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"]
+
+ # The transaction should use 10 inputs exactly
+ assert_equal(len(inputs), 10)
+
+ def test_all_destination_groups_are_used(self):
+ '''
+ Test the case where [1] only has 22 outputs of 1 BTC in the same reused
+ address and tries to send a payment of 20.5 BTC. The wallet
+ should use all 22 outputs from the reused address as inputs.
+ '''
+ self.log.info("Test that all destination groups are used")
+
+ # Node under test should be empty
+ assert_equal(self.nodes[1].getbalance(avoid_reuse=False), 0)
+
+ new_addr = self.nodes[1].getnewaddress()
+ ret_addr = self.nodes[0].getnewaddress()
+
+ # Send 22 outputs of 1 BTC to the same, reused address in the wallet
+ for _ in range(22):
+ self.nodes[0].sendtoaddress(new_addr, 1)
+
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ # Sending a transaction that needs to use the full groups
+ # of 10 inputs but also the incomplete group of 2 inputs.
+ txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=20.5)
+ inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"]
+
+ # The transaction should use 22 inputs exactly
+ assert_equal(len(inputs), 22)
+
+
if __name__ == '__main__':
AvoidReuseTest().main()
diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py
index 16c69f304a..9dd91b2495 100755
--- a/test/functional/wallet_backup.py
+++ b/test/functional/wallet_backup.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-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 the wallet backup features.
@@ -50,10 +50,10 @@ class WalletBackupTest(BitcoinTestFramework):
# nodes 1, 2,3 are spenders, let's give them a keypool=100
# whitelist all peers to speed up tx relay / mempool sync
self.extra_args = [
- ["-keypool=100", "-whitelist=127.0.0.1"],
- ["-keypool=100", "-whitelist=127.0.0.1"],
- ["-keypool=100", "-whitelist=127.0.0.1"],
- ["-whitelist=127.0.0.1"]
+ ["-whitelist=noban@127.0.0.1", "-keypool=100"],
+ ["-whitelist=noban@127.0.0.1", "-keypool=100"],
+ ["-whitelist=noban@127.0.0.1", "-keypool=100"],
+ ["-whitelist=noban@127.0.0.1"],
]
self.rpc_timeout = 120
diff --git a/test/functional/wallet_balance.py b/test/functional/wallet_balance.py
index a5f9a047ed..8efa66a856 100755
--- a/test/functional/wallet_balance.py
+++ b/test/functional/wallet_balance.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
"""Test the wallet balance RPC methods."""
@@ -107,7 +107,7 @@ class WalletTest(BitcoinTestFramework):
# First argument of getbalance must be set to "*"
assert_raises_rpc_error(-32, "dummy first argument must be excluded or set to \"*\"", self.nodes[1].getbalance, "")
- self.log.info("Test getbalance and getunconfirmedbalance with unconfirmed inputs")
+ self.log.info("Test balances with unconfirmed inputs")
# Before `test_balance()`, we have had two nodes with a balance of 50
# each and then we:
@@ -148,6 +148,18 @@ class WalletTest(BitcoinTestFramework):
def test_balances(*, fee_node_1=0):
+ # getbalances
+ expected_balances_0 = {'mine': {'immature': Decimal('0E-8'),
+ 'trusted': Decimal('9.99'), # change from node 0's send
+ 'untrusted_pending': Decimal('60.0')},
+ 'watchonly': {'immature': Decimal('5000'),
+ 'trusted': Decimal('50.0'),
+ 'untrusted_pending': Decimal('0E-8')}}
+ 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
+ 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
assert_equal(self.nodes[0].getbalance(), Decimal('9.99')) # change from node 0's send
assert_equal(self.nodes[1].getbalance(), Decimal('0')) # node 1's send had an unsafe input
@@ -160,11 +172,9 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[1].getbalance(minconf=1), Decimal('0'))
# getunconfirmedbalance
assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60')) # output of node 1's spend
- assert_equal(self.nodes[0].getbalances()['mine']['untrusted_pending'], Decimal('60'))
- assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], Decimal('60'))
-
assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('30') - fee_node_1) # Doesn't include output of node 0's send since it was spent
- assert_equal(self.nodes[1].getbalances()['mine']['untrusted_pending'], Decimal('30') - fee_node_1)
+ # getwalletinfo.unconfirmed_balance
+ assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], Decimal('60'))
assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"], Decimal('30') - fee_node_1)
test_balances(fee_node_1=Decimal('0.01'))
@@ -174,15 +184,19 @@ class WalletTest(BitcoinTestFramework):
self.nodes[0].sendrawtransaction(txs[1]['hex']) # sending on both nodes is faster than waiting for propagation
self.sync_all()
- self.log.info("Test getbalance and getunconfirmedbalance with conflicted unconfirmed inputs")
+ self.log.info("Test getbalance and getbalances.mine.untrusted_pending with conflicted unconfirmed inputs")
test_balances(fee_node_1=Decimal('0.02'))
self.nodes[1].generatetoaddress(1, ADDRESS_WATCHONLY)
self.sync_all()
# balances are correct after the transactions are confirmed
- assert_equal(self.nodes[0].getbalance(), Decimal('69.99')) # node 1's send plus change from node 0's send
- assert_equal(self.nodes[1].getbalance(), Decimal('29.98')) # change from node 0's send
+ balance_node0 = Decimal('69.99') # node 1's send plus change from node 0's send
+ balance_node1 = Decimal('29.98') # change from node 0's send
+ assert_equal(self.nodes[0].getbalances()['mine']['trusted'], balance_node0)
+ assert_equal(self.nodes[1].getbalances()['mine']['trusted'], balance_node1)
+ assert_equal(self.nodes[0].getbalance(), balance_node0)
+ assert_equal(self.nodes[1].getbalance(), balance_node1)
# Send total balance away from node 1
txs = create_transactions(self.nodes[1], self.nodes[0].getnewaddress(), Decimal('29.97'), [Decimal('0.01')])
@@ -200,13 +214,13 @@ class WalletTest(BitcoinTestFramework):
# check mempool transactions count for wallet unconfirmed balance after
# dynamically loading the wallet.
- before = self.nodes[1].getunconfirmedbalance()
+ before = self.nodes[1].getbalances()['mine']['untrusted_pending']
dst = self.nodes[1].getnewaddress()
self.nodes[1].unloadwallet('')
self.nodes[0].sendtoaddress(dst, 0.1)
self.sync_all()
self.nodes[1].loadwallet('')
- after = self.nodes[1].getunconfirmedbalance()
+ after = self.nodes[1].getbalances()['mine']['untrusted_pending']
assert_equal(before + Decimal('0.1'), after)
# Create 3 more wallet txs, where the last is not accepted to the
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 15746d312c..2dddbf2cf3 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -49,6 +49,7 @@ class WalletTest(BitcoinTestFramework):
return self.nodes[0].decoderawtransaction(txn)['vsize']
def run_test(self):
+
# Check that there's no UTXO on none of the nodes
assert_equal(len(self.nodes[0].listunspent()), 0)
assert_equal(len(self.nodes[1].listunspent()), 0)
@@ -219,7 +220,7 @@ 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']))
- self.start_node(3)
+ self.start_node(3, self.nodes[3].extra_args)
connect_nodes(self.nodes[0], 3)
self.sync_all()
@@ -315,57 +316,59 @@ class WalletTest(BitcoinTestFramework):
# This will raise an exception since generate does not accept a string
assert_raises_rpc_error(-1, "not an integer", self.nodes[0].generate, "2")
- # This will raise an exception for the invalid private key format
- assert_raises_rpc_error(-5, "Invalid private key encoding", self.nodes[0].importprivkey, "invalid")
+ if not self.options.descriptors:
- # This will raise an exception for importing an address with the PS2H flag
- temp_address = self.nodes[1].getnewaddress("", "p2sh-segwit")
- assert_raises_rpc_error(-5, "Cannot use the p2sh flag with an address - use a script instead", self.nodes[0].importaddress, temp_address, "label", False, True)
+ # This will raise an exception for the invalid private key format
+ assert_raises_rpc_error(-5, "Invalid private key encoding", self.nodes[0].importprivkey, "invalid")
- # This will raise an exception for attempting to dump the private key of an address you do not own
- assert_raises_rpc_error(-3, "Address does not refer to a key", self.nodes[0].dumpprivkey, temp_address)
+ # This will raise an exception for importing an address with the PS2H flag
+ temp_address = self.nodes[1].getnewaddress("", "p2sh-segwit")
+ assert_raises_rpc_error(-5, "Cannot use the p2sh flag with an address - use a script instead", self.nodes[0].importaddress, temp_address, "label", False, True)
- # This will raise an exception for attempting to get the private key of an invalid Bitcoin address
- assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].dumpprivkey, "invalid")
+ # This will raise an exception for attempting to dump the private key of an address you do not own
+ assert_raises_rpc_error(-3, "Address does not refer to a key", self.nodes[0].dumpprivkey, temp_address)
- # This will raise an exception for attempting to set a label for an invalid Bitcoin address
- assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].setlabel, "invalid address", "label")
+ # This will raise an exception for attempting to get the private key of an invalid Bitcoin address
+ assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].dumpprivkey, "invalid")
- # This will raise an exception for importing an invalid address
- assert_raises_rpc_error(-5, "Invalid Bitcoin address or script", self.nodes[0].importaddress, "invalid")
+ # This will raise an exception for attempting to set a label for an invalid Bitcoin address
+ assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].setlabel, "invalid address", "label")
- # This will raise an exception for attempting to import a pubkey that isn't in hex
- assert_raises_rpc_error(-5, "Pubkey must be a hex string", self.nodes[0].importpubkey, "not hex")
+ # This will raise an exception for importing an invalid address
+ assert_raises_rpc_error(-5, "Invalid Bitcoin address or script", self.nodes[0].importaddress, "invalid")
- # This will raise an exception for importing an invalid pubkey
- assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f")
+ # This will raise an exception for attempting to import a pubkey that isn't in hex
+ assert_raises_rpc_error(-5, "Pubkey must be a hex string", self.nodes[0].importpubkey, "not hex")
- # Import address and private key to check correct behavior of spendable unspents
- # 1. Send some coins to generate new UTXO
- address_to_import = self.nodes[2].getnewaddress()
- txid = self.nodes[0].sendtoaddress(address_to_import, 1)
- self.nodes[0].generate(1)
- self.sync_all(self.nodes[0:3])
+ # This will raise an exception for importing an invalid pubkey
+ assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f")
+
+ # Import address and private key to check correct behavior of spendable unspents
+ # 1. Send some coins to generate new UTXO
+ address_to_import = self.nodes[2].getnewaddress()
+ txid = self.nodes[0].sendtoaddress(address_to_import, 1)
+ self.nodes[0].generate(1)
+ self.sync_all(self.nodes[0:3])
- # 2. Import address from node2 to node1
- self.nodes[1].importaddress(address_to_import)
+ # 2. Import address from node2 to node1
+ self.nodes[1].importaddress(address_to_import)
- # 3. Validate that the imported address is watch-only on node1
- assert self.nodes[1].getaddressinfo(address_to_import)["iswatchonly"]
+ # 3. Validate that the imported address is watch-only on node1
+ assert self.nodes[1].getaddressinfo(address_to_import)["iswatchonly"]
- # 4. Check that the unspents after import are not spendable
- assert_array_result(self.nodes[1].listunspent(),
- {"address": address_to_import},
- {"spendable": False})
+ # 4. Check that the unspents after import are not spendable
+ assert_array_result(self.nodes[1].listunspent(),
+ {"address": address_to_import},
+ {"spendable": False})
- # 5. Import private key of the previously imported address on node1
- priv_key = self.nodes[2].dumpprivkey(address_to_import)
- self.nodes[1].importprivkey(priv_key)
+ # 5. Import private key of the previously imported address on node1
+ priv_key = self.nodes[2].dumpprivkey(address_to_import)
+ self.nodes[1].importprivkey(priv_key)
- # 6. Check that the unspents are now spendable on node1
- assert_array_result(self.nodes[1].listunspent(),
- {"address": address_to_import},
- {"spendable": True})
+ # 6. Check that the unspents are now spendable on node1
+ assert_array_result(self.nodes[1].listunspent(),
+ {"address": address_to_import},
+ {"spendable": True})
# Mine a block from node0 to an address from node1
coinbase_addr = self.nodes[1].getnewaddress()
@@ -460,7 +463,8 @@ class WalletTest(BitcoinTestFramework):
# Try with walletrejectlongchains
# Double chain limit but require combining inputs, so we pass SelectCoinsMinConf
self.stop_node(0)
- self.start_node(0, extra_args=["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)])
+ extra_args = ["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)]
+ self.start_node(0, extra_args=extra_args)
# wait for loadmempool
timeout = 10
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index 4eb0d19a4f..9ba23db42d 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2019 The Bitcoin Core developers
+# Copyright (c) 2016-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 the bumpfee RPC.
@@ -23,13 +23,20 @@ from test_framework.util import (
assert_equal,
assert_greater_than,
assert_raises_rpc_error,
- connect_nodes,
hex_str_to_bytes,
)
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
+
+
class BumpFeeTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
@@ -37,7 +44,6 @@ class BumpFeeTest(BitcoinTestFramework):
self.extra_args = [[
"-walletrbf={}".format(i),
"-mintxfee=0.00002",
- "-deprecatedrpc=totalFee",
"-addresstype=bech32",
] for i in range(self.num_nodes)]
@@ -49,9 +55,6 @@ class BumpFeeTest(BitcoinTestFramework):
self.nodes[1].encryptwallet(WALLET_PASSPHRASE)
self.nodes[1].walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
- connect_nodes(self.nodes[0], 1)
- self.sync_all()
-
peer_node, rbf_node = self.nodes
rbf_node_address = rbf_node.getnewaddress()
@@ -71,34 +74,33 @@ class BumpFeeTest(BitcoinTestFramework):
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)
- test_segwit_bumpfee_succeeds(rbf_node, dest_address)
- test_nonrbf_bumpfee_fails(peer_node, dest_address)
- test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address)
- test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
- test_small_output_fails(rbf_node, dest_address)
- test_dust_to_fee(rbf_node, dest_address)
- test_settxfee(rbf_node, dest_address)
+ test_segwit_bumpfee_succeeds(self, rbf_node, dest_address)
+ test_nonrbf_bumpfee_fails(self, peer_node, dest_address)
+ test_notmine_bumpfee_fails(self, rbf_node, peer_node, dest_address)
+ test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_address)
+ test_dust_to_fee(self, rbf_node, dest_address)
test_watchonly_psbt(self, peer_node, rbf_node, dest_address)
- test_rebumping(rbf_node, dest_address)
- test_rebumping_not_replaceable(rbf_node, dest_address)
- test_unconfirmed_not_spendable(rbf_node, rbf_node_address)
- test_bumpfee_metadata(rbf_node, dest_address)
- test_locked_wallet_fails(rbf_node, dest_address)
- test_change_script_match(rbf_node, dest_address)
+ test_rebumping(self, rbf_node, dest_address)
+ test_rebumping_not_replaceable(self, rbf_node, dest_address)
+ test_unconfirmed_not_spendable(self, rbf_node, rbf_node_address)
+ test_bumpfee_metadata(self, rbf_node, dest_address)
+ test_locked_wallet_fails(self, rbf_node, dest_address)
+ test_change_script_match(self, rbf_node, dest_address)
+ test_settxfee(self, rbf_node, dest_address)
test_maxtxfee_fails(self, rbf_node, dest_address)
# These tests wipe out a number of utxos that are expected in other tests
- test_small_output_with_feerate_succeeds(rbf_node, dest_address)
- test_no_more_inputs_fails(rbf_node, dest_address)
- self.log.info("Success")
+ test_small_output_with_feerate_succeeds(self, rbf_node, dest_address)
+ test_no_more_inputs_fails(self, rbf_node, dest_address)
def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
+ self.log.info('Test simple bumpfee: {}'.format(mode))
rbfid = spend_one_input(rbf_node, dest_address)
rbftx = rbf_node.gettransaction(rbfid)
self.sync_mempools((rbf_node, peer_node))
assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
if mode == "fee_rate":
- bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate":0.0015})
+ bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": NORMAL})
else:
bumped_tx = rbf_node.bumpfee(rbfid)
assert_equal(bumped_tx["errors"], [])
@@ -118,24 +120,27 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
assert_equal(oldwtx["replaced_by_txid"], bumped_tx["txid"])
assert_equal(bumpedwtx["replaces_txid"], rbfid)
+
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, "confTarget can't be set with totalFee or 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})
- assert_raises_rpc_error(-8, "confTarget can't be set with totalFee or fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"totalFee":0.00001, "confTarget":1})
- assert_raises_rpc_error(-8, "fee_rate can't be set along with totalFee.", rbf_node.bumpfee, rbfid, {"fee_rate":0.00001, "totalFee":0.001})
+ assert_raises_rpc_error(-8, "confTarget 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})
# 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":0.00001000})
+ 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(-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":1})
+ assert_raises_rpc_error(-4, "is too high (cannot be higher than", rbf_node.bumpfee, rbfid, {"fee_rate": TOO_HIGH})
-def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
+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.
@@ -165,14 +170,14 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
assert rbfid not in rbf_node.getrawmempool()
-def test_nonrbf_bumpfee_fails(peer_node, dest_address):
- # cannot replace a non RBF transaction (from node which did not enable RBF)
+def test_nonrbf_bumpfee_fails(self, peer_node, dest_address):
+ self.log.info('Test that we cannot replace a non RBF transaction')
not_rbfid = peer_node.sendtoaddress(dest_address, Decimal("0.00090000"))
assert_raises_rpc_error(-4, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid)
-def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address):
- # cannot bump fee unless the tx has only inputs that we own.
+def test_notmine_bumpfee_fails(self, rbf_node, peer_node, dest_address):
+ self.log.info('Test that it cannot bump fee if non-owned inputs are included')
# here, the rbftx has a peer_node coin and then adds a rbf_node input
# Note that this test depends upon the RPC code checking input ownership prior to change outputs
# (since it can't use fundrawtransaction, it lacks a proper change output)
@@ -192,8 +197,8 @@ def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address):
rbf_node.bumpfee, rbfid)
-def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address):
- # cannot bump fee if the transaction has a descendant
+def test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_address):
+ self.log.info('Test that fee cannot be bumped when it has descendant')
# parent is send-to-self, so we don't have to check which output is change when creating the child tx
parent_id = spend_one_input(rbf_node, rbf_node_address)
tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.00020000})
@@ -201,15 +206,9 @@ def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
rbf_node.sendrawtransaction(tx["hex"])
assert_raises_rpc_error(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
-def test_small_output_fails(rbf_node, dest_address):
- # cannot bump fee with a too-small output
- rbfid = spend_one_input(rbf_node, dest_address)
- rbf_node.bumpfee(rbfid, {"totalFee": 50000})
-
- rbfid = spend_one_input(rbf_node, dest_address)
- assert_raises_rpc_error(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 50001})
-def test_small_output_with_feerate_succeeds(rbf_node, dest_address):
+def test_small_output_with_feerate_succeeds(self, rbf_node, dest_address):
+ self.log.info('Testing small output with feerate bump succeeds')
# Make sure additional inputs exist
rbf_node.generatetoaddress(101, rbf_node.getnewaddress())
@@ -217,9 +216,9 @@ def test_small_output_with_feerate_succeeds(rbf_node, dest_address):
input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
assert_equal(len(input_list), 1)
original_txin = input_list[0]
- # Keep bumping until we out-spend change output
+ self.log.info('Keep bumping until transaction fee out-spends non-destination value')
tx_fee = 0
- while tx_fee < Decimal("0.0005"):
+ while True:
input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
new_item = list(input_list)[0]
assert_equal(len(input_list), 1)
@@ -231,7 +230,11 @@ def test_small_output_with_feerate_succeeds(rbf_node, dest_address):
assert rbfid not in raw_pool
assert rbfid_new in raw_pool
rbfid = rbfid_new
- tx_fee = rbfid_new_details["origfee"]
+ tx_fee = rbfid_new_details["fee"]
+
+ # Total value from input not going to destination
+ if tx_fee > Decimal('0.00050000'):
+ break
# input(s) have been added
final_input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
@@ -244,20 +247,31 @@ def test_small_output_with_feerate_succeeds(rbf_node, dest_address):
rbf_node.generatetoaddress(1, rbf_node.getnewaddress())
assert_equal(rbf_node.gettransaction(rbfid)["confirmations"], 1)
-def test_dust_to_fee(rbf_node, dest_address):
- # check that if output is reduced to dust, it will be converted to fee
- # the bumped tx sets fee=49,900, but it converts to 50,000
+
+def test_dust_to_fee(self, rbf_node, dest_address):
+ self.log.info('Test that bumped output that is dust is dropped to fee')
rbfid = spend_one_input(rbf_node, dest_address)
fulltx = rbf_node.getrawtransaction(rbfid, 1)
- # (31-vbyte p2wpkh output size + 67-vbyte p2wpkh spend estimate) * 10k(discard_rate) / 1000 = 980
- bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 50000 - 980})
+ # The DER formatting used by Bitcoin to serialize ECDSA signatures means that signatures can have a
+ # variable size of 70-72 bytes (or possibly even less), with most being 71 or 72 bytes. The signature
+ # in the witness is divided by 4 for the vsize, so this variance can take the weight across a 4-byte
+ # 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.
+ # 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})
full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1)
assert_equal(bumped_tx["fee"], Decimal("0.00050000"))
assert_equal(len(fulltx["vout"]), 2)
assert_equal(len(full_bumped_tx["vout"]), 1) # change output is eliminated
+ assert_equal(full_bumped_tx["vout"][0]['value'], Decimal("0.00050000"))
-def test_settxfee(rbf_node, dest_address):
+def test_settxfee(self, rbf_node, dest_address):
+ self.log.info('Test settxfee')
assert_raises_rpc_error(-8, "txfee cannot be less than min relay tx fee", rbf_node.settxfee, Decimal('0.000005'))
assert_raises_rpc_error(-8, "txfee cannot be less than wallet min fee", rbf_node.settxfee, Decimal('0.000015'))
# check that bumpfee reacts correctly to the use of settxfee (paytxfee)
@@ -271,18 +285,28 @@ def test_settxfee(rbf_node, dest_address):
assert_greater_than(Decimal("0.00001000"), abs(requested_feerate - actual_feerate))
rbf_node.settxfee(Decimal("0.00000000")) # unset paytxfee
+ # check that settxfee respects -maxtxfee
+ self.restart_node(1, ['-maxtxfee=0.000025'] + self.extra_args[1])
+ assert_raises_rpc_error(-8, "txfee cannot be more than wallet max tx fee", rbf_node.settxfee, Decimal('0.00003'))
+ self.restart_node(1, self.extra_args[1])
+ rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
+
-def test_maxtxfee_fails(test, rbf_node, dest_address):
+def test_maxtxfee_fails(self, rbf_node, dest_address):
+ self.log.info('Test that bumpfee fails when it hits -maxtxfee')
# size of bumped transaction (p2wpkh, 1 input, 2 outputs): 141 vbytes
- # expected bumping feerate of 20 sats/vbyte => 141*20 sats = 0.00002820 btc
- test.restart_node(1, ['-maxtxfee=0.000025'] + test.extra_args[1])
+ # expected bump fee of 141 vbytes * 0.00200000 BTC / 1000 vbytes = 0.00002820 BTC
+ # which exceeds maxtxfee and is expected to raise
+ self.restart_node(1, ['-maxtxfee=0.000025'] + self.extra_args[1])
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
rbfid = spend_one_input(rbf_node, dest_address)
assert_raises_rpc_error(-4, "Unable to create transaction: Fee exceeds maximum configured by -maxtxfee", rbf_node.bumpfee, rbfid)
- test.restart_node(1, test.extra_args[1])
+ self.restart_node(1, self.extra_args[1])
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
-def test_watchonly_psbt(test, peer_node, rbf_node, dest_address):
+
+def test_watchonly_psbt(self, peer_node, rbf_node, dest_address):
+ self.log.info('Test that PSBT is returned for bumpfee in watchonly wallets')
priv_rec_desc = "wpkh([00000001/84'/1'/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0/*)#rweraev0"
pub_rec_desc = rbf_node.getdescriptorinfo(priv_rec_desc)["descriptor"]
priv_change_desc = "wpkh([00000001/84'/1'/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/*)#j6uzqvuh"
@@ -315,12 +339,11 @@ def test_watchonly_psbt(test, peer_node, rbf_node, dest_address):
result = watcher.importmulti([{
"desc": pub_rec_desc,
"timestamp": 0,
- "range": [0,10],
+ "range": [0, 10],
"internal": False,
"keypool": True,
"watchonly": True
- },
- {
+ }, {
"desc": pub_change_desc,
"timestamp": 0,
"range": [0, 10],
@@ -334,17 +357,17 @@ def test_watchonly_psbt(test, peer_node, rbf_node, dest_address):
funding_address2 = watcher.getnewaddress(address_type='bech32')
peer_node.sendmany("", {funding_address1: 0.001, funding_address2: 0.001})
peer_node.generate(1)
- test.sync_all()
+ 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, {"feeRate": 0.00001}, 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"])
assert_equal(len(watcher.decodepsbt(psbt)["tx"]["vin"]), 1)
# Bump fee, obnoxiously high to add additional watchonly input
- bumped_psbt = watcher.bumpfee(original_txid, {"fee_rate":0.005})
+ bumped_psbt = watcher.bumpfee(original_txid, {"fee_rate": HIGH})
assert_greater_than(len(watcher.decodepsbt(bumped_psbt['psbt'])["tx"]["vin"]), 1)
assert "txid" not in bumped_psbt
assert_equal(bumped_psbt["origfee"], -watcher.gettransaction(original_txid)["fee"])
@@ -363,24 +386,25 @@ def test_watchonly_psbt(test, peer_node, rbf_node, dest_address):
rbf_node.unloadwallet("watcher")
rbf_node.unloadwallet("signer")
-def test_rebumping(rbf_node, dest_address):
- # check that re-bumping the original tx fails, but bumping the bumper succeeds
+
+def test_rebumping(self, rbf_node, dest_address):
+ self.log.info('Test that re-bumping the original tx fails, but bumping successor works')
rbfid = spend_one_input(rbf_node, dest_address)
- bumped = rbf_node.bumpfee(rbfid, {"totalFee": 2000})
- assert_raises_rpc_error(-4, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 3000})
- rbf_node.bumpfee(bumped["txid"], {"totalFee": 3000})
+ bumped = rbf_node.bumpfee(rbfid, {"fee_rate": ECONOMICAL})
+ assert_raises_rpc_error(-4, "already bumped", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL})
+ rbf_node.bumpfee(bumped["txid"], {"fee_rate": NORMAL})
-def test_rebumping_not_replaceable(rbf_node, dest_address):
- # check that re-bumping a non-replaceable bump tx fails
+def test_rebumping_not_replaceable(self, rbf_node, dest_address):
+ self.log.info('Test that re-bumping non-replaceable fails')
rbfid = spend_one_input(rbf_node, dest_address)
- bumped = rbf_node.bumpfee(rbfid, {"totalFee": 10000, "replaceable": False})
+ bumped = rbf_node.bumpfee(rbfid, {"fee_rate": ECONOMICAL, "replaceable": False})
assert_raises_rpc_error(-4, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"],
- {"totalFee": 20000})
+ {"fee_rate": NORMAL})
-def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):
- # check that unconfirmed outputs from bumped transactions are not spendable
+def test_unconfirmed_not_spendable(self, rbf_node, rbf_node_address):
+ self.log.info('Test that unconfirmed outputs from bumped txns are not spendable')
rbfid = spend_one_input(rbf_node, rbf_node_address)
rbftx = rbf_node.gettransaction(rbfid)["hex"]
assert rbfid in rbf_node.getrawmempool()
@@ -418,7 +442,8 @@ def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):
if t["txid"] == rbfid and t["address"] == rbf_node_address and t["spendable"]), 1)
-def test_bumpfee_metadata(rbf_node, dest_address):
+def test_bumpfee_metadata(self, rbf_node, dest_address):
+ self.log.info('Test that bumped txn metadata persists to new txn record')
assert(rbf_node.getbalance() < 49)
rbf_node.generatetoaddress(101, rbf_node.getnewaddress())
rbfid = rbf_node.sendtoaddress(dest_address, 49, "comment value", "to value")
@@ -428,15 +453,18 @@ def test_bumpfee_metadata(rbf_node, dest_address):
assert_equal(bumped_wtx["to"], "to value")
-def test_locked_wallet_fails(rbf_node, dest_address):
+def test_locked_wallet_fails(self, rbf_node, dest_address):
+ self.log.info('Test that locked wallet cannot bump txn')
rbfid = spend_one_input(rbf_node, dest_address)
rbf_node.walletlock()
assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first.",
rbf_node.bumpfee, rbfid)
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
-def test_change_script_match(rbf_node, dest_address):
- """Test that the same change addresses is used for the replacement transaction when possible."""
+
+def test_change_script_match(self, rbf_node, dest_address):
+ self.log.info('Test that the same change addresses is used for the replacement transaction when possible')
+
def get_change_address(tx):
tx_details = rbf_node.getrawtransaction(tx, 1)
txout_addresses = [txout['scriptPubKey']['addresses'][0] for txout in tx_details["vout"]]
@@ -448,11 +476,12 @@ def test_change_script_match(rbf_node, dest_address):
assert_equal(len(change_addresses), 1)
# Now find that address in each subsequent tx, and no other change
- bumped_total_tx = rbf_node.bumpfee(rbfid, {"totalFee": 2000})
+ bumped_total_tx = rbf_node.bumpfee(rbfid, {"fee_rate": ECONOMICAL})
assert_equal(change_addresses, get_change_address(bumped_total_tx['txid']))
bumped_rate_tx = rbf_node.bumpfee(bumped_total_tx["txid"])
assert_equal(change_addresses, get_change_address(bumped_rate_tx['txid']))
+
def spend_one_input(node, dest_address, change_size=Decimal("0.00049000")):
tx_input = dict(
sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000")))
@@ -464,6 +493,7 @@ def spend_one_input(node, dest_address, change_size=Decimal("0.00049000")):
txid = node.sendrawtransaction(signedtx["hex"])
return txid
+
def submit_block_with_tx(node, tx):
ctx = CTransaction()
ctx.deserialize(io.BytesIO(hex_str_to_bytes(tx)))
@@ -480,12 +510,15 @@ def submit_block_with_tx(node, tx):
node.submitblock(block.serialize().hex())
return block
-def test_no_more_inputs_fails(rbf_node, dest_address):
+
+def test_no_more_inputs_fails(self, rbf_node, dest_address):
+ self.log.info('Test that bumpfee fails when there are no available confirmed outputs')
# feerate rbf requires confirmed outputs when change output doesn't exist or is insufficient
rbf_node.generatetoaddress(1, dest_address)
# spend all funds, no change output
rbfid = rbf_node.sendtoaddress(rbf_node.getnewaddress(), rbf_node.getbalance(), "", "", True)
assert_raises_rpc_error(-4, "Unable to create transaction: Insufficient funds", rbf_node.bumpfee, rbfid)
+
if __name__ == "__main__":
BumpFeeTest().main()
diff --git a/test/functional/wallet_bumpfee_totalfee_deprecation.py b/test/functional/wallet_bumpfee_totalfee_deprecation.py
deleted file mode 100755
index b8e097c32e..0000000000
--- a/test/functional/wallet_bumpfee_totalfee_deprecation.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2019 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Test deprecation of passing `totalFee` to the bumpfee RPC."""
-from decimal import Decimal
-
-from test_framework.messages import BIP125_SEQUENCE_NUMBER
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_raises_rpc_error
-
-class BumpFeeWithTotalFeeArgumentDeprecationTest(BitcoinTestFramework):
- def set_test_params(self):
- self.num_nodes = 2
- self.extra_args = [[
- "-walletrbf={}".format(i),
- "-mintxfee=0.00002",
- ] for i in range(self.num_nodes)]
-
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
-
- def run_test(self):
- peer_node, rbf_node = self.nodes
- peer_node.generate(110)
- self.sync_all()
- peer_node.sendtoaddress(rbf_node.getnewaddress(), 0.001)
- self.sync_all()
- peer_node.generate(1)
- self.sync_all()
- rbfid = spend_one_input(rbf_node, peer_node.getnewaddress())
-
- self.log.info("Testing bumpfee with totalFee argument raises RPC error with deprecation message")
- assert_raises_rpc_error(
- -8,
- "totalFee argument has been deprecated and will be removed in 0.20. " +
- "Please use -deprecatedrpc=totalFee to continue using this argument until removal.",
- rbf_node.bumpfee, rbfid, {"totalFee": 2000})
-
- self.log.info("Testing bumpfee without totalFee argument does not raise")
- rbf_node.bumpfee(rbfid)
-
-def spend_one_input(node, dest_address, change_size=Decimal("0.00049000")):
- tx_input = dict(sequence=BIP125_SEQUENCE_NUMBER,
- **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000")))
- destinations = {dest_address: Decimal("0.00050000")}
- destinations[node.getrawchangeaddress()] = change_size
- rawtx = node.createrawtransaction([tx_input], destinations)
- signedtx = node.signrawtransactionwithwallet(rawtx)
- txid = node.sendrawtransaction(signedtx["hex"])
- return txid
-
-if __name__ == "__main__":
- BumpFeeWithTotalFeeArgumentDeprecationTest().main()
diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py
index 048b3127ff..48c0fcb731 100755
--- a/test/functional/wallet_createwallet.py
+++ b/test/functional/wallet_createwallet.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
"""Test createwallet arguments.
@@ -79,7 +79,7 @@ class CreateWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w4.getnewaddress)
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', 2)
+ w4.walletpassphrase('pass', 60)
w4.sethdseed()
w4.getnewaddress()
w4.getrawchangeaddress()
@@ -99,7 +99,7 @@ class CreateWalletTest(BitcoinTestFramework):
self.nodes[0].createwallet(wallet_name='wblank', disable_private_keys=False, blank=True, passphrase='thisisapassphrase')
wblank = node.get_wallet_rpc('wblank')
assert_raises_rpc_error(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.", wblank.signmessage, "needanargument", "test")
- wblank.walletpassphrase('thisisapassphrase', 10)
+ wblank.walletpassphrase('thisisapassphrase', 60)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", wblank.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", wblank.getrawchangeaddress)
@@ -108,7 +108,7 @@ class CreateWalletTest(BitcoinTestFramework):
self.nodes[0].createwallet(wallet_name='w6', disable_private_keys=False, blank=False, passphrase='thisisapassphrase')
w6 = node.get_wallet_rpc('w6')
assert_raises_rpc_error(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.", w6.signmessage, "needanargument", "test")
- w6.walletpassphrase('thisisapassphrase', 10)
+ w6.walletpassphrase('thisisapassphrase', 60)
w6.signmessage(w6.getnewaddress('', 'legacy'), "test")
w6.keypoolrefill(1)
# There should only be 1 key
@@ -119,12 +119,12 @@ class CreateWalletTest(BitcoinTestFramework):
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.')
w7 = node.get_wallet_rpc('w7')
- assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10)
+ assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 60)
self.log.info('Test making a wallet with avoid reuse flag')
self.nodes[0].createwallet('w8', False, False, '', True) # Use positional arguments to check for bug where avoid_reuse could not be set for wallets without needing them to be encrypted
w8 = node.get_wallet_rpc('w8')
- assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10)
+ assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 60)
assert_equal(w8.getwalletinfo()["avoid_reuse"], True)
self.log.info('Using a passphrase with private keys disabled returns error')
diff --git a/test/functional/wallet_descriptor.py b/test/functional/wallet_descriptor.py
new file mode 100755
index 0000000000..289ccf43ec
--- /dev/null
+++ b/test/functional/wallet_descriptor.py
@@ -0,0 +1,144 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test descriptor wallet function."""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error
+)
+
+
+class WalletDescriptorTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+ self.extra_args = [['-keypool=100']]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def run_test(self):
+ # Make a descriptor wallet
+ self.log.info("Making a descriptor wallet")
+ self.nodes[0].createwallet(wallet_name="desc1", descriptors=True)
+ self.nodes[0].unloadwallet("")
+
+ # 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['keypoolsize'], 300)
+ assert_equal(wallet_info['keypoolsize_hd_internal'], 300)
+ assert 'keypoololdest' not in wallet_info
+
+ # Check that getnewaddress works
+ self.log.info("Test that getnewaddress and getrawchangeaddress work")
+ addr = self.nodes[0].getnewaddress("", "legacy")
+ addr_info = self.nodes[0].getaddressinfo(addr)
+ assert addr_info['desc'].startswith('pkh(')
+ assert_equal(addr_info['hdkeypath'], 'm/44\'/1\'/0\'/0/0')
+
+ addr = self.nodes[0].getnewaddress("", "p2sh-segwit")
+ addr_info = self.nodes[0].getaddressinfo(addr)
+ assert addr_info['desc'].startswith('sh(wpkh(')
+ assert_equal(addr_info['hdkeypath'], 'm/49\'/1\'/0\'/0/0')
+
+ addr = self.nodes[0].getnewaddress("", "bech32")
+ addr_info = self.nodes[0].getaddressinfo(addr)
+ assert addr_info['desc'].startswith('wpkh(')
+ assert_equal(addr_info['hdkeypath'], 'm/84\'/1\'/0\'/0/0')
+
+ # Check that getrawchangeaddress works
+ addr = self.nodes[0].getrawchangeaddress("legacy")
+ addr_info = self.nodes[0].getaddressinfo(addr)
+ assert addr_info['desc'].startswith('pkh(')
+ assert_equal(addr_info['hdkeypath'], 'm/44\'/1\'/0\'/1/0')
+
+ addr = self.nodes[0].getrawchangeaddress("p2sh-segwit")
+ addr_info = self.nodes[0].getaddressinfo(addr)
+ assert addr_info['desc'].startswith('sh(wpkh(')
+ assert_equal(addr_info['hdkeypath'], 'm/49\'/1\'/0\'/1/0')
+
+ addr = self.nodes[0].getrawchangeaddress("bech32")
+ addr_info = self.nodes[0].getaddressinfo(addr)
+ assert addr_info['desc'].startswith('wpkh(')
+ assert_equal(addr_info['hdkeypath'], 'm/84\'/1\'/0\'/1/0')
+
+ # Make a wallet to receive coins at
+ self.nodes[0].createwallet(wallet_name="desc2", descriptors=True)
+ recv_wrpc = self.nodes[0].get_wallet_rpc("desc2")
+ send_wrpc = self.nodes[0].get_wallet_rpc("desc1")
+
+ # Generate some coins
+ send_wrpc.generatetoaddress(101, send_wrpc.getnewaddress())
+
+ # Make transactions
+ self.log.info("Test sending and receiving")
+ addr = recv_wrpc.getnewaddress()
+ send_wrpc.sendtoaddress(addr, 10)
+
+ # Make sure things are disabled
+ self.log.info("Test disabled RPCs")
+ assert_raises_rpc_error(-4, "This type of wallet does not support this command", recv_wrpc.rpc.importprivkey, "cVpF924EspNh8KjYsfhgY96mmxvT6DgdWiTYMtMjuM74hJaU5psW")
+ assert_raises_rpc_error(-4, "This type of wallet does not support this command", recv_wrpc.rpc.importpubkey, send_wrpc.getaddressinfo(send_wrpc.getnewaddress()))
+ assert_raises_rpc_error(-4, "This type of wallet does not support this command", recv_wrpc.rpc.importaddress, recv_wrpc.getnewaddress())
+ assert_raises_rpc_error(-4, "This type of wallet does not support this command", recv_wrpc.rpc.importmulti, [])
+ assert_raises_rpc_error(-4, "This type of wallet does not support this command", recv_wrpc.rpc.addmultisigaddress, 1, [recv_wrpc.getnewaddress()])
+ assert_raises_rpc_error(-4, "This type of wallet does not support this command", recv_wrpc.rpc.dumpprivkey, recv_wrpc.getnewaddress())
+ assert_raises_rpc_error(-4, "This type of wallet does not support this command", recv_wrpc.rpc.dumpwallet, 'wallet.dump')
+ assert_raises_rpc_error(-4, "This type of wallet does not support this command", recv_wrpc.rpc.importwallet, 'wallet.dump')
+ assert_raises_rpc_error(-4, "This type of wallet does not support this command", recv_wrpc.rpc.sethdseed)
+
+ self.log.info("Test encryption")
+ # Get the master fingerprint before encrypt
+ info1 = send_wrpc.getaddressinfo(send_wrpc.getnewaddress())
+
+ # Encrypt wallet 0
+ send_wrpc.encryptwallet('pass')
+ send_wrpc.walletpassphrase('pass', 10)
+ addr = send_wrpc.getnewaddress()
+ info2 = send_wrpc.getaddressinfo(addr)
+ assert info1['hdmasterfingerprint'] != info2['hdmasterfingerprint']
+ send_wrpc.walletlock()
+ assert 'hdmasterfingerprint' in send_wrpc.getaddressinfo(send_wrpc.getnewaddress())
+ info3 = send_wrpc.getaddressinfo(addr)
+ assert_equal(info2['desc'], info3['desc'])
+
+ self.log.info("Test that getnewaddress still works after keypool is exhausted in an encrypted wallet")
+ for i in range(0, 500):
+ send_wrpc.getnewaddress()
+
+ self.log.info("Test that unlock is needed when deriving only hardened keys in an encrypted wallet")
+ send_wrpc.walletpassphrase('pass', 10)
+ send_wrpc.importdescriptors([{
+ "desc": "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/*h)#y4dfsj7n",
+ "timestamp": "now",
+ "range": [0,10],
+ "active": True
+ }])
+ send_wrpc.walletlock()
+ # Exhaust keypool of 100
+ for i in range(0, 100):
+ send_wrpc.getnewaddress(address_type='bech32')
+ # This should now error
+ assert_raises_rpc_error(-12, "Keypool ran out, please call keypoolrefill first", send_wrpc.getnewaddress, '', 'bech32')
+
+ self.log.info("Test born encrypted wallets")
+ self.nodes[0].createwallet('desc_enc', False, False, 'pass', False, True)
+ enc_rpc = self.nodes[0].get_wallet_rpc('desc_enc')
+ enc_rpc.getnewaddress() # Makes sure that we can get a new address from a born encrypted wallet
+
+ self.log.info("Test blank descriptor wallets")
+ self.nodes[0].createwallet(wallet_name='desc_blank', blank=True, descriptors=True)
+ blank_rpc = self.nodes[0].get_wallet_rpc('desc_blank')
+ assert_raises_rpc_error(-4, 'This wallet has no available keys', blank_rpc.getnewaddress)
+
+ self.log.info("Test descriptor wallet with disabled private keys")
+ self.nodes[0].createwallet(wallet_name='desc_no_priv', disable_private_keys=True, descriptors=True)
+ nopriv_rpc = self.nodes[0].get_wallet_rpc('desc_no_priv')
+ assert_raises_rpc_error(-4, 'This wallet has no available keys', nopriv_rpc.getnewaddress)
+
+if __name__ == '__main__':
+ WalletDescriptorTest().main ()
diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py
index a39dfc7895..cc349c7bc5 100755
--- a/test/functional/wallet_dump.py
+++ b/test/functional/wallet_dump.py
@@ -1,9 +1,11 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2019 The Bitcoin Core developers
+# Copyright (c) 2016-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 the dumpwallet RPC."""
+import datetime
import os
+import time
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -18,6 +20,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
Also check that the old hd_master is inactive
"""
with open(file_name, encoding='utf8') as inputfile:
+ found_comments = []
found_legacy_addr = 0
found_p2sh_segwit_addr = 0
found_bech32_addr = 0
@@ -26,8 +29,12 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_addr_rsv = 0
hd_master_addr_ret = None
for line in inputfile:
- # only read non comment lines
- if line[0] != "#" and len(line) > 10:
+ line = line.strip()
+ if not line:
+ continue
+ if line[0] == '#':
+ found_comments.append(line)
+ else:
# split out some data
key_date_label, comment = line.split("#")
key_date_label = key_date_label.split(" ")
@@ -82,7 +89,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_script_addr += 1
break
- return found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
+ return found_comments, found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
class WalletDumpTest(BitcoinTestFramework):
@@ -122,12 +129,36 @@ class WalletDumpTest(BitcoinTestFramework):
# its capacity
self.nodes[0].keypoolrefill()
- # dump unencrypted wallet
+ self.log.info('Mine a block one second before the wallet is dumped')
+ dump_time = int(time.time())
+ self.nodes[0].setmocktime(dump_time - 1)
+ self.nodes[0].generate(1)
+ self.nodes[0].setmocktime(dump_time)
+ dump_time_str = '# * Created on {}Z'.format(
+ datetime.datetime.fromtimestamp(
+ dump_time,
+ tz=datetime.timezone.utc,
+ ).replace(tzinfo=None).isoformat())
+ dump_best_block_1 = '# * Best block at time of backup was {} ({}),'.format(
+ self.nodes[0].getblockcount(),
+ self.nodes[0].getbestblockhash(),
+ )
+ dump_best_block_2 = '# mined on {}Z'.format(
+ datetime.datetime.fromtimestamp(
+ dump_time - 1,
+ tz=datetime.timezone.utc,
+ ).replace(tzinfo=None).isoformat())
+
+ self.log.info('Dump unencrypted wallet')
result = self.nodes[0].dumpwallet(wallet_unenc_dump)
assert_equal(result['filename'], wallet_unenc_dump)
- found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
+ found_comments, found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
read_dump(wallet_unenc_dump, addrs, [multisig_addr], None)
+ assert '# End of dump' in found_comments # Check that file is not corrupt
+ assert_equal(dump_time_str, next(c for c in found_comments if c.startswith('# * Created on')))
+ assert_equal(dump_best_block_1, next(c for c in found_comments if c.startswith('# * Best block')))
+ assert_equal(dump_best_block_2, next(c for c in found_comments if c.startswith('# mined on')))
assert_equal(found_legacy_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_p2sh_segwit_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_bech32_addr, test_addr_count) # all keys must be in the dump
@@ -142,8 +173,12 @@ class WalletDumpTest(BitcoinTestFramework):
self.nodes[0].keypoolrefill()
self.nodes[0].dumpwallet(wallet_enc_dump)
- found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \
+ found_comments, found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \
read_dump(wallet_enc_dump, addrs, [multisig_addr], hd_master_addr_unenc)
+ assert '# End of dump' in found_comments # Check that file is not corrupt
+ assert_equal(dump_time_str, next(c for c in found_comments if c.startswith('# * Created on')))
+ assert_equal(dump_best_block_1, next(c for c in found_comments if c.startswith('# * Best block')))
+ assert_equal(dump_best_block_2, next(c for c in found_comments if c.startswith('# mined on')))
assert_equal(found_legacy_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_p2sh_segwit_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_bech32_addr, test_addr_count) # all keys must be in the dump
diff --git a/test/functional/wallet_encryption.py b/test/functional/wallet_encryption.py
index bc7e3cca59..6cd82ad250 100755
--- a/test/functional/wallet_encryption.py
+++ b/test/functional/wallet_encryption.py
@@ -8,7 +8,6 @@ import time
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
- assert_equal,
assert_raises_rpc_error,
assert_greater_than,
assert_greater_than_or_equal,
@@ -27,10 +26,10 @@ class WalletEncryptionTest(BitcoinTestFramework):
passphrase2 = "SecondWalletPassphrase"
# Make sure the wallet isn't encrypted first
- address = self.nodes[0].getnewaddress()
- privkey = self.nodes[0].dumpprivkey(address)
- assert_equal(privkey[:1], "c")
- assert_equal(len(privkey), 52)
+ msg = "test message"
+ address = self.nodes[0].getnewaddress(address_type='legacy')
+ sig = self.nodes[0].signmessage(address, msg)
+ assert self.nodes[0].verifymessage(address, sig, msg)
assert_raises_rpc_error(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called", self.nodes[0].walletpassphrase, 'ff', 1)
assert_raises_rpc_error(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.", self.nodes[0].walletpassphrasechange, 'ff', 'ff')
@@ -39,33 +38,36 @@ class WalletEncryptionTest(BitcoinTestFramework):
self.nodes[0].encryptwallet(passphrase)
# Test that the wallet is encrypted
- assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].dumpprivkey, address)
+ assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].signmessage, address, msg)
assert_raises_rpc_error(-15, "Error: running with an encrypted wallet, but encryptwallet was called.", self.nodes[0].encryptwallet, 'ff')
assert_raises_rpc_error(-8, "passphrase can not be empty", self.nodes[0].walletpassphrase, '', 1)
assert_raises_rpc_error(-8, "passphrase can not be empty", self.nodes[0].walletpassphrasechange, '', 'ff')
# Check that walletpassphrase works
self.nodes[0].walletpassphrase(passphrase, 2)
- assert_equal(privkey, self.nodes[0].dumpprivkey(address))
+ sig = self.nodes[0].signmessage(address, msg)
+ assert self.nodes[0].verifymessage(address, sig, msg)
# Check that the timeout is right
time.sleep(3)
- assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].dumpprivkey, address)
+ assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].signmessage, address, msg)
# Test wrong passphrase
assert_raises_rpc_error(-14, "wallet passphrase entered was incorrect", self.nodes[0].walletpassphrase, passphrase + "wrong", 10)
# Test walletlock
self.nodes[0].walletpassphrase(passphrase, 84600)
- assert_equal(privkey, self.nodes[0].dumpprivkey(address))
+ sig = self.nodes[0].signmessage(address, msg)
+ assert self.nodes[0].verifymessage(address, sig, msg)
self.nodes[0].walletlock()
- assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].dumpprivkey, address)
+ assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].signmessage, address, msg)
# Test passphrase changes
self.nodes[0].walletpassphrasechange(passphrase, passphrase2)
assert_raises_rpc_error(-14, "wallet passphrase entered was incorrect", self.nodes[0].walletpassphrase, passphrase, 10)
self.nodes[0].walletpassphrase(passphrase2, 10)
- assert_equal(privkey, self.nodes[0].dumpprivkey(address))
+ sig = self.nodes[0].signmessage(address, msg)
+ assert self.nodes[0].verifymessage(address, sig, msg)
self.nodes[0].walletlock()
# Test timeout bounds
diff --git a/test/functional/wallet_groups.py b/test/functional/wallet_groups.py
index f2fa1d3e40..9dd55b4ab1 100755
--- a/test/functional/wallet_groups.py
+++ b/test/functional/wallet_groups.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
"""Test wallet group functionality."""
@@ -11,12 +11,13 @@ from test_framework.util import (
assert_equal,
)
+
class WalletGroupTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
self.extra_args = [[], [], ['-avoidpartialspends']]
- self.rpc_timeout = 240
+ self.rpc_timeout = 480
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -87,5 +88,6 @@ class WalletGroupTest(BitcoinTestFramework):
# is way too big.
assert self.nodes[2].sendtoaddress(address=addr2[0], amount=5)
+
if __name__ == '__main__':
- WalletGroupTest().main ()
+ WalletGroupTest().main()
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index 7497475b67..09f89eb59d 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2019 The Bitcoin Core developers
+# Copyright (c) 2016-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 Hierarchical Deterministic wallet function."""
@@ -27,17 +27,21 @@ class WalletHDTest(BitcoinTestFramework):
def run_test(self):
# Make sure we use hd, keep masterkeyid
- masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
- assert_equal(len(masterkeyid), 40)
+ hd_fingerprint = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['hdmasterfingerprint']
+ assert_equal(len(hd_fingerprint), 8)
# create an internal key
change_addr = self.nodes[1].getrawchangeaddress()
change_addrV= self.nodes[1].getaddressinfo(change_addr)
- assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") #first internal child key
+ if self.options.descriptors:
+ assert_equal(change_addrV["hdkeypath"], "m/84'/1'/0'/1/0")
+ else:
+ assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") #first internal child key
# Import a non-HD private key in the HD wallet
- non_hd_add = self.nodes[0].getnewaddress()
- self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add))
+ non_hd_add = 'bcrt1qmevj8zfx0wdvp05cqwkmr6mxkfx60yezwjksmt'
+ non_hd_key = 'cS9umN9w6cDMuRVYdbkfE4c7YUFLJRoXMfhQ569uY4odiQbVN8Rt'
+ self.nodes[1].importprivkey(non_hd_key)
# This should be enough to keep the master key and the non-HD key
self.nodes[1].backupwallet(os.path.join(self.nodes[1].datadir, "hd.bak"))
@@ -48,11 +52,14 @@ class WalletHDTest(BitcoinTestFramework):
self.nodes[0].generate(101)
hd_add = None
NUM_HD_ADDS = 10
- for i in range(NUM_HD_ADDS):
+ for i in range(1, NUM_HD_ADDS + 1):
hd_add = self.nodes[1].getnewaddress()
hd_info = self.nodes[1].getaddressinfo(hd_add)
- assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i)+"'")
- assert_equal(hd_info["hdseedid"], masterkeyid)
+ if self.options.descriptors:
+ assert_equal(hd_info["hdkeypath"], "m/84'/1'/0'/0/" + str(i))
+ else:
+ assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i)+"'")
+ assert_equal(hd_info["hdmasterfingerprint"], hd_fingerprint)
self.nodes[0].sendtoaddress(hd_add, 1)
self.nodes[0].generate(1)
self.nodes[0].sendtoaddress(non_hd_add, 1)
@@ -61,7 +68,10 @@ class WalletHDTest(BitcoinTestFramework):
# create an internal key (again)
change_addr = self.nodes[1].getrawchangeaddress()
change_addrV= self.nodes[1].getaddressinfo(change_addr)
- assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") #second internal child key
+ if self.options.descriptors:
+ assert_equal(change_addrV["hdkeypath"], "m/84'/1'/0'/1/1")
+ else:
+ assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") #second internal child key
self.sync_all()
assert_equal(self.nodes[1].getbalance(), NUM_HD_ADDS + 1)
@@ -72,16 +82,19 @@ class WalletHDTest(BitcoinTestFramework):
# otherwise node1 would auto-recover all funds in flag the keypool keys as used
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "blocks"))
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "chainstate"))
- shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat"))
+ shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, 'wallets', "wallet.dat"))
self.start_node(1)
# Assert that derivation is deterministic
hd_add_2 = None
- for i in range(NUM_HD_ADDS):
+ for i in range(1, NUM_HD_ADDS + 1):
hd_add_2 = self.nodes[1].getnewaddress()
hd_info_2 = self.nodes[1].getaddressinfo(hd_add_2)
- assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(i)+"'")
- assert_equal(hd_info_2["hdseedid"], masterkeyid)
+ if self.options.descriptors:
+ assert_equal(hd_info_2["hdkeypath"], "m/84'/1'/0'/0/" + str(i))
+ else:
+ 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.sync_all()
@@ -117,41 +130,45 @@ class WalletHDTest(BitcoinTestFramework):
if out['value'] != 1:
keypath = self.nodes[1].getaddressinfo(out['scriptPubKey']['addresses'][0])['hdkeypath']
- assert_equal(keypath[0:7], "m/0'/1'")
-
- # Generate a new HD seed on node 1 and make sure it is set
- orig_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
- self.nodes[1].sethdseed()
- new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
- assert orig_masterkeyid != new_masterkeyid
- addr = self.nodes[1].getnewaddress()
- assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is the first from the keypool
- self.nodes[1].keypoolrefill(1) # Fill keypool with 1 key
-
- # Set a new HD seed on node 1 without flushing the keypool
- new_seed = self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())
- orig_masterkeyid = new_masterkeyid
- self.nodes[1].sethdseed(False, new_seed)
- new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
- assert orig_masterkeyid != new_masterkeyid
- addr = self.nodes[1].getnewaddress()
- assert_equal(orig_masterkeyid, self.nodes[1].getaddressinfo(addr)['hdseedid'])
- assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/1\'') # Make sure the new address continues previous keypool
-
- # Check that the next address is from the new seed
- self.nodes[1].keypoolrefill(1)
- next_addr = self.nodes[1].getnewaddress()
- assert_equal(new_masterkeyid, self.nodes[1].getaddressinfo(next_addr)['hdseedid'])
- assert_equal(self.nodes[1].getaddressinfo(next_addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is not from previous keypool
- assert next_addr != addr
-
- # Sethdseed parameter validity
- assert_raises_rpc_error(-1, 'sethdseed', self.nodes[0].sethdseed, False, new_seed, 0)
- assert_raises_rpc_error(-5, "Invalid private key", self.nodes[1].sethdseed, False, "not_wif")
- assert_raises_rpc_error(-1, "JSON value is not a boolean as expected", self.nodes[1].sethdseed, "Not_bool")
- assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[1].sethdseed, False, True)
- assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, new_seed)
- assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, self.nodes[1].dumpprivkey(self.nodes[1].getnewaddress()))
+ if self.options.descriptors:
+ assert_equal(keypath[0:14], "m/84'/1'/0'/1/")
+ else:
+ assert_equal(keypath[0:7], "m/0'/1'")
+
+ if not self.options.descriptors:
+ # Generate a new HD seed on node 1 and make sure it is set
+ orig_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
+ self.nodes[1].sethdseed()
+ new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
+ assert orig_masterkeyid != new_masterkeyid
+ addr = self.nodes[1].getnewaddress()
+ assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is the first from the keypool
+ self.nodes[1].keypoolrefill(1) # Fill keypool with 1 key
+
+ # Set a new HD seed on node 1 without flushing the keypool
+ new_seed = self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())
+ orig_masterkeyid = new_masterkeyid
+ self.nodes[1].sethdseed(False, new_seed)
+ new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
+ assert orig_masterkeyid != new_masterkeyid
+ addr = self.nodes[1].getnewaddress()
+ assert_equal(orig_masterkeyid, self.nodes[1].getaddressinfo(addr)['hdseedid'])
+ assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/1\'') # Make sure the new address continues previous keypool
+
+ # Check that the next address is from the new seed
+ self.nodes[1].keypoolrefill(1)
+ next_addr = self.nodes[1].getnewaddress()
+ assert_equal(new_masterkeyid, self.nodes[1].getaddressinfo(next_addr)['hdseedid'])
+ assert_equal(self.nodes[1].getaddressinfo(next_addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is not from previous keypool
+ assert next_addr != addr
+
+ # Sethdseed parameter validity
+ assert_raises_rpc_error(-1, 'sethdseed', self.nodes[0].sethdseed, False, new_seed, 0)
+ assert_raises_rpc_error(-5, "Invalid private key", self.nodes[1].sethdseed, False, "not_wif")
+ assert_raises_rpc_error(-1, "JSON value is not a boolean as expected", self.nodes[1].sethdseed, "Not_bool")
+ assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[1].sethdseed, False, True)
+ assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, new_seed)
+ assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, self.nodes[1].dumpprivkey(self.nodes[1].getnewaddress()))
if __name__ == '__main__':
WalletHDTest().main ()
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index b8b85b7a19..4ff7f1d525 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -40,7 +40,6 @@ Rescan = enum.Enum("Rescan", "no yes late_timestamp")
class Variant(collections.namedtuple("Variant", "call data address_type rescan prune")):
"""Helper for importing one key and verifying scanned transactions."""
-
def do_import(self, timestamp):
"""Call one key import RPC."""
rescan = self.rescan == Rescan.yes
@@ -146,6 +145,7 @@ class ImportRescanTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2 + len(IMPORT_NODES)
self.supports_cli = False
+ self.rpc_timeout = 120
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -226,5 +226,6 @@ class ImportRescanTest(BitcoinTestFramework):
variant.expected_txs += 1
variant.check(variant.sent_txid, variant.sent_amount, variant.confirmation_height)
+
if __name__ == "__main__":
ImportRescanTest().main()
diff --git a/test/functional/wallet_importdescriptors.py b/test/functional/wallet_importdescriptors.py
new file mode 100755
index 0000000000..fc5d653a91
--- /dev/null
+++ b/test/functional/wallet_importdescriptors.py
@@ -0,0 +1,445 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test the importdescriptors RPC.
+
+Test importdescriptors by generating keys on node0, importing the corresponding
+descriptors on node1 and then testing the address info for the different address
+variants.
+
+- `get_generate_key()` is called to generate keys and return the privkeys,
+ pubkeys and all variants of scriptPubKey and address.
+- `test_importdesc()` is called to send an importdescriptors call to node1, test
+ success, and (if unsuccessful) test the error code and error message returned.
+- `test_address()` is called to call getaddressinfo for an address on node1
+ and test the values returned."""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.descriptors import descsum_create
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+ find_vout_for_address,
+)
+from test_framework.wallet_util import (
+ get_generate_key,
+ test_address,
+)
+
+class ImportDescriptorsTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 2
+ self.extra_args = [["-addresstype=legacy"],
+ ["-addresstype=bech32", "-keypool=5"]
+ ]
+ self.setup_clean_chain = True
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def test_importdesc(self, req, success, error_code=None, error_message=None, warnings=None, wallet=None):
+ """Run importdescriptors and assert success"""
+ if warnings is None:
+ warnings = []
+ wrpc = self.nodes[1].get_wallet_rpc('w1')
+ if wallet is not None:
+ wrpc = wallet
+
+ result = wrpc.importdescriptors([req])
+ observed_warnings = []
+ if 'warnings' in result[0]:
+ observed_warnings = result[0]['warnings']
+ assert_equal("\n".join(sorted(warnings)), "\n".join(sorted(observed_warnings)))
+ assert_equal(result[0]['success'], success)
+ if error_code is not None:
+ assert_equal(result[0]['error']['code'], error_code)
+ assert_equal(result[0]['error']['message'], error_message)
+
+ def run_test(self):
+ self.log.info('Setting up wallets')
+ self.nodes[0].createwallet(wallet_name='w0', disable_private_keys=False)
+ w0 = self.nodes[0].get_wallet_rpc('w0')
+
+ self.nodes[1].createwallet(wallet_name='w1', disable_private_keys=True, blank=True, descriptors=True)
+ w1 = self.nodes[1].get_wallet_rpc('w1')
+ assert_equal(w1.getwalletinfo()['keypoolsize'], 0)
+
+ self.nodes[1].createwallet(wallet_name="wpriv", disable_private_keys=False, blank=True, descriptors=True)
+ wpriv = self.nodes[1].get_wallet_rpc("wpriv")
+ assert_equal(wpriv.getwalletinfo()['keypoolsize'], 0)
+
+ self.log.info('Mining coins')
+ w0.generatetoaddress(101, w0.getnewaddress())
+
+ # RPC importdescriptors -----------------------------------------------
+
+ # # Test import fails if no descriptor present
+ key = get_generate_key()
+ self.log.info("Import should fail if a descriptor is not provided")
+ self.test_importdesc({"timestamp": "now"},
+ success=False,
+ error_code=-8,
+ error_message='Descriptor not found.')
+
+ # # Test importing of a P2PKH descriptor
+ key = get_generate_key()
+ self.log.info("Should import a p2pkh descriptor")
+ self.test_importdesc({"desc": descsum_create("pkh(" + key.pubkey + ")"),
+ "timestamp": "now",
+ "label": "Descriptor import test"},
+ success=True)
+ test_address(w1,
+ key.p2pkh_addr,
+ solvable=True,
+ ismine=True,
+ labels=["Descriptor import test"])
+ assert_equal(w1.getwalletinfo()['keypoolsize'], 0)
+
+ self.log.info("Internal addresses cannot have labels")
+ self.test_importdesc({"desc": descsum_create("pkh(" + key.pubkey + ")"),
+ "timestamp": "now",
+ "internal": True,
+ "label": "Descriptor import test"},
+ success=False,
+ error_code=-8,
+ error_message="Internal addresses should not have a label")
+
+ # # Test importing of a P2SH-P2WPKH descriptor
+ key = get_generate_key()
+ self.log.info("Should not import a p2sh-p2wpkh descriptor without checksum")
+ self.test_importdesc({"desc": "sh(wpkh(" + key.pubkey + "))",
+ "timestamp": "now"
+ },
+ success=False,
+ error_code=-5,
+ error_message="Missing checksum")
+
+ self.log.info("Should not import a p2sh-p2wpkh descriptor that has range specified")
+ self.test_importdesc({"desc": descsum_create("sh(wpkh(" + key.pubkey + "))"),
+ "timestamp": "now",
+ "range": 1,
+ },
+ success=False,
+ error_code=-8,
+ error_message="Range should not be specified for an un-ranged descriptor")
+
+ self.log.info("Should not import a p2sh-p2wpkh descriptor and have it set to active")
+ self.test_importdesc({"desc": descsum_create("sh(wpkh(" + key.pubkey + "))"),
+ "timestamp": "now",
+ "active": True,
+ },
+ success=False,
+ error_code=-8,
+ error_message="Active descriptors must be ranged")
+
+ self.log.info("Should import a (non-active) p2sh-p2wpkh descriptor")
+ self.test_importdesc({"desc": descsum_create("sh(wpkh(" + key.pubkey + "))"),
+ "timestamp": "now",
+ "active": False,
+ },
+ success=True)
+ assert_equal(w1.getwalletinfo()['keypoolsize'], 0)
+
+ test_address(w1,
+ key.p2sh_p2wpkh_addr,
+ ismine=True,
+ solvable=True)
+
+ # # Test importing of a multisig descriptor
+ key1 = get_generate_key()
+ key2 = get_generate_key()
+ self.log.info("Should import a 1-of-2 bare multisig from descriptor")
+ self.test_importdesc({"desc": descsum_create("multi(1," + key1.pubkey + "," + key2.pubkey + ")"),
+ "timestamp": "now"},
+ success=True)
+ self.log.info("Should not treat individual keys from the imported bare multisig as watchonly")
+ test_address(w1,
+ key1.p2pkh_addr,
+ ismine=False)
+
+ # # Test ranged descriptors
+ xpriv = "tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg"
+ xpub = "tpubD6NzVbkrYhZ4YNXVQbNhMK1WqguFsUXceaVJKbmno2aZ3B6QfbMeraaYvnBSGpV3vxLyTTK9DYT1yoEck4XUScMzXoQ2U2oSmE2JyMedq3H"
+ addresses = ["2N7yv4p8G8yEaPddJxY41kPihnWvs39qCMf", "2MsHxyb2JS3pAySeNUsJ7mNnurtpeenDzLA"] # hdkeypath=m/0'/0'/0' and 1'
+ addresses += ["bcrt1qrd3n235cj2czsfmsuvqqpr3lu6lg0ju7scl8gn", "bcrt1qfqeppuvj0ww98r6qghmdkj70tv8qpchehegrg8"] # wpkh subscripts corresponding to the above addresses
+ desc = "sh(wpkh(" + xpub + "/0/0/*" + "))"
+
+ self.log.info("Ranged descriptors cannot have labels")
+ self.test_importdesc({"desc":descsum_create(desc),
+ "timestamp": "now",
+ "range": [0, 100],
+ "label": "test"},
+ success=False,
+ error_code=-8,
+ error_message='Ranged descriptors should not have a label')
+
+ self.log.info("Private keys required for private keys enabled wallet")
+ self.test_importdesc({"desc":descsum_create(desc),
+ "timestamp": "now",
+ "range": [0, 100]},
+ success=False,
+ error_code=-4,
+ error_message='Cannot import descriptor without private keys to a wallet with private keys enabled',
+ wallet=wpriv)
+
+ self.log.info("Ranged descriptor import should warn without a specified range")
+ self.test_importdesc({"desc": descsum_create(desc),
+ "timestamp": "now"},
+ success=True,
+ warnings=['Range not given, using default keypool range'])
+ assert_equal(w1.getwalletinfo()['keypoolsize'], 0)
+
+ # # Test importing of a ranged descriptor with xpriv
+ self.log.info("Should not import a ranged descriptor that includes xpriv into a watch-only wallet")
+ desc = "sh(wpkh(" + xpriv + "/0'/0'/*'" + "))"
+ self.test_importdesc({"desc": descsum_create(desc),
+ "timestamp": "now",
+ "range": 1},
+ success=False,
+ error_code=-4,
+ error_message='Cannot import private keys to a wallet with private keys disabled')
+ for address in addresses:
+ test_address(w1,
+ address,
+ ismine=False,
+ solvable=False)
+
+ self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": -1},
+ success=False, error_code=-8, error_message='End of range is too high')
+
+ self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": [-1, 10]},
+ success=False, error_code=-8, error_message='Range should be greater or equal than 0')
+
+ self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": [(2 << 31 + 1) - 1000000, (2 << 31 + 1)]},
+ success=False, error_code=-8, error_message='End of range is too high')
+
+ self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": [2, 1]},
+ success=False, error_code=-8, error_message='Range specified as [begin,end] must not have begin after end')
+
+ self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": [0, 1000001]},
+ success=False, error_code=-8, error_message='Range is too large')
+
+ # Make sure ranged imports import keys in order
+ w1 = self.nodes[1].get_wallet_rpc('w1')
+ self.log.info('Key ranges should be imported in order')
+ xpub = "tpubDAXcJ7s7ZwicqjprRaEWdPoHKrCS215qxGYxpusRLLmJuT69ZSicuGdSfyvyKpvUNYBW1s2U3NSrT6vrCYB9e6nZUEvrqnwXPF8ArTCRXMY"
+ addresses = [
+ 'bcrt1qtmp74ayg7p24uslctssvjm06q5phz4yrxucgnv', # m/0'/0'/0
+ 'bcrt1q8vprchan07gzagd5e6v9wd7azyucksq2xc76k8', # m/0'/0'/1
+ 'bcrt1qtuqdtha7zmqgcrr26n2rqxztv5y8rafjp9lulu', # m/0'/0'/2
+ 'bcrt1qau64272ymawq26t90md6an0ps99qkrse58m640', # m/0'/0'/3
+ 'bcrt1qsg97266hrh6cpmutqen8s4s962aryy77jp0fg0', # m/0'/0'/4
+ ]
+
+ self.test_importdesc({'desc': descsum_create('wpkh([80002067/0h/0h]' + xpub + '/*)'),
+ 'active': True,
+ 'range' : [0, 2],
+ 'timestamp': 'now'
+ },
+ success=True)
+ self.test_importdesc({'desc': descsum_create('sh(wpkh([abcdef12/0h/0h]' + xpub + '/*))'),
+ 'active': True,
+ 'range' : [0, 2],
+ 'timestamp': 'now'
+ },
+ success=True)
+ self.test_importdesc({'desc': descsum_create('pkh([12345678/0h/0h]' + xpub + '/*)'),
+ 'active': True,
+ 'range' : [0, 2],
+ 'timestamp': 'now'
+ },
+ success=True)
+
+ assert_equal(w1.getwalletinfo()['keypoolsize'], 5 * 3)
+ for i, expected_addr in enumerate(addresses):
+ received_addr = w1.getnewaddress('', 'bech32')
+ assert_raises_rpc_error(-4, 'This wallet has no available keys', w1.getrawchangeaddress, 'bech32')
+ assert_equal(received_addr, expected_addr)
+ bech32_addr_info = w1.getaddressinfo(received_addr)
+ assert_equal(bech32_addr_info['desc'][:23], 'wpkh([80002067/0\'/0\'/{}]'.format(i))
+
+ shwpkh_addr = w1.getnewaddress('', 'p2sh-segwit')
+ shwpkh_addr_info = w1.getaddressinfo(shwpkh_addr)
+ assert_equal(shwpkh_addr_info['desc'][:26], 'sh(wpkh([abcdef12/0\'/0\'/{}]'.format(i))
+
+ pkh_addr = w1.getnewaddress('', 'legacy')
+ pkh_addr_info = w1.getaddressinfo(pkh_addr)
+ assert_equal(pkh_addr_info['desc'][:22], 'pkh([12345678/0\'/0\'/{}]'.format(i))
+
+ assert_equal(w1.getwalletinfo()['keypoolsize'], 4 * 3) # After retrieving a key, we don't refill the keypool again, so it's one less for each address type
+ w1.keypoolrefill()
+ assert_equal(w1.getwalletinfo()['keypoolsize'], 5 * 3)
+
+ # Check active=False default
+ self.log.info('Check imported descriptors are not active by default')
+ self.test_importdesc({'desc': descsum_create('pkh([12345678/0h/0h]' + xpub + '/*)'),
+ 'range' : [0, 2],
+ 'timestamp': 'now',
+ 'internal': True
+ },
+ success=True)
+ assert_raises_rpc_error(-4, 'This wallet has no available keys', w1.getrawchangeaddress, 'legacy')
+
+ # # Test importing a descriptor containing a WIF private key
+ wif_priv = "cTe1f5rdT8A8DFgVWTjyPwACsDPJM9ff4QngFxUixCSvvbg1x6sh"
+ address = "2MuhcG52uHPknxDgmGPsV18jSHFBnnRgjPg"
+ desc = "sh(wpkh(" + wif_priv + "))"
+ self.log.info("Should import a descriptor with a WIF private key as spendable")
+ self.test_importdesc({"desc": descsum_create(desc),
+ "timestamp": "now"},
+ success=True,
+ wallet=wpriv)
+ test_address(wpriv,
+ address,
+ solvable=True,
+ ismine=True)
+ txid = w0.sendtoaddress(address, 49.99995540)
+ w0.generatetoaddress(6, w0.getnewaddress())
+ self.sync_blocks()
+ tx = wpriv.createrawtransaction([{"txid": txid, "vout": 0}], {w0.getnewaddress(): 49.999})
+ signed_tx = wpriv.signrawtransactionwithwallet(tx)
+ w1.sendrawtransaction(signed_tx['hex'])
+
+ # Make sure that we can use import and use multisig as addresses
+ self.log.info('Test that multisigs can be imported, signed for, and getnewaddress\'d')
+ self.nodes[1].createwallet(wallet_name="wmulti_priv", disable_private_keys=False, blank=True, descriptors=True)
+ wmulti_priv = self.nodes[1].get_wallet_rpc("wmulti_priv")
+ assert_equal(wmulti_priv.getwalletinfo()['keypoolsize'], 0)
+
+ self.test_importdesc({"desc":"wsh(multi(2,tprv8ZgxMBicQKsPevADjDCWsa6DfhkVXicu8NQUzfibwX2MexVwW4tCec5mXdCW8kJwkzBRRmAay1KZya4WsehVvjTGVW6JLqiqd8DdZ4xSg52/84h/0h/0h/*,tprv8ZgxMBicQKsPdSNWUhDiwTScDr6JfkZuLshTRwzvZGnMSnGikV6jxpmdDkC3YRc4T3GD6Nvg9uv6hQg73RVv1EiTXDZwxVbsLugVHU8B1aq/84h/0h/0h/*,tprv8ZgxMBicQKsPeonDt8Ka2mrQmHa61hQ5FQCsvWBTpSNzBFgM58cV2EuXNAHF14VawVpznnme3SuTbA62sGriwWyKifJmXntfNeK7zeqMCj1/84h/0h/0h/*))#m2sr93jn",
+ "active": True,
+ "range": 1000,
+ "next_index": 0,
+ "timestamp": "now"},
+ success=True,
+ wallet=wmulti_priv)
+ self.test_importdesc({"desc":"wsh(multi(2,tprv8ZgxMBicQKsPevADjDCWsa6DfhkVXicu8NQUzfibwX2MexVwW4tCec5mXdCW8kJwkzBRRmAay1KZya4WsehVvjTGVW6JLqiqd8DdZ4xSg52/84h/1h/0h/*,tprv8ZgxMBicQKsPdSNWUhDiwTScDr6JfkZuLshTRwzvZGnMSnGikV6jxpmdDkC3YRc4T3GD6Nvg9uv6hQg73RVv1EiTXDZwxVbsLugVHU8B1aq/84h/1h/0h/*,tprv8ZgxMBicQKsPeonDt8Ka2mrQmHa61hQ5FQCsvWBTpSNzBFgM58cV2EuXNAHF14VawVpznnme3SuTbA62sGriwWyKifJmXntfNeK7zeqMCj1/84h/1h/0h/*))#q3sztvx5",
+ "active": True,
+ "internal" : True,
+ "range": 1000,
+ "next_index": 0,
+ "timestamp": "now"},
+ success=True,
+ wallet=wmulti_priv)
+
+ assert_equal(wmulti_priv.getwalletinfo()['keypoolsize'], 1001) # Range end (1000) is inclusive, so 1001 addresses generated
+ addr = wmulti_priv.getnewaddress('', 'bech32')
+ assert_equal(addr, 'bcrt1qdt0qy5p7dzhxzmegnn4ulzhard33s2809arjqgjndx87rv5vd0fq2czhy8') # Derived at m/84'/0'/0'/0
+ change_addr = wmulti_priv.getrawchangeaddress('bech32')
+ assert_equal(change_addr, 'bcrt1qt9uhe3a9hnq7vajl7a094z4s3crm9ttf8zw3f5v9gr2nyd7e3lnsy44n8e')
+ assert_equal(wmulti_priv.getwalletinfo()['keypoolsize'], 1000)
+ txid = w0.sendtoaddress(addr, 10)
+ self.nodes[0].generate(6)
+ self.sync_all()
+ send_txid = wmulti_priv.sendtoaddress(w0.getnewaddress(), 8)
+ decoded = wmulti_priv.decoderawtransaction(wmulti_priv.gettransaction(send_txid)['hex'])
+ assert_equal(len(decoded['vin'][0]['txinwitness']), 4)
+ self.nodes[0].generate(6)
+ self.sync_all()
+
+ self.nodes[1].createwallet(wallet_name="wmulti_pub", disable_private_keys=True, blank=True, descriptors=True)
+ wmulti_pub = self.nodes[1].get_wallet_rpc("wmulti_pub")
+ assert_equal(wmulti_pub.getwalletinfo()['keypoolsize'], 0)
+
+ self.test_importdesc({"desc":"wsh(multi(2,[7b2d0242/84h/0h/0h]tpubDCJtdt5dgJpdhW4MtaVYDhG4T4tF6jcLR1PxL43q9pq1mxvXgMS9Mzw1HnXG15vxUGQJMMSqCQHMTy3F1eW5VkgVroWzchsPD5BUojrcWs8/*,[59b09cd6/84h/0h/0h]tpubDDBF2BTR6s8drwrfDei8WxtckGuSm1cyoKxYY1QaKSBFbHBYQArWhHPA6eJrzZej6nfHGLSURYSLHr7GuYch8aY5n61tGqgn8b4cXrMuoPH/*,[e81a0532/84h/0h/0h]tpubDCsWoW1kuQB9kG5MXewHqkbjPtqPueRnXju7uM2NK7y3JYb2ajAZ9EiuZXNNuE4661RAfriBWhL8UsnAPpk8zrKKnZw1Ug7X4oHgMdZiU4E/*))#tsry0s5e",
+ "active": True,
+ "range": 1000,
+ "next_index": 0,
+ "timestamp": "now"},
+ success=True,
+ wallet=wmulti_pub)
+ self.test_importdesc({"desc":"wsh(multi(2,[7b2d0242/84h/1h/0h]tpubDCXqdwWZcszwqYJSnZp8eARkxGJfHAk23KDxbztV4BbschfaTfYLTcSkSJ3TN64dRqwa1rnFUScsYormKkGqNbbPwkorQimVevXjxzUV9Gf/*,[59b09cd6/84h/1h/0h]tpubDCYfZY2ceyHzYzMMVPt9MNeiqtQ2T7Uyp9QSFwYXh8Vi9iJFYXcuphJaGXfF3jUQJi5Y3GMNXvM11gaL4txzZgNGK22BFAwMXynnzv4z2Jh/*,[e81a0532/84h/1h/0h]tpubDC6UGqnsQStngYuGD4MKsMy7eD1Yg9NTJfPdvjdG2JE5oZ7EsSL3WHg4Gsw2pR5K39ZwJ46M1wZayhedVdQtMGaUhq5S23PH6fnENK3V1sb/*))#c08a2rzv",
+ "active": True,
+ "internal" : True,
+ "range": 1000,
+ "next_index": 0,
+ "timestamp": "now"},
+ success=True,
+ wallet=wmulti_pub)
+
+ assert_equal(wmulti_pub.getwalletinfo()['keypoolsize'], 1000) # The first one was already consumed by previous import and is detected as used
+ addr = wmulti_pub.getnewaddress('', 'bech32')
+ assert_equal(addr, 'bcrt1qp8s25ckjl7gr6x2q3dx3tn2pytwp05upkjztk6ey857tt50r5aeqn6mvr9') # Derived at m/84'/0'/0'/1
+ change_addr = wmulti_pub.getrawchangeaddress('bech32')
+ assert_equal(change_addr, 'bcrt1qt9uhe3a9hnq7vajl7a094z4s3crm9ttf8zw3f5v9gr2nyd7e3lnsy44n8e')
+ assert_equal(wmulti_pub.getwalletinfo()['keypoolsize'], 999)
+ txid = w0.sendtoaddress(addr, 10)
+ vout = find_vout_for_address(self.nodes[0], txid, addr)
+ self.nodes[0].generate(6)
+ self.sync_all()
+ assert_equal(wmulti_pub.getbalance(), wmulti_priv.getbalance())
+
+ self.log.info("Multisig with distributed keys")
+ self.nodes[1].createwallet(wallet_name="wmulti_priv1", descriptors=True)
+ wmulti_priv1 = self.nodes[1].get_wallet_rpc("wmulti_priv1")
+ res = wmulti_priv1.importdescriptors([
+ {
+ "desc": descsum_create("wsh(multi(2,tprv8ZgxMBicQKsPevADjDCWsa6DfhkVXicu8NQUzfibwX2MexVwW4tCec5mXdCW8kJwkzBRRmAay1KZya4WsehVvjTGVW6JLqiqd8DdZ4xSg52/84h/0h/0h/*,[59b09cd6/84h/0h/0h]tpubDDBF2BTR6s8drwrfDei8WxtckGuSm1cyoKxYY1QaKSBFbHBYQArWhHPA6eJrzZej6nfHGLSURYSLHr7GuYch8aY5n61tGqgn8b4cXrMuoPH/*,[e81a0532/84h/0h/0h]tpubDCsWoW1kuQB9kG5MXewHqkbjPtqPueRnXju7uM2NK7y3JYb2ajAZ9EiuZXNNuE4661RAfriBWhL8UsnAPpk8zrKKnZw1Ug7X4oHgMdZiU4E/*))"),
+ "active": True,
+ "range": 1000,
+ "next_index": 0,
+ "timestamp": "now"
+ },
+ {
+ "desc": descsum_create("wsh(multi(2,tprv8ZgxMBicQKsPevADjDCWsa6DfhkVXicu8NQUzfibwX2MexVwW4tCec5mXdCW8kJwkzBRRmAay1KZya4WsehVvjTGVW6JLqiqd8DdZ4xSg52/84h/1h/0h/*,[59b09cd6/84h/1h/0h]tpubDCYfZY2ceyHzYzMMVPt9MNeiqtQ2T7Uyp9QSFwYXh8Vi9iJFYXcuphJaGXfF3jUQJi5Y3GMNXvM11gaL4txzZgNGK22BFAwMXynnzv4z2Jh/*,[e81a0532/84h/1h/0h]tpubDC6UGqnsQStngYuGD4MKsMy7eD1Yg9NTJfPdvjdG2JE5oZ7EsSL3WHg4Gsw2pR5K39ZwJ46M1wZayhedVdQtMGaUhq5S23PH6fnENK3V1sb/*))"),
+ "active": True,
+ "internal" : True,
+ "range": 1000,
+ "next_index": 0,
+ "timestamp": "now"
+ }])
+ assert_equal(res[0]['success'], True)
+ assert_equal(res[0]['warnings'][0], 'Not all private keys provided. Some wallet functionality may return unexpected errors')
+ assert_equal(res[1]['success'], True)
+ assert_equal(res[1]['warnings'][0], 'Not all private keys provided. Some wallet functionality may return unexpected errors')
+
+ self.nodes[1].createwallet(wallet_name='wmulti_priv2', blank=True, descriptors=True)
+ wmulti_priv2 = self.nodes[1].get_wallet_rpc('wmulti_priv2')
+ res = wmulti_priv2.importdescriptors([
+ {
+ "desc": descsum_create("wsh(multi(2,[7b2d0242/84h/0h/0h]tpubDCJtdt5dgJpdhW4MtaVYDhG4T4tF6jcLR1PxL43q9pq1mxvXgMS9Mzw1HnXG15vxUGQJMMSqCQHMTy3F1eW5VkgVroWzchsPD5BUojrcWs8/*,tprv8ZgxMBicQKsPdSNWUhDiwTScDr6JfkZuLshTRwzvZGnMSnGikV6jxpmdDkC3YRc4T3GD6Nvg9uv6hQg73RVv1EiTXDZwxVbsLugVHU8B1aq/84h/0h/0h/*,[e81a0532/84h/0h/0h]tpubDCsWoW1kuQB9kG5MXewHqkbjPtqPueRnXju7uM2NK7y3JYb2ajAZ9EiuZXNNuE4661RAfriBWhL8UsnAPpk8zrKKnZw1Ug7X4oHgMdZiU4E/*))"),
+ "active": True,
+ "range": 1000,
+ "next_index": 0,
+ "timestamp": "now"
+ },
+ {
+ "desc": descsum_create("wsh(multi(2,[7b2d0242/84h/1h/0h]tpubDCXqdwWZcszwqYJSnZp8eARkxGJfHAk23KDxbztV4BbschfaTfYLTcSkSJ3TN64dRqwa1rnFUScsYormKkGqNbbPwkorQimVevXjxzUV9Gf/*,tprv8ZgxMBicQKsPdSNWUhDiwTScDr6JfkZuLshTRwzvZGnMSnGikV6jxpmdDkC3YRc4T3GD6Nvg9uv6hQg73RVv1EiTXDZwxVbsLugVHU8B1aq/84h/1h/0h/*,[e81a0532/84h/1h/0h]tpubDC6UGqnsQStngYuGD4MKsMy7eD1Yg9NTJfPdvjdG2JE5oZ7EsSL3WHg4Gsw2pR5K39ZwJ46M1wZayhedVdQtMGaUhq5S23PH6fnENK3V1sb/*))"),
+ "active": True,
+ "internal" : True,
+ "range": 1000,
+ "next_index": 0,
+ "timestamp": "now"
+ }])
+ assert_equal(res[0]['success'], True)
+ assert_equal(res[0]['warnings'][0], 'Not all private keys provided. Some wallet functionality may return unexpected errors')
+ assert_equal(res[1]['success'], True)
+ assert_equal(res[1]['warnings'][0], 'Not all private keys provided. Some wallet functionality may return unexpected errors')
+
+ rawtx = self.nodes[1].createrawtransaction([{'txid': txid, 'vout': vout}], {w0.getnewaddress(): 9.999})
+ tx_signed_1 = wmulti_priv1.signrawtransactionwithwallet(rawtx)
+ assert_equal(tx_signed_1['complete'], False)
+ tx_signed_2 = wmulti_priv2.signrawtransactionwithwallet(tx_signed_1['hex'])
+ assert_equal(tx_signed_2['complete'], True)
+ self.nodes[1].sendrawtransaction(tx_signed_2['hex'])
+
+ self.log.info("Combo descriptors cannot be active")
+ self.test_importdesc({"desc": descsum_create("combo(tpubDCJtdt5dgJpdhW4MtaVYDhG4T4tF6jcLR1PxL43q9pq1mxvXgMS9Mzw1HnXG15vxUGQJMMSqCQHMTy3F1eW5VkgVroWzchsPD5BUojrcWs8/*)"),
+ "active": True,
+ "range": 1,
+ "timestamp": "now"},
+ success=False,
+ error_code=-4,
+ error_message="Combo descriptors cannot be set to active")
+
+ self.log.info("Descriptors with no type cannot be active")
+ self.test_importdesc({"desc": descsum_create("pk(tpubDCJtdt5dgJpdhW4MtaVYDhG4T4tF6jcLR1PxL43q9pq1mxvXgMS9Mzw1HnXG15vxUGQJMMSqCQHMTy3F1eW5VkgVroWzchsPD5BUojrcWs8/*)"),
+ "active": True,
+ "range": 1,
+ "timestamp": "now"},
+ success=True,
+ warnings=["Unknown output type, cannot set descriptor to active."])
+
+if __name__ == '__main__':
+ ImportDescriptorsTest().main()
diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py
index f152fcd1a4..bd4fcdabcf 100755
--- a/test/functional/wallet_importmulti.py
+++ b/test/functional/wallet_importmulti.py
@@ -32,6 +32,7 @@ from test_framework.wallet_util import (
test_address,
)
+
class ImportMultiTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
@@ -51,7 +52,7 @@ class ImportMultiTest(BitcoinTestFramework):
result = self.nodes[1].importmulti([req])
observed_warnings = []
if 'warnings' in result[0]:
- observed_warnings = result[0]['warnings']
+ observed_warnings = result[0]['warnings']
assert_equal("\n".join(sorted(warnings)), "\n".join(sorted(observed_warnings)))
assert_equal(result[0]['success'], success)
if error_code is not None:
@@ -63,6 +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()
node0_address1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
@@ -257,6 +259,7 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
+ self.nodes[1].syncwithvalidationinterfacequeue()
self.log.info("Should import a p2sh")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},
@@ -277,6 +280,7 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
+ self.nodes[1].syncwithvalidationinterfacequeue()
self.log.info("Should import a p2sh with respective redeem script")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},
@@ -297,6 +301,7 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
+ self.nodes[1].syncwithvalidationinterfacequeue()
self.log.info("Should import a p2sh with respective redeem script and private keys")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},
@@ -322,6 +327,7 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
+ self.nodes[1].syncwithvalidationinterfacequeue()
self.log.info("Should import a p2sh with respective redeem script and private keys")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},
@@ -851,5 +857,6 @@ class ImportMultiTest(BitcoinTestFramework):
addr = wrpc.getnewaddress('', 'bech32')
assert_equal(addr, addresses[i])
+
if __name__ == '__main__':
ImportMultiTest().main()
diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py
index e3aeb61197..40a2b3ab6a 100755
--- a/test/functional/wallet_keypool.py
+++ b/test/functional/wallet_keypool.py
@@ -5,6 +5,7 @@
"""Test the wallet keypool and interaction with wallet encryption/locking."""
import time
+from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
@@ -21,16 +22,63 @@ class KeyPoolTest(BitcoinTestFramework):
addr_before_encrypting = nodes[0].getnewaddress()
addr_before_encrypting_data = nodes[0].getaddressinfo(addr_before_encrypting)
wallet_info_old = nodes[0].getwalletinfo()
- assert addr_before_encrypting_data['hdseedid'] == wallet_info_old['hdseedid']
+ if not self.options.descriptors:
+ assert addr_before_encrypting_data['hdseedid'] == wallet_info_old['hdseedid']
# Encrypt wallet and wait to terminate
nodes[0].encryptwallet('test')
+ if self.options.descriptors:
+ # Import hardened derivation only descriptors
+ nodes[0].walletpassphrase('test', 10)
+ nodes[0].importdescriptors([
+ {
+ "desc": "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/*h)#y4dfsj7n",
+ "timestamp": "now",
+ "range": [0,0],
+ "active": True
+ },
+ {
+ "desc": "pkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1h/*h)#a0nyvl0k",
+ "timestamp": "now",
+ "range": [0,0],
+ "active": True
+ },
+ {
+ "desc": "sh(wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/2h/*h))#lmeu2axg",
+ "timestamp": "now",
+ "range": [0,0],
+ "active": True
+ },
+ {
+ "desc": "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/3h/*h)#jkl636gm",
+ "timestamp": "now",
+ "range": [0,0],
+ "active": True,
+ "internal": True
+ },
+ {
+ "desc": "pkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/4h/*h)#l3crwaus",
+ "timestamp": "now",
+ "range": [0,0],
+ "active": True,
+ "internal": True
+ },
+ {
+ "desc": "sh(wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/5h/*h))#qg8wa75f",
+ "timestamp": "now",
+ "range": [0,0],
+ "active": True,
+ "internal": True
+ }
+ ])
+ nodes[0].walletlock()
# Keep creating keys
addr = nodes[0].getnewaddress()
addr_data = nodes[0].getaddressinfo(addr)
wallet_info = nodes[0].getwalletinfo()
- assert addr_before_encrypting_data['hdseedid'] != wallet_info['hdseedid']
- assert addr_data['hdseedid'] == wallet_info['hdseedid']
+ assert addr_before_encrypting_data['hdmasterfingerprint'] != addr_data['hdmasterfingerprint']
+ if not self.options.descriptors:
+ assert addr_data['hdseedid'] == wallet_info['hdseedid']
assert_raises_rpc_error(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress)
# put six (plus 2) new keys in the keypool (100% external-, +100% internal-keys, 1 in min)
@@ -38,8 +86,12 @@ class KeyPoolTest(BitcoinTestFramework):
nodes[0].keypoolrefill(6)
nodes[0].walletlock()
wi = nodes[0].getwalletinfo()
- assert_equal(wi['keypoolsize_hd_internal'], 6)
- assert_equal(wi['keypoolsize'], 6)
+ if self.options.descriptors:
+ assert_equal(wi['keypoolsize_hd_internal'], 18)
+ assert_equal(wi['keypoolsize'], 18)
+ else:
+ assert_equal(wi['keypoolsize_hd_internal'], 6)
+ assert_equal(wi['keypoolsize'], 6)
# drain the internal keys
nodes[0].getrawchangeaddress()
@@ -53,12 +105,12 @@ class KeyPoolTest(BitcoinTestFramework):
assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].getrawchangeaddress)
# drain the external keys
- addr.add(nodes[0].getnewaddress())
- addr.add(nodes[0].getnewaddress())
- addr.add(nodes[0].getnewaddress())
- addr.add(nodes[0].getnewaddress())
- addr.add(nodes[0].getnewaddress())
- addr.add(nodes[0].getnewaddress())
+ addr.add(nodes[0].getnewaddress(address_type="bech32"))
+ addr.add(nodes[0].getnewaddress(address_type="bech32"))
+ addr.add(nodes[0].getnewaddress(address_type="bech32"))
+ addr.add(nodes[0].getnewaddress(address_type="bech32"))
+ addr.add(nodes[0].getnewaddress(address_type="bech32"))
+ addr.add(nodes[0].getnewaddress(address_type="bech32"))
assert len(addr) == 6
# the next one should fail
assert_raises_rpc_error(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress)
@@ -79,8 +131,62 @@ class KeyPoolTest(BitcoinTestFramework):
nodes[0].walletpassphrase('test', 100)
nodes[0].keypoolrefill(100)
wi = nodes[0].getwalletinfo()
- assert_equal(wi['keypoolsize_hd_internal'], 100)
- assert_equal(wi['keypoolsize'], 100)
+ if self.options.descriptors:
+ assert_equal(wi['keypoolsize_hd_internal'], 300)
+ assert_equal(wi['keypoolsize'], 300)
+ else:
+ assert_equal(wi['keypoolsize_hd_internal'], 100)
+ assert_equal(wi['keypoolsize'], 100)
+
+ # create a blank wallet
+ nodes[0].createwallet(wallet_name='w2', blank=True, disable_private_keys=True)
+ w2 = nodes[0].get_wallet_rpc('w2')
+
+ # refer to initial wallet as w1
+ w1 = nodes[0].get_wallet_rpc('')
+
+ # import private key and fund it
+ address = addr.pop()
+ desc = w1.getaddressinfo(address)['desc']
+ if self.options.descriptors:
+ res = w2.importdescriptors([{'desc': desc, 'timestamp': 'now'}])
+ else:
+ res = w2.importmulti([{'desc': desc, 'timestamp': 'now'}])
+ assert_equal(res[0]['success'], True)
+ w1.walletpassphrase('test', 100)
+
+ res = w1.sendtoaddress(address=address, amount=0.00010000)
+ nodes[0].generate(1)
+ destination = addr.pop()
+
+ # Using a fee rate (10 sat / byte) well above the minimum relay rate
+ # creating a 5,000 sat transaction with change should not be possible
+ assert_raises_rpc_error(-4, "Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.", w2.walletcreatefundedpsbt, inputs=[], outputs=[{addr.pop(): 0.00005000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010})
+
+ # creating a 10,000 sat transaction without change, with a manual input, should still be possible
+ res = w2.walletcreatefundedpsbt(inputs=w2.listunspent(), outputs=[{destination: 0.00010000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010})
+ assert_equal("psbt" in res, True)
+
+ # creating a 10,000 sat transaction without change should still be possible
+ res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00010000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010})
+ assert_equal("psbt" in res, True)
+ # should work without subtractFeeFromOutputs if the exact fee is subtracted from the amount
+ res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00008900}], options={"feeRate": 0.00010})
+ assert_equal("psbt" in res, True)
+
+ # dust change should be removed
+ res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00008800}], options={"feeRate": 0.00010})
+ assert_equal("psbt" in res, True)
+
+ # create a transaction without change at the maximum fee rate, such that the output is still spendable:
+ res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00010000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.0008824})
+ assert_equal("psbt" in res, True)
+ assert_equal(res["fee"], Decimal("0.00009706"))
+
+ # creating a 10,000 sat transaction with a manual change address should be possible
+ res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00010000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010, "changeAddress": addr.pop()})
+ assert_equal("psbt" in res, True)
+
if __name__ == '__main__':
KeyPoolTest().main()
diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py
index 829633a050..102ed23fba 100755
--- a/test/functional/wallet_keypool_topup.py
+++ b/test/functional/wallet_keypool_topup.py
@@ -79,7 +79,15 @@ class KeypoolRestoreTest(BitcoinTestFramework):
assert_equal(self.nodes[idx].getbalance(), 15)
assert_equal(self.nodes[idx].listtransactions()[0]['category'], "receive")
# Check that we have marked all keys up to the used keypool key as used
- assert_equal(self.nodes[idx].getaddressinfo(self.nodes[idx].getnewaddress())['hdkeypath'], "m/0'/0'/110'")
+ if self.options.descriptors:
+ if output_type == 'legacy':
+ assert_equal(self.nodes[idx].getaddressinfo(self.nodes[idx].getnewaddress(address_type=output_type))['hdkeypath'], "m/44'/1'/0'/0/110")
+ elif output_type == 'p2sh-segwit':
+ assert_equal(self.nodes[idx].getaddressinfo(self.nodes[idx].getnewaddress(address_type=output_type))['hdkeypath'], "m/49'/1'/0'/0/110")
+ elif output_type == 'bech32':
+ assert_equal(self.nodes[idx].getaddressinfo(self.nodes[idx].getnewaddress(address_type=output_type))['hdkeypath'], "m/84'/1'/0'/0/110")
+ else:
+ assert_equal(self.nodes[idx].getaddressinfo(self.nodes[idx].getnewaddress(address_type=output_type))['hdkeypath'], "m/0'/0'/110'")
if __name__ == '__main__':
diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py
index 337d2e55d9..f8d1720469 100755
--- a/test/functional/wallet_labels.py
+++ b/test/functional/wallet_labels.py
@@ -115,15 +115,16 @@ class WalletLabelsTest(BitcoinTestFramework):
assert_raises_rpc_error(-11, "No addresses with label", node.getaddressesbylabel, "")
# Check that addmultisigaddress can assign labels.
- for label in labels:
- addresses = []
- for x in range(10):
- addresses.append(node.getnewaddress())
- multisig_address = node.addmultisigaddress(5, addresses, label.name)['address']
- label.add_address(multisig_address)
- label.purpose[multisig_address] = "send"
- label.verify(node)
- node.generate(101)
+ if not self.options.descriptors:
+ for label in labels:
+ addresses = []
+ for x in range(10):
+ addresses.append(node.getnewaddress())
+ multisig_address = node.addmultisigaddress(5, addresses, label.name)['address']
+ label.add_address(multisig_address)
+ label.purpose[multisig_address] = "send"
+ label.verify(node)
+ node.generate(101)
# Check that setlabel can change the label of an address from a
# different label.
diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py
index 6f248c9bd3..6d51ca6c93 100755
--- a/test/functional/wallet_listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
@@ -2,7 +2,7 @@
# Copyright (c) 2017-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.
-"""Test the listsincelast RPC."""
+"""Test the listsinceblock RPC."""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.messages import BIP125_SEQUENCE_NUMBER
@@ -38,6 +38,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
self.double_spends_filtered()
def test_no_blockhash(self):
+ self.log.info("Test no blockhash")
txid = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 1)
blockhash, = self.nodes[2].generate(1)
blockheight = self.nodes[2].getblockheader(blockhash)['height']
@@ -63,6 +64,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
"transactions": txs})
def test_invalid_blockhash(self):
+ self.log.info("Test invalid blockhash")
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].listsinceblock,
"42759cde25462784395a337460bde75f58e73d3f08bd31fdc3507cbac856a2c4")
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].listsinceblock,
@@ -100,6 +102,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
This test only checks that [tx0] is present.
'''
+ self.log.info("Test reorg")
# Split network into two
self.split_network()
@@ -108,23 +111,21 @@ class ListSinceBlockTest(BitcoinTestFramework):
senttx = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 1)
# generate on both sides
- lastblockhash = self.nodes[1].generate(6)[5]
- self.nodes[2].generate(7)
- self.log.info('lastblockhash=%s' % (lastblockhash))
+ nodes1_last_blockhash = self.nodes[1].generate(6)[-1]
+ nodes2_first_blockhash = self.nodes[2].generate(7)[0]
+ self.log.debug("nodes[1] last blockhash = {}".format(nodes1_last_blockhash))
+ self.log.debug("nodes[2] first blockhash = {}".format(nodes2_first_blockhash))
self.sync_all(self.nodes[:2])
self.sync_all(self.nodes[2:])
self.join_network()
- # listsinceblock(lastblockhash) should now include tx, as seen from nodes[0]
- lsbres = self.nodes[0].listsinceblock(lastblockhash)
- found = False
- for tx in lsbres['transactions']:
- if tx['txid'] == senttx:
- found = True
- break
- assert found
+ # listsinceblock(nodes1_last_blockhash) should now include tx as seen from nodes[0]
+ # and return the block height which listsinceblock now exposes since a5e7795.
+ transactions = self.nodes[0].listsinceblock(nodes1_last_blockhash)['transactions']
+ found = next(tx for tx in transactions if tx['txid'] == senttx)
+ assert_equal(found['blockheight'], self.nodes[0].getblockheader(nodes2_first_blockhash)['height'])
def test_double_spend(self):
'''
@@ -155,6 +156,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
until the fork point, and to include all transactions that relate to the
node wallet.
'''
+ self.log.info("Test double spend")
self.sync_all()
@@ -234,6 +236,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
3. It is listed with a confirmation count of 2 (bb3, bb4), not
3 (aa1, aa2, aa3).
'''
+ self.log.info("Test double send")
self.sync_all()
@@ -302,6 +305,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
`listsinceblock` was returning conflicted transactions even if they
occurred before the specified cutoff blockhash
'''
+ self.log.info("Test spends filtered")
spending_node = self.nodes[2]
dest_address = spending_node.getnewaddress()
diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py
index 8c44a070b8..8ff663ccd2 100755
--- a/test/functional/wallet_listtransactions.py
+++ b/test/functional/wallet_listtransactions.py
@@ -97,6 +97,8 @@ class ListTransactionsTest(BitcoinTestFramework):
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")},
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index f2fa41b647..c569416292 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -1,11 +1,12 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2019 The Bitcoin Core developers
+# Copyright (c) 2017-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 multiwallet.
Verify that a bitcoind node can load multiple wallet files
"""
+from decimal import Decimal
import os
import shutil
import time
@@ -24,6 +25,7 @@ class MultiWalletTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
+ self.rpc_timeout = 120
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -124,10 +126,6 @@ class MultiWalletTest(BitcoinTestFramework):
self.nodes[0].assert_start_raises_init_error(['-salvagewallet', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file")
self.nodes[0].assert_start_raises_init_error(['-salvagewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file")
- self.log.info("Do not allow -upgradewallet with multiwallet")
- self.nodes[0].assert_start_raises_init_error(['-upgradewallet', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file")
- self.nodes[0].assert_start_raises_init_error(['-upgradewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file")
-
# if wallets/ doesn't exist, datadir should be the default wallet dir
wallet_dir2 = data_dir('walletdir')
os.rename(wallet_dir(), wallet_dir2)
@@ -192,9 +190,9 @@ class MultiWalletTest(BitcoinTestFramework):
self.log.info('Check for per-wallet settxfee call')
assert_equal(w1.getwalletinfo()['paytxfee'], 0)
assert_equal(w2.getwalletinfo()['paytxfee'], 0)
- w2.settxfee(4.0)
+ w2.settxfee(0.001)
assert_equal(w1.getwalletinfo()['paytxfee'], 0)
- assert_equal(w2.getwalletinfo()['paytxfee'], 4.0)
+ assert_equal(w2.getwalletinfo()['paytxfee'], Decimal('0.00100000'))
self.log.info("Test dynamic wallet loading")
@@ -235,10 +233,10 @@ class MultiWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "Wallet file verification failed: Error loading wallet wallet.dat. Duplicate -wallet filename specified.", self.nodes[0].loadwallet, 'wallet.dat')
# Fail to load if one wallet is a copy of another
- assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
+ assert_raises_rpc_error(-4, "BerkeleyBatch: 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(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
+ assert_raises_rpc_error(-4, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
# Fail to load if wallet file is a symlink
@@ -331,18 +329,5 @@ class MultiWalletTest(BitcoinTestFramework):
self.nodes[0].unloadwallet(wallet)
self.nodes[1].loadwallet(wallet)
- # Fail to load if wallet is downgraded
- shutil.copytree(os.path.join(self.options.data_wallets_dir, 'high_minversion'), wallet_dir('high_minversion'))
- self.restart_node(0, extra_args=['-upgradewallet={}'.format(FEATURE_LATEST)])
- assert {'name': 'high_minversion'} in self.nodes[0].listwalletdir()['wallets']
- self.log.info("Fail -upgradewallet that results in downgrade")
- assert_raises_rpc_error(
- -4,
- 'Wallet loading failed: Error loading {}: Wallet requires newer version of {}'.format(
- wallet_dir('high_minversion', 'wallet.dat'), self.config['environment']['PACKAGE_NAME']),
- lambda: self.nodes[0].loadwallet(filename='high_minversion'),
- )
-
-
if __name__ == '__main__':
MultiWalletTest().main()
diff --git a/test/functional/wallet_resendwallettransactions.py b/test/functional/wallet_resendwallettransactions.py
index 91d26e9cb3..b384998d56 100755
--- a/test/functional/wallet_resendwallettransactions.py
+++ b/test/functional/wallet_resendwallettransactions.py
@@ -1,29 +1,16 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2019 The Bitcoin Core developers
+# Copyright (c) 2017-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 that the wallet resends transactions periodically."""
-from collections import defaultdict
import time
from test_framework.blocktools import create_block, create_coinbase
from test_framework.messages import ToHex
-from test_framework.mininode import P2PInterface, mininode_lock
+from test_framework.mininode import P2PTxInvStore, mininode_lock
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, wait_until
-class P2PStoreTxInvs(P2PInterface):
- def __init__(self):
- super().__init__()
- self.tx_invs_received = defaultdict(int)
-
- def on_inv(self, message):
- # Store how many times invs have been received for each tx.
- for i in message.inv:
- if i.type == 1:
- # save txid
- self.tx_invs_received[i.hash] += 1
-
class ResendWalletTransactionsTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
@@ -34,7 +21,7 @@ class ResendWalletTransactionsTest(BitcoinTestFramework):
def run_test(self):
node = self.nodes[0] # alias
- node.add_p2p_connection(P2PStoreTxInvs())
+ node.add_p2p_connection(P2PTxInvStore())
self.log.info("Create a new transaction and wait until it's broadcast")
txid = int(node.sendtoaddress(node.getnewaddress(), 1), 16)
@@ -49,7 +36,7 @@ class ResendWalletTransactionsTest(BitcoinTestFramework):
wait_until(lambda: node.p2p.tx_invs_received[txid] >= 1, lock=mininode_lock)
# Add a second peer since txs aren't rebroadcast to the same peer (see filterInventoryKnown)
- node.add_p2p_connection(P2PStoreTxInvs())
+ node.add_p2p_connection(P2PTxInvStore())
self.log.info("Create a block")
# Create and submit a block without the transaction.
@@ -63,14 +50,17 @@ class ResendWalletTransactionsTest(BitcoinTestFramework):
node.submitblock(ToHex(block))
# Transaction should not be rebroadcast
+ node.syncwithvalidationinterfacequeue()
node.p2ps[1].sync_with_ping()
assert_equal(node.p2ps[1].tx_invs_received[txid], 0)
- self.log.info("Transaction should be rebroadcast after 30 minutes")
- # Use mocktime and give an extra 5 minutes to be sure.
- rebroadcast_time = int(time.time()) + 41 * 60
+ 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.
+ rebroadcast_time = int(time.time()) + 36 * 60 * 60
node.setmocktime(rebroadcast_time)
wait_until(lambda: node.p2ps[1].tx_invs_received[txid] >= 1, lock=mininode_lock)
+
if __name__ == '__main__':
ResendWalletTransactionsTest().main()
diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py
index 99559090ee..ad23206c90 100755
--- a/test/functional/wallet_txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -29,7 +29,7 @@ class TxnMallTest(BitcoinTestFramework):
def setup_network(self):
# Start with split network:
- super(TxnMallTest, self).setup_network()
+ super().setup_network()
disconnect_nodes(self.nodes[1], 2)
disconnect_nodes(self.nodes[2], 1)
diff --git a/test/functional/wallet_upgradewallet.py b/test/functional/wallet_upgradewallet.py
new file mode 100755
index 0000000000..e7e71bf3f6
--- /dev/null
+++ b/test/functional/wallet_upgradewallet.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python3
+# 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.
+"""upgradewallet RPC functional test
+
+Test upgradewallet RPC. Download v0.15.2 v0.16.3 node binaries:
+
+contrib/devtools/previous_release.sh -b v0.15.2 v0.16.3
+"""
+
+import os
+import shutil
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ adjust_bitcoin_conf_for_pre_17,
+ assert_equal,
+ assert_greater_than,
+ assert_is_hex_string,
+)
+
+
+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
+ ]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+ self.skip_if_no_previous_releases()
+
+ def setup_network(self):
+ self.setup_nodes()
+
+ def setup_nodes(self):
+ self.add_nodes(self.num_nodes, extra_args=self.extra_args, versions=[
+ None,
+ 160300,
+ 150200,
+ ])
+ # adapt bitcoin.conf, because older bitcoind's don't recognize config sections
+ adjust_bitcoin_conf_for_pre_17(self.nodes[1].bitcoinconf)
+ adjust_bitcoin_conf_for_pre_17(self.nodes[2].bitcoinconf)
+ self.start_nodes()
+
+ def dumb_sync_blocks(self):
+ """
+ Little helper to sync older wallets.
+ Notice that v0.15.2's regtest is hardforked, so there is
+ no sync for it.
+ v0.15.2 is only being used to test for version upgrade
+ and master hash key presence.
+ v0.16.3 is being used to test for version upgrade and balances.
+ Further info: https://github.com/bitcoin/bitcoin/pull/18774#discussion_r416967844
+ """
+ node_from = self.nodes[0]
+ v16_3_node = self.nodes[1]
+ to_height = node_from.getblockcount()
+ height = self.nodes[1].getblockcount()
+ for i in range(height, to_height+1):
+ b = node_from.getblock(blockhash=node_from.getblockhash(i), verbose=0)
+ v16_3_node.submitblock(b)
+ assert_equal(v16_3_node.getblockcount(), to_height)
+
+ def run_test(self):
+ self.nodes[0].generatetoaddress(101, self.nodes[0].getnewaddress())
+ self.dumb_sync_blocks()
+ # # Sanity check the test framework:
+ res = self.nodes[0].getblockchaininfo()
+ assert_equal(res['blocks'], 101)
+ node_master = self.nodes[0]
+ v16_3_node = self.nodes[1]
+ v15_2_node = self.nodes[2]
+
+ # Send coins to old wallets for later conversion checks.
+ v16_3_wallet = v16_3_node.get_wallet_rpc('wallet.dat')
+ v16_3_address = v16_3_wallet.getnewaddress()
+ node_master.generatetoaddress(101, v16_3_address)
+ self.dumb_sync_blocks()
+ v16_3_balance = v16_3_wallet.getbalance()
+
+ 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")
+ 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")
+ 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('')
+
+ wallet = node_master.get_wallet_rpc('')
+ old_version = wallet.getwalletinfo()["walletversion"]
+
+ # 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)
+ # 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('')
+ # 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)
+ # after conversion master key hash should be present
+ assert_is_hex_string(wallet.getwalletinfo()['hdseedid'])
+
+if __name__ == '__main__':
+ UpgradeWalletTest().main()
diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py
index 6b687060e2..e2454c4237 100755
--- a/test/fuzz/test_runner.py
+++ b/test/fuzz/test_runner.py
@@ -1,53 +1,24 @@
#!/usr/bin/env python3
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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.
"""Run fuzz test targets.
"""
+from concurrent.futures import ThreadPoolExecutor, as_completed
import argparse
import configparser
+import logging
import os
-import sys
import subprocess
-import logging
+import sys
-# Fuzzers known to lack a seed corpus in https://github.com/bitcoin-core/qa-assets/tree/master/fuzz_seed_corpus
-FUZZERS_MISSING_CORPORA = [
- "addr_info_deserialize",
- "base_encode_decode",
- "block",
- "block_file_info_deserialize",
- "block_filter_deserialize",
- "block_header_and_short_txids_deserialize",
- "decode_tx",
- "fee_rate_deserialize",
- "flat_file_pos_deserialize",
- "hex",
- "integer",
- "key_origin_info_deserialize",
- "merkle_block_deserialize",
- "out_point_deserialize",
- "parse_hd_keypath",
- "parse_numbers",
- "parse_script",
- "parse_univalue",
- "partial_merkle_tree_deserialize",
- "partially_signed_transaction_deserialize",
- "prefilled_transaction_deserialize",
- "psbt_input_deserialize",
- "psbt_output_deserialize",
- "pub_key_deserialize",
- "script_deserialize",
- "strprintf",
- "sub_net_deserialize",
- "tx_in",
- "tx_in_deserialize",
- "tx_out",
-]
def main():
- parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ description='''Run the fuzz targets with all inputs from the seed_dir once.''',
+ )
parser.add_argument(
"-l",
"--loglevel",
@@ -56,9 +27,20 @@ def main():
help="log events at this level and higher to the console. Can be set to DEBUG, INFO, WARNING, ERROR or CRITICAL. Passing --loglevel DEBUG will output all logs to console.",
)
parser.add_argument(
- '--export_coverage',
+ '--valgrind',
action='store_true',
- help='If true, export coverage information to files in the seed corpus',
+ help='If true, run fuzzing binaries under the valgrind memory error detector',
+ )
+ parser.add_argument(
+ '-x',
+ '--exclude',
+ help="A comma-separated list of targets to exclude",
+ )
+ parser.add_argument(
+ '--par',
+ type=int,
+ default=4,
+ help='How many targets to merge or execute in parallel.',
)
parser.add_argument(
'seed_dir',
@@ -69,6 +51,10 @@ def main():
nargs='*',
help='The target(s) to run. Default is to run all targets.',
)
+ parser.add_argument(
+ '--m_dir',
+ help='Merge inputs from this directory into the seed_dir. Needs /target subdirectory.',
+ )
args = parser.parse_args()
@@ -94,7 +80,7 @@ def main():
logging.error("No fuzz targets found")
sys.exit(1)
- logging.info("Fuzz targets found: {}".format(test_list_all))
+ logging.debug("{} fuzz target(s) found: {}".format(len(test_list_all), " ".join(sorted(test_list_all))))
args.target = args.target or test_list_all # By default run all
test_list_error = list(set(args.target).difference(set(test_list_all)))
@@ -103,7 +89,29 @@ def main():
test_list_selection = list(set(test_list_all).intersection(set(args.target)))
if not test_list_selection:
logging.error("No fuzz targets selected")
- logging.info("Fuzz targets selected: {}".format(test_list_selection))
+ if args.exclude:
+ for excluded_target in args.exclude.split(","):
+ if excluded_target not in test_list_selection:
+ logging.error("Target \"{}\" not found in current target list.".format(excluded_target))
+ continue
+ test_list_selection.remove(excluded_target)
+ test_list_selection.sort()
+
+ logging.info("{} of {} detected fuzz target(s) selected: {}".format(len(test_list_selection), len(test_list_all), " ".join(test_list_selection)))
+
+ test_list_seedless = []
+ for t in test_list_selection:
+ corpus_path = os.path.join(args.seed_dir, t)
+ if not os.path.exists(corpus_path) or len(os.listdir(corpus_path)) == 0:
+ test_list_seedless.append(t)
+ test_list_seedless.sort()
+ if test_list_seedless:
+ logging.info(
+ "Fuzzing harnesses lacking a seed corpus: {}".format(
+ " ".join(test_list_seedless)
+ )
+ )
+ logging.info("Please consider adding a fuzz seed corpus at https://github.com/bitcoin-core/qa-assets")
try:
help_output = subprocess.run(
@@ -111,7 +119,7 @@ def main():
os.path.join(config["environment"]["BUILDDIR"], 'src', 'test', 'fuzz', test_list_selection[0]),
'-help=1',
],
- timeout=10,
+ timeout=20,
check=True,
stderr=subprocess.PIPE,
universal_newlines=True,
@@ -123,37 +131,84 @@ def main():
logging.error("subprocess timed out: Currently only libFuzzer is supported")
sys.exit(1)
- run_once(
- corpus=args.seed_dir,
- test_list=test_list_selection,
- build_dir=config["environment"]["BUILDDIR"],
- export_coverage=args.export_coverage,
- )
+ with ThreadPoolExecutor(max_workers=args.par) as fuzz_pool:
+ if args.m_dir:
+ merge_inputs(
+ fuzz_pool=fuzz_pool,
+ corpus=args.seed_dir,
+ test_list=test_list_selection,
+ build_dir=config["environment"]["BUILDDIR"],
+ merge_dir=args.m_dir,
+ )
+ return
+
+ run_once(
+ fuzz_pool=fuzz_pool,
+ corpus=args.seed_dir,
+ test_list=test_list_selection,
+ build_dir=config["environment"]["BUILDDIR"],
+ use_valgrind=args.valgrind,
+ )
+
+
+def merge_inputs(*, fuzz_pool, corpus, test_list, build_dir, merge_dir):
+ logging.info("Merge the inputs in the passed dir into the seed_dir. Passed dir {}".format(merge_dir))
+ jobs = []
+ for t in test_list:
+ args = [
+ os.path.join(build_dir, 'src', 'test', 'fuzz', t),
+ '-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),
+ os.path.join(merge_dir, t),
+ ]
+ os.makedirs(os.path.join(corpus, t), exist_ok=True)
+ os.makedirs(os.path.join(merge_dir, t), exist_ok=True)
+ 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
+ logging.debug(output)
-def run_once(*, corpus, test_list, build_dir, export_coverage):
+ jobs.append(fuzz_pool.submit(job, t, args))
+
+ for future in as_completed(jobs):
+ future.result()
+
+
+def run_once(*, fuzz_pool, corpus, test_list, build_dir, use_valgrind):
+ jobs = []
for t in test_list:
corpus_path = os.path.join(corpus, t)
- if t in FUZZERS_MISSING_CORPORA:
- os.makedirs(corpus_path, exist_ok=True)
+ os.makedirs(corpus_path, exist_ok=True)
args = [
os.path.join(build_dir, 'src', 'test', 'fuzz', t),
'-runs=1',
- '-detect_leaks=0',
corpus_path,
]
- logging.debug('Run {} with args {}'.format(t, args))
- result = subprocess.run(args, stderr=subprocess.PIPE, universal_newlines=True)
- output = result.stderr
- logging.debug('Output: {}'.format(output))
- result.check_returncode()
- if not export_coverage:
- continue
- for l in output.splitlines():
- if 'INITED' in l:
- with open(os.path.join(corpus, t + '_coverage'), 'w', encoding='utf-8') as cov_file:
- cov_file.write(l)
- break
+ if use_valgrind:
+ args = ['valgrind', '--quiet', '--error-exitcode=1'] + args
+
+ def job(t, args):
+ output = 'Run {} with args {}'.format(t, args)
+ result = subprocess.run(args, stderr=subprocess.PIPE, universal_newlines=True)
+ output += result.stderr
+ return output, result
+
+ jobs.append(fuzz_pool.submit(job, t, args))
+
+ for future in as_completed(jobs):
+ output, result = future.result()
+ logging.debug(output)
+ try:
+ result.check_returncode()
+ except subprocess.CalledProcessError as e:
+ if e.stdout:
+ logging.info(e.stdout)
+ if e.stderr:
+ logging.info(e.stderr)
+ logging.info("Target \"{}\" failed with exit code {}".format(" ".join(result.args), e.returncode))
+ sys.exit(1)
def parse_test_list(makefile):
diff --git a/test/lint/README.md b/test/lint/README.md
index f415d619ee..6b95cc3540 100644
--- a/test/lint/README.md
+++ b/test/lint/README.md
@@ -21,6 +21,7 @@ maintained:
* for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork)
* for `src/univalue`: https://github.com/bitcoin-core/univalue.git (branch master)
* for `src/crypto/ctaes`: https://github.com/bitcoin-core/ctaes.git (branch master)
+* for `src/crc32c`: https://github.com/google/crc32c.git (branch master)
Usage: `git-subtree-check.sh DIR (COMMIT)`
diff --git a/test/lint/extended-lint-all.sh b/test/lint/extended-lint-all.sh
index 65c51e02f5..be5d9db4a9 100755
--- a/test/lint/extended-lint-all.sh
+++ b/test/lint/extended-lint-all.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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.
#
diff --git a/test/lint/extended-lint-cppcheck.sh b/test/lint/extended-lint-cppcheck.sh
index 47df25ba6b..20021d8605 100755
--- a/test/lint/extended-lint-cppcheck.sh
+++ b/test/lint/extended-lint-cppcheck.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2019 The Bitcoin Core developers
+# Copyright (c) 2019-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.
#
@@ -65,8 +65,8 @@ 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/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 -DHAVE_WORKING_BOOST_SLEEP_FOR -I src/ -q 2>&1 | sort -u | \
+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 | \
grep -E "${ENABLED_CHECKS_REGEXP}" | \
grep -vE "${IGNORED_WARNINGS_REGEXP}")
if [[ ${WARNINGS} != "" ]]; then
diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh
index bbd94dd6c7..6bd02d45ac 100755
--- a/test/lint/lint-circular-dependencies.sh
+++ b/test/lint/lint-circular-dependencies.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
#
diff --git a/test/lint/lint-format-strings.sh b/test/lint/lint-format-strings.sh
index 184c3682c8..cb3ec09ae6 100755
--- a/test/lint/lint-format-strings.sh
+++ b/test/lint/lint-format-strings.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
#
diff --git a/test/lint/lint-include-guards.sh b/test/lint/lint-include-guards.sh
index 2d3beaf582..3a0494c190 100755
--- a/test/lint/lint-include-guards.sh
+++ b/test/lint/lint-include-guards.sh
@@ -10,7 +10,7 @@ export LC_ALL=C
HEADER_ID_PREFIX="BITCOIN_"
HEADER_ID_SUFFIX="_H"
-REGEXP_EXCLUDE_FILES_WITH_PREFIX="src/(crypto/ctaes/|leveldb/|secp256k1/|test/fuzz/FuzzedDataProvider.h|tinyformat.h|univalue/)"
+REGEXP_EXCLUDE_FILES_WITH_PREFIX="src/(crypto/ctaes/|leveldb/|crc32c/|secp256k1/|test/fuzz/FuzzedDataProvider.h|tinyformat.h|univalue/)"
EXIT_CODE=0
for HEADER_FILE in $(git ls-files -- "*.h" | grep -vE "^${REGEXP_EXCLUDE_FILES_WITH_PREFIX}")
diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh
index bb2bd4e56c..bd9c8337ac 100755
--- a/test/lint/lint-includes.sh
+++ b/test/lint/lint-includes.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
#
@@ -9,7 +9,7 @@
# Check includes: Check for duplicate includes. Enforce bracket syntax includes.
export LC_ALL=C
-IGNORE_REGEXP="/(leveldb|secp256k1|univalue)/"
+IGNORE_REGEXP="/(leveldb|secp256k1|univalue|crc32c)/"
# cd to root folder of git repo for git ls-files to work properly
cd "$(dirname $0)/../.." || exit 1
@@ -53,7 +53,6 @@ EXPECTED_BOOST_INCLUDES=(
boost/algorithm/string/classification.hpp
boost/algorithm/string/replace.hpp
boost/algorithm/string/split.hpp
- boost/chrono/chrono.hpp
boost/date_time/posix_time/posix_time.hpp
boost/filesystem.hpp
boost/filesystem/fstream.hpp
diff --git a/test/lint/lint-locale-dependence.sh b/test/lint/lint-locale-dependence.sh
index 35e58c2df6..e2bb403c4d 100755
--- a/test/lint/lint-locale-dependence.sh
+++ b/test/lint/lint-locale-dependence.sh
@@ -1,35 +1,21 @@
#!/usr/bin/env bash
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
export LC_ALL=C
KNOWN_VIOLATIONS=(
"src/bitcoin-tx.cpp.*stoul"
- "src/bitcoin-tx.cpp.*std::to_string"
"src/bitcoin-tx.cpp.*trim_right"
"src/dbwrapper.cpp.*stoul"
"src/dbwrapper.cpp:.*vsnprintf"
"src/httprpc.cpp.*trim"
"src/init.cpp:.*atoi"
- "src/qt/optionsmodel.cpp.*std::to_string"
"src/qt/rpcconsole.cpp:.*atoi"
"src/rest.cpp:.*strtol"
- "src/rpc/net.cpp.*std::to_string"
- "src/rpc/rawtransaction.cpp.*std::to_string"
- "src/rpc/util.cpp.*std::to_string"
- "src/test/addrman_tests.cpp.*std::to_string"
- "src/test/blockchain_tests.cpp.*std::to_string"
"src/test/dbwrapper_tests.cpp:.*snprintf"
- "src/test/denialofservice_tests.cpp.*std::to_string"
+ "src/test/fuzz/locale.cpp"
"src/test/fuzz/parse_numbers.cpp:.*atoi"
- "src/test/key_tests.cpp.*std::to_string"
- "src/test/net_tests.cpp.*std::to_string"
- "src/test/settings_tests.cpp.*std::to_string"
- "src/test/timedata_tests.cpp.*std::to_string"
- "src/test/util/setup_common.cpp.*std::to_string"
- "src/test/util_tests.cpp.*std::to_string"
- "src/test/util_threadnames_tests.cpp.*std::to_string"
"src/torcontrol.cpp:.*atoi"
"src/torcontrol.cpp:.*strtol"
"src/util/strencodings.cpp:.*atoi"
@@ -37,7 +23,6 @@ KNOWN_VIOLATIONS=(
"src/util/strencodings.cpp:.*strtoul"
"src/util/strencodings.h:.*atoi"
"src/util/system.cpp:.*atoi"
- "src/wallet/scriptpubkeyman.cpp.*std::to_string"
)
REGEXP_IGNORE_EXTERNAL_DEPENDENCIES="^src/(crypto/ctaes/|leveldb/|secp256k1/|tinyformat.h|univalue/)"
diff --git a/test/lint/lint-python-utf8-encoding.sh b/test/lint/lint-python-utf8-encoding.sh
index d03c20205d..7257919c98 100755
--- a/test/lint/lint-python-utf8-encoding.sh
+++ b/test/lint/lint-python-utf8-encoding.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2018 The Bitcoin Core developers
+# Copyright (c) 2018-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.
#
@@ -9,7 +9,7 @@
export LC_ALL=C
EXIT_CODE=0
-OUTPUT=$(git grep " open(" -- "*.py" | grep -vE "encoding=.(ascii|utf8|utf-8)." | grep -vE "open\([^,]*, ['\"][^'\"]*b[^'\"]*['\"]")
+OUTPUT=$(git grep " open(" -- "*.py" ":(exclude)src/crc32c/" | grep -vE "encoding=.(ascii|utf8|utf-8)." | grep -vE "open\([^,]*, ['\"][^'\"]*b[^'\"]*['\"]")
if [[ ${OUTPUT} != "" ]]; then
echo "Python's open(...) seems to be used to open text files without explicitly"
echo "specifying encoding=\"utf8\":"
@@ -17,7 +17,7 @@ if [[ ${OUTPUT} != "" ]]; then
echo "${OUTPUT}"
EXIT_CODE=1
fi
-OUTPUT=$(git grep "check_output(" -- "*.py" | grep "universal_newlines=True" | grep -vE "encoding=.(ascii|utf8|utf-8).")
+OUTPUT=$(git grep "check_output(" -- "*.py" ":(exclude)src/crc32c/"| grep "universal_newlines=True" | grep -vE "encoding=.(ascii|utf8|utf-8).")
if [[ ${OUTPUT} != "" ]]; then
echo "Python's check_output(...) seems to be used to get program outputs without explicitly"
echo "specifying encoding=\"utf8\":"
diff --git a/test/lint/lint-shebang.sh b/test/lint/lint-shebang.sh
index a666fdfecf..a5c8aa42b2 100755
--- a/test/lint/lint-shebang.sh
+++ b/test/lint/lint-shebang.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2018 The Bitcoin Core developers
+# Copyright (c) 2018-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.
diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh
index 63624e3ae0..2bb76ec286 100755
--- a/test/lint/lint-shell.sh
+++ b/test/lint/lint-shell.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2018-2019 The Bitcoin Core developers
+# 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.
#
@@ -41,20 +41,22 @@ if ! shellcheck "$EXCLUDE" $(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|sec
fi
if ! command -v yq > /dev/null; then
- echo "Skipping Gitian desriptor scripts checking since yq is not installed."
+ echo "Skipping Gitian descriptor scripts checking since yq is not installed."
exit $EXIT_CODE
fi
EXCLUDE_GITIAN=${EXCLUDE}",$(IFS=','; echo "${disabled_gitian[*]}")"
+SHELLCHECK_CMD="shellcheck --external-sources --check-sourced $EXCLUDE_GITIAN"
for descriptor in $(git ls-files -- 'contrib/gitian-descriptors/*.yml')
do
- echo
- echo "$descriptor"
+ script=$(basename "$descriptor")
# Use #!/bin/bash as gitian-builder/bin/gbuild does to complete a script.
- SCRIPT=$'#!/bin/bash\n'$(yq -r .script "$descriptor")
- if ! echo "$SCRIPT" | shellcheck "$EXCLUDE_GITIAN" -; then
+ echo "#!/bin/bash" > $script
+ yq -r .script "$descriptor" >> $script
+ if ! $SHELLCHECK_CMD $script; then
EXIT_CODE=1
fi
+ rm $script
done
exit $EXIT_CODE
diff --git a/test/lint/lint-spelling.ignore-words.txt b/test/lint/lint-spelling.ignore-words.txt
index 576ae94098..a7a97eb41f 100644
--- a/test/lint/lint-spelling.ignore-words.txt
+++ b/test/lint/lint-spelling.ignore-words.txt
@@ -12,3 +12,5 @@ keyserver
homogenous
setban
hist
+ser
+unselect
diff --git a/test/lint/lint-spelling.sh b/test/lint/lint-spelling.sh
index c7a3d0de44..cb84727ba5 100755
--- a/test/lint/lint-spelling.sh
+++ b/test/lint/lint-spelling.sh
@@ -15,6 +15,6 @@ if ! command -v codespell > /dev/null; then
fi
IGNORE_WORDS_FILE=test/lint/lint-spelling.ignore-words.txt
-if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/leveldb/" ":(exclude)src/qt/locale/" ":(exclude)src/qt/*.qrc" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/"); then
+if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/qt/locale/" ":(exclude)src/qt/*.qrc" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/"); then
echo "^ Warning: codespell identified likely spelling errors. Any false positives? Add them to the list of ignored words in ${IGNORE_WORDS_FILE}"
fi
diff --git a/test/lint/lint-submodule.sh b/test/lint/lint-submodule.sh
new file mode 100755
index 0000000000..d9aa021df7
--- /dev/null
+++ b/test/lint/lint-submodule.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.
+#
+# This script checks for git modules
+export LC_ALL=C
+EXIT_CODE=0
+
+CMD=$(git submodule status --recursive)
+if test -n "$CMD";
+then
+ echo These submodules were found, delete them:
+ echo "$CMD"
+ EXIT_CODE=1
+fi
+
+exit $EXIT_CODE
+
diff --git a/test/lint/lint-whitespace.sh b/test/lint/lint-whitespace.sh
index 861faf8516..d8bdb0a8d7 100755
--- a/test/lint/lint-whitespace.sh
+++ b/test/lint/lint-whitespace.sh
@@ -31,14 +31,14 @@ if [ -z "${TRAVIS_COMMIT_RANGE}" ]; then
fi
showdiff() {
- if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- "." ":(exclude)depends/patches/" ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/" ":(exclude)src/qt/locale/"; then
+ if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- "." ":(exclude)depends/patches/" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/" ":(exclude)src/qt/locale/"; then
echo "Failed to get a diff"
exit 1
fi
}
showcodediff() {
- if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- *.cpp *.h *.md *.py *.sh ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/" ":(exclude)src/qt/locale/"; then
+ if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- *.cpp *.h *.md *.py *.sh ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/" ":(exclude)src/qt/locale/"; then
echo "Failed to get a diff"
exit 1
fi
diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan
index b9c5c038d0..70eea34363 100644
--- a/test/sanitizer_suppressions/tsan
+++ b/test/sanitizer_suppressions/tsan
@@ -7,14 +7,6 @@ deadlock:WalletBatch
# Intentional deadlock in tests
deadlock:TestPotentialDeadLockDetected
-# Race due to unprotected calls to thread-unsafe BOOST_TEST_MESSAGE from different threads:
-# * G_TEST_LOG_FUN in the index thread
-# * boost test case invoker (entering a test case) in the main thread
-# TODO: get rid of BOOST_ macros, see also https://github.com/bitcoin/bitcoin/issues/8670
-race:blockfilter_index_initial_sync_invoker
-race:txindex_initial_sync_invoker
-race:validation_block_tests::TestSubscriber
-
# Wildcard for all gui tests, should be replaced with non-wildcard suppressions
race:src/qt/test/*
deadlock:src/qt/test/*
diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan
index f5de358bcb..b3d9b9e6ec 100644
--- a/test/sanitizer_suppressions/ubsan
+++ b/test/sanitizer_suppressions/ubsan
@@ -1,7 +1,5 @@
# -fsanitize=undefined suppressions
# =================================
-alignment:move.h
-alignment:prevector.h
float-divide-by-zero:policy/fees.cpp
float-divide-by-zero:validation.cpp
float-divide-by-zero:wallet/wallet.cpp
@@ -84,3 +82,4 @@ implicit-signed-integer-truncation:test/skiplist_tests.cpp
implicit-signed-integer-truncation:torcontrol.cpp
implicit-unsigned-integer-truncation:crypto/*
implicit-unsigned-integer-truncation:leveldb/*
+implicit-integer-sign-change:crc32c/*
diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json
index 761923a818..99cd4ab695 100644
--- a/test/util/data/bitcoin-util-test.json
+++ b/test/util/data/bitcoin-util-test.json
@@ -219,6 +219,12 @@
"description": "Parses a transaction with no inputs and a single output script (output in json)"
},
{ "exec": "./bitcoin-tx",
+ "args": ["-create", "outscript=0:123badscript"],
+ "return_code": 1,
+ "error_txt": "error: script parse error",
+ "description": "Create a new transaction with an invalid output script"
+ },
+ { "exec": "./bitcoin-tx",
"args": ["-create", "outscript=0:OP_DROP", "nversion=1"],
"output_cmp": "txcreatescript1.hex",
"description": "Create a new transaction with a single output script (OP_DROP)"
@@ -259,6 +265,40 @@
"description": "Create a new transaction with a single output script (OP_DROP) in a P2SH, wrapped in a P2SH (output as json)"
},
{ "exec": "./bitcoin-tx",
+ "args": ["-create", "outscript=0:9999999999"],
+ "return_code": 1,
+ "error_txt": "error: script parse error: decimal numeric value only allowed in the range -0xFFFFFFFF...0xFFFFFFFF",
+ "description": "Try to parse an output script with a decimal number above the allowed range"
+ },
+ { "exec": "./bitcoin-tx",
+ "args": ["-create", "outscript=0:4294967296"],
+ "return_code": 1,
+ "error_txt": "error: script parse error: decimal numeric value only allowed in the range -0xFFFFFFFF...0xFFFFFFFF",
+ "description": "Try to parse an output script with a decimal number just above the allowed range"
+ },
+ { "exec": "./bitcoin-tx",
+ "args": ["-create", "outscript=0:4294967295"],
+ "output_cmp": "txcreatescript5.hex",
+ "description": "Try to parse an output script with a decimal number at the upper limit of the allowed range"
+ },
+ { "exec": "./bitcoin-tx",
+ "args": ["-create", "outscript=0:-9999999999"],
+ "return_code": 1,
+ "error_txt": "error: script parse error: decimal numeric value only allowed in the range -0xFFFFFFFF...0xFFFFFFFF",
+ "description": "Try to parse an output script with a decimal number below the allowed range"
+ },
+ { "exec": "./bitcoin-tx",
+ "args": ["-create", "outscript=0:-4294967296"],
+ "return_code": 1,
+ "error_txt": "error: script parse error: decimal numeric value only allowed in the range -0xFFFFFFFF...0xFFFFFFFF",
+ "description": "Try to parse an output script with a decimal number just below the allowed range"
+ },
+ { "exec": "./bitcoin-tx",
+ "args": ["-create", "outscript=0:-4294967295"],
+ "output_cmp": "txcreatescript6.hex",
+ "description": "Try to parse an output script with a decimal number at the lower limit of the allowed range"
+ },
+ { "exec": "./bitcoin-tx",
"args":
["-create", "nversion=1",
"in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
diff --git a/test/util/data/txcreatescript5.hex b/test/util/data/txcreatescript5.hex
new file mode 100644
index 0000000000..48e0a12b0c
--- /dev/null
+++ b/test/util/data/txcreatescript5.hex
@@ -0,0 +1 @@
+02000000000100000000000000000605ffffffff0000000000
diff --git a/test/util/data/txcreatescript6.hex b/test/util/data/txcreatescript6.hex
new file mode 100644
index 0000000000..b98293813d
--- /dev/null
+++ b/test/util/data/txcreatescript6.hex
@@ -0,0 +1 @@
+02000000000100000000000000000605ffffffff8000000000