diff options
149 files changed, 9368 insertions, 3051 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index eace0b7121..0d026748b5 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,6 +1,6 @@ version: '{branch}.{build}' skip_tags: true -image: Visual Studio 2019 +image: Previous Visual Studio 2019 configuration: Release platform: x64 clone_depth: 5 diff --git a/.cirrus.yml b/.cirrus.yml index 6a496f00a3..237560fc2e 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -29,6 +29,7 @@ global_task_template: &GLOBAL_TASK_TEMPLATE depends_releases_cache: folder: "/tmp/cirrus-ci-build/releases" merge_base_script: + - if [ "$CIRRUS_PR" = "" ]; then exit 0; fi - bash -c "$PACKAGE_MANAGER_INSTALL git" - git fetch $CIRRUS_REPO_CLONE_URL $CIRRUS_BASE_BRANCH - git config --global user.email "ci@ci.ci" @@ -113,14 +114,6 @@ task: FILE_ENV: "./ci/test/00_setup_env_native_fuzz.sh" task: - name: 'x86_64 Linux [GOAL: install] [focal] [no depends, only system libs, fuzzers under valgrind]' - << : *GLOBAL_TASK_TEMPLATE - container: - image: ubuntu:focal - env: - FILE_ENV: "./ci/test/00_setup_env_native_fuzz_with_valgrind.sh" - -task: name: 'x86_64 Linux [GOAL: install] [focal] [multiprocess]' << : *GLOBAL_TASK_TEMPLATE container: diff --git a/.python-version b/.python-version index c49282585a..8b7b0b52e5 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.5.6 +3.6.12 diff --git a/.travis.yml b/.travis.yml index 656eed9871..780bc9944f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,7 @@ jobs: env: cache: pip language: python - python: '3.5' # Oldest supported version according to doc/dependencies.md + python: '3.6' # Oldest supported version according to doc/dependencies.md install: - set -o errexit; source ./ci/lint/04_install.sh before_script: @@ -66,11 +66,11 @@ jobs: - set -o errexit; source ./ci/lint/06_script.sh - stage: test - name: '32-bit + dash [GOAL: install] [CentOS 7] [gui]' + name: '32-bit + dash [GOAL: install] [CentOS 8] [gui]' env: >- FILE_ENV="./ci/test/00_setup_env_i686_centos.sh" - stage: test - name: 'x86_64 Linux [GOAL: install] [xenial] [no wallet]' + name: 'x86_64 Linux [GOAL: install] [bionic] [no wallet]' env: >- FILE_ENV="./ci/test/00_setup_env_native_nowallet.sh" diff --git a/build_msvc/bitcoin_config.h b/build_msvc/bitcoin_config.h index 9d0b50a0b4..c1433d4852 100644 --- a/build_msvc/bitcoin_config.h +++ b/build_msvc/bitcoin_config.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 0 /* Minor version */ -#define CLIENT_VERSION_MINOR 20 +#define CLIENT_VERSION_MINOR 21 /* Build revision */ #define CLIENT_VERSION_REVISION 99 @@ -253,7 +253,7 @@ #define PACKAGE_NAME "Bitcoin Core" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "Bitcoin Core 0.19.99" +#define PACKAGE_STRING "Bitcoin Core 0.21.99" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "bitcoin" @@ -262,7 +262,7 @@ #define PACKAGE_URL "https://bitcoincore.org/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "0.19.99" +#define PACKAGE_VERSION "0.21.99" /* Define to necessary symbol if this constant uses a non-standard name on your system. */ diff --git a/ci/test/00_setup_env_i686_centos.sh b/ci/test/00_setup_env_i686_centos.sh index e58003ab19..52cdb75a0c 100644 --- a/ci/test/00_setup_env_i686_centos.sh +++ b/ci/test/00_setup_env_i686_centos.sh @@ -7,9 +7,10 @@ export LC_ALL=C.UTF-8 export HOST=i686-pc-linux-gnu -export CONTAINER_NAME=ci_i686_centos_7 -export DOCKER_NAME_TAG=centos:7 -export DOCKER_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache libtool make git python3 python36-zmq which patch lbzip2 dash" +export CONTAINER_NAME=ci_i686_centos_8 +export DOCKER_NAME_TAG=centos:8 +export DOCKER_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache libtool make git python3 python3-zmq which patch lbzip2 dash rsync coreutils" export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-reduce-exports --with-boost-process" +export DEP_OPTS="NO_QT=1" # Gui disabled for now to avoid build failures +export BITCOIN_CONFIG="--enable-zmq --with-gui=no --enable-reduce-exports --with-boost-process" export CONFIG_SHELL="/bin/dash" diff --git a/ci/test/00_setup_env_native_nowallet.sh b/ci/test/00_setup_env_native_nowallet.sh index 0a09bfe230..7ff044c020 100644 --- a/ci/test/00_setup_env_native_nowallet.sh +++ b/ci/test/00_setup_env_native_nowallet.sh @@ -7,8 +7,8 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_nowallet -export DOCKER_NAME_TAG=ubuntu:16.04 # Use xenial to have one config run the tests in python3.5, see doc/dependencies.md -export PACKAGES="python3-zmq clang-3.8 llvm-3.8" # Use clang-3.8 to test C++11 compatibility, see doc/dependencies.md +export DOCKER_NAME_TAG=ubuntu:18.04 # Use bionic to have one config run the tests in python3.6, see doc/dependencies.md +export PACKAGES="python3-zmq clang-5.0 llvm-5.0" # Use clang-5 to test C++17 compatibility, see doc/dependencies.md export DEP_OPTS="NO_WALLET=1" export GOAL="install" -export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-3.8 CXX=clang++-3.8 --with-boost-process" +export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-5.0 CXX=clang++-5.0 --with-boost-process" diff --git a/ci/test/00_setup_env_native_qt5.sh b/ci/test/00_setup_env_native_qt5.sh index 8668662299..dc6b2aecb5 100644 --- a/ci/test/00_setup_env_native_qt5.sh +++ b/ci/test/00_setup_env_native_qt5.sh @@ -7,7 +7,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_qt5 -export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can compile our c++17 and run our functional tests in python3 +export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic gcc-7 can compile our c++17 and run our functional tests in python3, see doc/dependencies.md export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libdbus-1-dev libharfbuzz-dev" export DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1" export TEST_RUNNER_EXTRA="--previous-releases --coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash @@ -16,4 +16,4 @@ export RUN_UNIT_TESTS_SEQUENTIAL="true" export RUN_UNIT_TESTS="false" export GOAL="install" export PREVIOUS_RELEASES_TO_DOWNLOAD="v0.15.2 v0.16.3 v0.17.2 v0.18.1 v0.19.1" -export BITCOIN_CONFIG="--enable-zmq --with-libs=no --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-c++17 --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\" --with-boost-process" +export BITCOIN_CONFIG="--enable-zmq --with-libs=no --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\" --with-boost-process" diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index db74fe6569..cce0c7e49e 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -60,8 +60,8 @@ if [ -n "$DPKG_ADD_ARCH" ]; then fi if [[ $DOCKER_NAME_TAG == centos* ]]; then - ${CI_RETRY_EXE} DOCKER_EXEC yum -y install epel-release - ${CI_RETRY_EXE} DOCKER_EXEC yum -y install $DOCKER_PACKAGES $PACKAGES + ${CI_RETRY_EXE} DOCKER_EXEC dnf -y install epel-release + ${CI_RETRY_EXE} DOCKER_EXEC dnf -y --allowerasing install $DOCKER_PACKAGES $PACKAGES elif [ "$CI_USE_APT_INSTALL" != "no" ]; then ${CI_RETRY_EXE} DOCKER_EXEC apt-get update ${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES diff --git a/configure.ac b/configure.ac index 9a16b7c880..e1548e5c36 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 0) -define(_CLIENT_VERSION_MINOR, 20) +define(_CLIENT_VERSION_MINOR, 21) define(_CLIENT_VERSION_REVISION, 99) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_RC, 0) @@ -68,18 +68,8 @@ case $host in ;; esac -AC_ARG_ENABLE([c++17], - [AS_HELP_STRING([--enable-c++17], - [enable compilation in c++17 mode (disabled by default)])], - [use_cxx17=$enableval], - [use_cxx17=no]) - -dnl Require C++11 or C++17 compiler (no GNU extensions) -if test "x$use_cxx17" = xyes -o "x$enable_fuzz" = xyes ; then - AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory]) -else - AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory]) -fi +dnl Require C++17 compiler (no GNU extensions) +AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory]) dnl Check if -latomic is required for <std::atomic> CHECK_ATOMIC @@ -107,8 +97,8 @@ AC_PATH_TOOL(STRIP, strip) AC_PATH_TOOL(GCOV, gcov) AC_PATH_TOOL(LLVM_COV, llvm-cov) AC_PATH_PROG(LCOV, lcov) -dnl Python 3.5 is specified in .python-version and should be used if available, see doc/dependencies.md -AC_PATH_PROGS([PYTHON], [python3.5 python3.6 python3.7 python3.8 python3 python]) +dnl Python 3.6 is specified in .python-version and should be used if available, see doc/dependencies.md +AC_PATH_PROGS([PYTHON], [python3.6 python3.7 python3.8 python3.9 python3 python]) AC_PATH_PROG(GENHTML, genhtml) AC_PATH_PROG([GIT], [git]) AC_PATH_PROG(CCACHE,ccache) diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index dc74de9198..02615edb54 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -62,7 +62,7 @@ def get_ELF_program_headers(executable): splitline = [x.strip() for x in line.split()] flags = splitline[ofs_flags] # check for 'R', ' E' - if splitline[ofs_flags + 1] is 'E': + if splitline[ofs_flags + 1] == 'E': flags += ' E' headers.append((typ, flags, [])) count += 1 diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index ec716cf2f3..f873742a6d 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-linux-0.21" +name: "bitcoin-core-linux-0.22" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index df50f45188..0479a49514 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-osx-0.21" +name: "bitcoin-core-osx-0.22" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 4d61cded74..7900c7e07e 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-win-0.21" +name: "bitcoin-core-win-0.22" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/macdeploy/custom_dsstore.py b/contrib/macdeploy/custom_dsstore.py index dc1c1882dd..7ab42ea5d4 100755 --- a/contrib/macdeploy/custom_dsstore.py +++ b/contrib/macdeploy/custom_dsstore.py @@ -2,7 +2,6 @@ # Copyright (c) 2013-2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -import biplist from ds_store import DSStore from mac_alias import Alias import sys @@ -47,7 +46,7 @@ alias.volume.disk_image_alias.target.filename = package_name_ns + '.temp.dmg' alias.volume.disk_image_alias.target.carbon_path = 'Macintosh HD:Users:\x00bitcoinuser:\x00Documents:\x00bitcoin:\x00bitcoin:\x00' + package_name_ns + '.temp.dmg' alias.volume.disk_image_alias.target.posix_path = 'Users/bitcoinuser/Documents/bitcoin/bitcoin/' + package_name_ns + '.temp.dmg' alias.target.carbon_path = package_name_ns + ':.background:\x00background.tiff' -icvp['backgroundImageAlias'] = biplist.Data(alias.to_bytes()) +icvp['backgroundImageAlias'] = alias.to_bytes() ds['.']['icvp'] = icvp ds['.']['vSrn'] = ('long', 1) diff --git a/contrib/seeds/README.md b/contrib/seeds/README.md index 502c20d0d6..3bca094d3b 100644 --- a/contrib/seeds/README.md +++ b/contrib/seeds/README.md @@ -16,6 +16,12 @@ The seeds compiled into the release are created from sipa's DNS seed data, like ## Dependencies -Ubuntu: +Ubuntu, Debian: sudo apt-get install python3-dnspython + +and/or for other operating systems: + + pip install dnspython + +See https://dnspython.readthedocs.io/en/latest/installation.html for more information. diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index 6d9d49ad2f..9be6a690a6 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -136,7 +136,7 @@ def lookup_asn(net, ip): ipaddr = res.rstrip('.') # 2.0.0.1.4.8.6.0.b.0.0.2.0.0.2.3 prefix = '.origin6' - asn = int([x.to_text() for x in dns.resolver.query('.'.join( + asn = int([x.to_text() for x in dns.resolver.resolve('.'.join( reversed(ipaddr.split('.'))) + prefix + '.asn.cymru.com', 'TXT').response.answer][0].split('\"')[1].split(' ')[0]) return asn diff --git a/contrib/signet/README.md b/contrib/signet/README.md new file mode 100644 index 0000000000..c4aa5ae2f7 --- /dev/null +++ b/contrib/signet/README.md @@ -0,0 +1,19 @@ +Contents +======== +This directory contains tools related to Signet, both for running a Signet yourself and for using one. + +getcoins.py +=========== + +A script to call a faucet to get Signet coins. + +Syntax: `getcoins.py [-h|--help] [-c|--cmd=<bitcoin-cli path>] [-f|--faucet=<faucet URL>] [-a|--addr=<signet bech32 address>] [-p|--password=<faucet password>] [--] [<bitcoin-cli args>]` + +* `--cmd` lets you customize the bitcoin-cli path. By default it will look for it in the PATH +* `--faucet` lets you specify which faucet to use; the faucet is assumed to be compatible with https://github.com/kallewoof/bitcoin-faucet +* `--addr` lets you specify a Signet address; by default, the address must be a bech32 address. This and `--cmd` above complement each other (i.e. you do not need `bitcoin-cli` if you use `--addr`) +* `--password` lets you specify a faucet password; this is handy if you are in a classroom and set up your own faucet for your students; (above faucet does not limit by IP when password is enabled) + +If using the default network, invoking the script with no arguments should be sufficient under normal +circumstances, but if multiple people are behind the same IP address, the faucet will by default only +accept one claim per day. See `--password` above. diff --git a/contrib/signet/getcoins.py b/contrib/signet/getcoins.py new file mode 100755 index 0000000000..691f0bb1b6 --- /dev/null +++ b/contrib/signet/getcoins.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# Copyright (c) 2020 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import argparse +import subprocess +import requests +import sys + +parser = argparse.ArgumentParser(description='Script to get coins from a faucet.', epilog='You may need to start with double-dash (--) when providing bitcoin-cli arguments.') +parser.add_argument('-c', '--cmd', dest='cmd', default='bitcoin-cli', help='bitcoin-cli command to use') +parser.add_argument('-f', '--faucet', dest='faucet', default='https://signetfaucet.com/claim', help='URL of the faucet') +parser.add_argument('-a', '--addr', dest='addr', default='', help='Bitcoin address to which the faucet should send') +parser.add_argument('-p', '--password', dest='password', default='', help='Faucet password, if any') +parser.add_argument('bitcoin_cli_args', nargs='*', help='Arguments to pass on to bitcoin-cli (default: -signet)') + +args = parser.parse_args() + +if args.addr == '': + if args.bitcoin_cli_args == []: + args.bitcoin_cli_args = ['-signet'] + # get address for receiving coins + try: + args.addr = subprocess.check_output([args.cmd] + args.bitcoin_cli_args + ['getnewaddress', 'faucet', 'bech32']).strip() + except FileNotFoundError: + print('The binary', args.cmd, 'could not be found.') + exit() + +data = {'address': args.addr, 'password': args.password} +try: + res = requests.post(args.faucet, data=data) +except: + print('Unexpected error when contacting faucet:', sys.exc_info()[0]) + exit() +print(res.text) diff --git a/depends/config.site.in b/depends/config.site.in index 87a3379303..f4531830c8 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -1,4 +1,14 @@ -depends_prefix="`dirname ${ac_site_file}`/.." +# shellcheck shell=sh disable=SC2034 # Many variables set will be used in + # ./configure but shellcheck doesn't know + # that, hence: disable=SC2034 + +true # Dummy command because shellcheck treats all directives before first + # command as file-wide, and we only want to disable for one line. + # + # See: https://github.com/koalaman/shellcheck/wiki/Directive + +# shellcheck disable=SC2154 +depends_prefix="$(cd "$(dirname ${ac_site_file})/.." && pwd)" cross_compiling=maybe host_alias=@HOST@ @@ -50,7 +60,7 @@ if test x@host_os@ = xdarwin; then fi PATH=$depends_prefix/native/bin:$PATH -PKG_CONFIG="`which pkg-config` --static" +PKG_CONFIG="$(which pkg-config) --static" # These two need to remain exported because pkg-config does not see them # otherwise. That means they must be unexported at the end of configure.ac to @@ -69,7 +79,7 @@ fi if test -n "@CXX@" -a -z "${CXX}"; then CXX="@CXX@" fi -PYTHONPATH=$depends_prefix/native/lib/python3/dist-packages:$PYTHONPATH +PYTHONPATH="${depends_prefix}/native/lib/python3/dist-packages${PYTHONPATH:+${PATH_SEPARATOR}}${PYTHONPATH}" if test -n "@AR@"; then AR=@AR@ diff --git a/depends/packages/native_biplist.mk b/depends/packages/native_biplist.mk deleted file mode 100644 index c3054cbd1a..0000000000 --- a/depends/packages/native_biplist.mk +++ /dev/null @@ -1,15 +0,0 @@ -package=native_biplist -$(package)_version=1.0.3 -$(package)_download_path=https://bitbucket.org/wooster/biplist/downloads -$(package)_file_name=biplist-$($(package)_version).tar.gz -$(package)_sha256_hash=4c0549764c5fe50b28042ec21aa2e14fe1a2224e239a1dae77d9e7f3932aa4c6 -$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages - -define $(package)_build_cmds - python3 setup.py build -endef - -define $(package)_stage_cmds - mkdir -p $($(package)_install_libdir) && \ - python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir) -endef diff --git a/depends/packages/native_ds_store.mk b/depends/packages/native_ds_store.mk index f99b689ecd..44108925a4 100644 --- a/depends/packages/native_ds_store.mk +++ b/depends/packages/native_ds_store.mk @@ -1,10 +1,9 @@ package=native_ds_store -$(package)_version=1.1.2 +$(package)_version=1.3.0 $(package)_download_path=https://github.com/al45tair/ds_store/archive/ $(package)_file_name=v$($(package)_version).tar.gz -$(package)_sha256_hash=3b3ecb7bf0a5157f5b6010bc3af7c141fb0ad3527084e63336220d22744bc20c +$(package)_sha256_hash=76b3280cd4e19e5179defa23fb594a9dd32643b0c80d774bd3108361d94fb46d $(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages -$(package)_dependencies=native_biplist define $(package)_build_cmds python3 setup.py build diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 4627acb521..ca06b6dd7e 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -20,7 +20,7 @@ upnp_packages=miniupnpc multiprocess_packages = libmultiprocess capnp multiprocess_native_packages = native_libmultiprocess native_capnp -darwin_native_packages = native_biplist native_ds_store native_mac_alias +darwin_native_packages = native_ds_store native_mac_alias ifneq ($(build_os),darwin) darwin_native_packages += native_cctools native_cdrkit native_libdmg-hfsplus diff --git a/doc/dependencies.md b/doc/dependencies.md index d1bf4b3a87..6a743caba2 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -7,18 +7,18 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct | --- | --- | --- | --- | --- | --- | | Berkeley DB | [4.8.30](https://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html) | 4.8.x | No | | | | Boost | [1.70.0](https://www.boost.org/users/download/) | [1.58.0](https://github.com/bitcoin/bitcoin/pull/19667) | No | | | -| Clang | | [3.3+](https://releases.llvm.org/download.html) (C++11 support) | | | | +| Clang | | [5.0+](https://releases.llvm.org/download.html) (C++17 support) | | | | | Expat | [2.2.7](https://libexpat.github.io/) | | No | Yes | | | fontconfig | [2.12.1](https://www.freedesktop.org/software/fontconfig/release/) | | No | Yes | | | FreeType | [2.7.1](https://download.savannah.gnu.org/releases/freetype) | | No | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) (Android only) | -| GCC | | [4.8+](https://gcc.gnu.org/) (C++11 support) | | | | +| GCC | | [7+](https://gcc.gnu.org/) (C++17 support) | | | | | HarfBuzz-NG | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | | libevent | [2.1.11-stable](https://github.com/libevent/libevent/releases) | [2.0.21](https://github.com/bitcoin/bitcoin/pull/18676) | No | | | | libpng | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | | librsvg | | | | | | | MiniUPnPc | [2.0.20180203](https://miniupnp.tuxfamily.org/files) | | No | | | | PCRE | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | -| Python (tests) | | [3.5](https://www.python.org/downloads) | | | | +| Python (tests) | | [3.6](https://www.python.org/downloads) | | | | | qrencode | [3.4.4](https://fukuchi.org/works/qrencode) | | No | | | | Qt | [5.9.8](https://download.qt.io/official_releases/qt/) | [5.5.1](https://github.com/bitcoin/bitcoin/issues/13478) | No | | | | SQLite | [3.32.1](https://sqlite.org/download.html) | [3.7.17](https://github.com/bitcoin/bitcoin/pull/19077) | | | | diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1 index 129651d8e9..588ae81fce 100644 --- a/doc/man/bitcoin-cli.1 +++ b/doc/man/bitcoin-cli.1 @@ -1,115 +1,5 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH BITCOIN-CLI "1" "February 2019" "bitcoin-cli v0.17.99.0" "User Commands" +.TH BITCOIN-CLI "1" .SH NAME -bitcoin-cli \- manual page for bitcoin-cli v0.17.99.0 -.SH SYNOPSIS -.B bitcoin-cli -[\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR] \fI\,Send command to Bitcoin Core\/\fR -.br -.B bitcoin-cli -[\fI\,options\/\fR] \fI\,-named <command> \/\fR[\fI\,name=value\/\fR]... \fI\,Send command to Bitcoin Core (with named arguments)\/\fR -.br -.B bitcoin-cli -[\fI\,options\/\fR] \fI\,help List commands\/\fR -.br -.B bitcoin-cli -[\fI\,options\/\fR] \fI\,help <command> Get help for a command\/\fR -.SH DESCRIPTION -Bitcoin Core RPC client version v0.17.99.0 -.SH OPTIONS -.HP -\-? -.IP -Print this help message and exit -.HP -\fB\-conf=\fR<file> -.IP -Specify configuration file. Relative paths will be prefixed by datadir -location. (default: bitcoin.conf) -.HP -\fB\-datadir=\fR<dir> -.IP -Specify data directory -.HP -\fB\-getinfo\fR -.IP -Get general information from the remote server. Note that unlike -server\-side RPC calls, the results of \fB\-getinfo\fR is the result of -multiple non\-atomic requests. Some entries in the result may -represent results from different states (e.g. wallet balance may -be as of a different block from the chain state reported) -.HP -\fB\-named\fR -.IP -Pass named instead of positional arguments (default: false) -.HP -\fB\-rpcclienttimeout=\fR<n> -.IP -Timeout in seconds during HTTP requests, or 0 for no timeout. (default: -900) -.HP -\fB\-rpcconnect=\fR<ip> -.IP -Send commands to node running on <ip> (default: 127.0.0.1) -.HP -\fB\-rpccookiefile=\fR<loc> -.IP -Location of the auth cookie. Relative paths will be prefixed by a -net\-specific datadir location. (default: data dir) -.HP -\fB\-rpcpassword=\fR<pw> -.IP -Password for JSON\-RPC connections -.HP -\fB\-rpcport=\fR<port> -.IP -Connect to JSON\-RPC on <port> (default: 8332, testnet: 18332, regtest: -18443) -.HP -\fB\-rpcuser=\fR<user> -.IP -Username for JSON\-RPC connections -.HP -\fB\-rpcwait\fR -.IP -Wait for RPC server to start -.HP -\fB\-rpcwallet=\fR<walletname> -.IP -Send RPC for non\-default wallet on RPC server (needs to exactly match -corresponding \fB\-wallet\fR option passed to bitcoind). This changes -the RPC endpoint used, e.g. -http://127.0.0.1:8332/wallet/<walletname> -.HP -\fB\-stdin\fR -.IP -Read extra arguments from standard input, one per line until EOF/Ctrl\-D -(recommended for sensitive information such as passphrases). When -combined with \fB\-stdinrpcpass\fR, the first line from standard input -is used for the RPC password. -.HP -\fB\-stdinrpcpass\fR -.IP -Read RPC password from standard input as a single line. When combined -with \fB\-stdin\fR, the first line from standard input is used for the -RPC password. -.HP -\fB\-version\fR -.IP -Print version and exit -.PP -Chain selection options: -.HP -\fB\-testnet\fR -.IP -Use the test chain -.SH COPYRIGHT -Copyright (C) 2009-2019 The Bitcoin Core developers +bitcoin-cli \- manual page for bitcoin-cli -Please contribute if you find Bitcoin Core useful. Visit -<https://bitcoincore.org> for further information about the software. -The source code is available from <https://github.com/bitcoin/bitcoin>. - -This is experimental software. -Distributed under the MIT software license, see the accompanying file COPYING -or <https://opensource.org/licenses/MIT> +This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release. diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1 index f68be21e8d..9c75e9fe54 100644 --- a/doc/man/bitcoin-qt.1 +++ b/doc/man/bitcoin-qt.1 @@ -1,610 +1,5 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH BITCOIN-QT "1" "February 2019" "bitcoin-qt v0.17.99.0" "User Commands" +.TH BITCOIN-QT "1" .SH NAME -bitcoin-qt \- manual page for bitcoin-qt v0.17.99.0 -.SH SYNOPSIS -.B bitcoin-qt -[\fI\,command-line options\/\fR] -.SH DESCRIPTION -Bitcoin Core version v0.17.99.0 (64\-bit) -.SH OPTIONS -.HP -\-? -.IP -Print this help message and exit -.HP -\fB\-alertnotify=\fR<cmd> -.IP -Execute command when a relevant alert is received or we see a really -long fork (%s in cmd is replaced by message) -.HP -\fB\-assumevalid=\fR<hex> -.IP -If this block is in the chain assume that it and its ancestors are valid -and potentially skip their script verification (0 to verify all, -default: -0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8, -testnet: -0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75) -.HP -\fB\-blocknotify=\fR<cmd> -.IP -Execute command when the best block changes (%s in cmd is replaced by -block hash) -.HP -\fB\-blockreconstructionextratxn=\fR<n> -.IP -Extra transactions to keep in memory for compact block reconstructions -(default: 100) -.HP -\fB\-blocksdir=\fR<dir> -.IP -Specify blocks directory (default: <datadir>/blocks) -.HP -\fB\-conf=\fR<file> -.IP -Specify configuration file. Relative paths will be prefixed by datadir -location. (default: bitcoin.conf) -.HP -\fB\-daemon\fR -.IP -Run in the background as a daemon and accept commands -.HP -\fB\-datadir=\fR<dir> -.IP -Specify data directory -.HP -\fB\-dbcache=\fR<n> -.IP -Set database cache size in MiB (4 to 16384, default: 450) -.HP -\fB\-debuglogfile=\fR<file> -.IP -Specify location of debug log file. Relative paths will be prefixed by a -net\-specific datadir location. (\fB\-nodebuglogfile\fR to disable; -default: debug.log) -.HP -\fB\-includeconf=\fR<file> -.IP -Specify additional configuration file, relative to the \fB\-datadir\fR path -(only useable from configuration file, not command line) -.HP -\fB\-loadblock=\fR<file> -.IP -Imports blocks from external blk000??.dat file on startup -.HP -\fB\-maxmempool=\fR<n> -.IP -Keep the transaction memory pool below <n> megabytes (default: 300) -.HP -\fB\-maxorphantx=\fR<n> -.IP -Keep at most <n> unconnectable transactions in memory (default: 100) -.HP -\fB\-mempoolexpiry=\fR<n> -.IP -Do not keep transactions in the mempool longer than <n> hours (default: -336) -.HP -\fB\-par=\fR<n> -.IP -Set the number of script verification threads (\fB\-8\fR to 16, 0 = auto, <0 = -leave that many cores free, default: 0) -.HP -\fB\-persistmempool\fR -.IP -Whether to save the mempool on shutdown and load on restart (default: 1) -.HP -\fB\-pid=\fR<file> -.IP -Specify pid file. Relative paths will be prefixed by a net\-specific -datadir location. (default: bitcoind.pid) -.HP -\fB\-prune=\fR<n> -.IP -Reduce storage requirements by enabling pruning (deleting) of old -blocks. This allows the pruneblockchain RPC to be called to -delete specific blocks, and enables automatic pruning of old -blocks if a target size in MiB is provided. This mode is -incompatible with \fB\-txindex\fR and \fB\-rescan\fR. Warning: Reverting this -setting requires re\-downloading the entire blockchain. (default: -0 = disable pruning blocks, 1 = allow manual pruning via RPC, ->=550 = automatically prune block files to stay under the -specified target size in MiB) -.HP -\fB\-reindex\fR -.IP -Rebuild chain state and block index from the blk*.dat files on disk -.HP -\fB\-reindex\-chainstate\fR -.IP -Rebuild chain state from the currently indexed blocks. When in pruning -mode or if blocks on disk might be corrupted, use full \fB\-reindex\fR -instead. -.HP -\fB\-sysperms\fR -.IP -Create new files with system default permissions, instead of umask 077 -(only effective with disabled wallet functionality) -.HP -\fB\-txindex\fR -.IP -Maintain a full transaction index, used by the getrawtransaction rpc -call (default: 0) -.HP -\fB\-version\fR -.IP -Print version and exit -.PP -Connection options: -.HP -\fB\-addnode=\fR<ip> -.IP -Add a node to connect to and attempt to keep the connection open (see -the `addnode` RPC command help for more info). This option can be -specified multiple times to add multiple nodes. -.HP -\fB\-banscore=\fR<n> -.IP -Threshold for disconnecting misbehaving peers (default: 100) -.HP -\fB\-bantime=\fR<n> -.IP -Number of seconds to keep misbehaving peers from reconnecting (default: -86400) -.HP -\fB\-bind=\fR<addr> -.IP -Bind to given address and always listen on it. Use [host]:port notation -for IPv6 -.HP -\fB\-connect=\fR<ip> -.IP -Connect only to the specified node; \fB\-noconnect\fR disables automatic -connections (the rules for this peer are the same as for -\fB\-addnode\fR). This option can be specified multiple times to connect -to multiple nodes. -.HP -\fB\-discover\fR -.IP -Discover own IP addresses (default: 1 when listening and no \fB\-externalip\fR -or \fB\-proxy\fR) -.HP -\fB\-dns\fR -.IP -Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (default: 1) -.HP -\fB\-dnsseed\fR -.IP -Query for peer addresses via DNS lookup, if low on addresses (default: 1 -unless \fB\-connect\fR used) -.HP -\fB\-externalip=\fR<ip> -.IP -Specify your own public address -.HP -\fB\-forcednsseed\fR -.IP -Always query for peer addresses via DNS lookup (default: 0) -.HP -\fB\-listen\fR -.IP -Accept connections from outside (default: 1 if no \fB\-proxy\fR or \fB\-connect\fR) -.HP -\fB\-listenonion\fR -.IP -Automatically create Tor hidden service (default: 1) -.HP -\fB\-maxconnections=\fR<n> -.IP -Maintain at most <n> connections to peers (default: 125) -.HP -\fB\-maxreceivebuffer=\fR<n> -.IP -Maximum per\-connection receive buffer, <n>*1000 bytes (default: 5000) -.HP -\fB\-maxsendbuffer=\fR<n> -.IP -Maximum per\-connection send buffer, <n>*1000 bytes (default: 1000) -.HP -\fB\-maxtimeadjustment\fR -.IP -Maximum allowed median peer time offset adjustment. Local perspective of -time may be influenced by peers forward or backward by this -amount. (default: 4200 seconds) -.HP -\fB\-maxuploadtarget=\fR<n> -.IP -Tries to keep outbound traffic under the given target (in MiB per 24h), -0 = no limit (default: 0) -.HP -\fB\-onion=\fR<ip:port> -.IP -Use separate SOCKS5 proxy to reach peers via Tor hidden services, set -\fB\-noonion\fR to disable (default: \fB\-proxy\fR) -.HP -\fB\-onlynet=\fR<net> -.IP -Make outgoing connections only through network <net> (ipv4, ipv6 or -onion). Incoming connections are not affected by this option. -This option can be specified multiple times to allow multiple -networks. -.HP -\fB\-peerbloomfilters\fR -.IP -Support filtering of blocks and transaction with bloom filters (default: -1) -.HP -\fB\-permitbaremultisig\fR -.IP -Relay non\-P2SH multisig (default: 1) -.HP -\fB\-port=\fR<port> -.IP -Listen for connections on <port> (default: 8333, testnet: 18333, -regtest: 18444) -.HP -\fB\-proxy=\fR<ip:port> -.IP -Connect through SOCKS5 proxy, set \fB\-noproxy\fR to disable (default: -disabled) -.HP -\fB\-proxyrandomize\fR -.IP -Randomize credentials for every proxy connection. This enables Tor -stream isolation (default: 1) -.HP -\fB\-seednode=\fR<ip> -.IP -Connect to a node to retrieve peer addresses, and disconnect. This -option can be specified multiple times to connect to multiple -nodes. -.HP -\fB\-timeout=\fR<n> -.IP -Specify connection timeout in milliseconds (minimum: 1, default: 5000) -.HP -\fB\-torcontrol=\fR<ip>:<port> -.IP -Tor control port to use if onion listening enabled (default: -127.0.0.1:9051) -.HP -\fB\-torpassword=\fR<pass> -.IP -Tor control port password (default: empty) -.HP -\fB\-upnp\fR -.IP -Use UPnP to map the listening port (default: 0) -.HP -\fB\-whitebind=\fR<addr> -.IP -Bind to given address and whitelist peers connecting to it. Use -[host]:port notation for IPv6 -.HP -\fB\-whitelist=\fR<IP address or network> -.IP -Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or -CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple -times. Whitelisted peers cannot be DoS banned and their -transactions are always relayed, even if they are already in the -mempool, useful e.g. for a gateway -.PP -Wallet options: -.HP -\fB\-addresstype\fR -.IP -What type of addresses to use ("legacy", "p2sh\-segwit", or "bech32", -default: "p2sh\-segwit") -.HP -\fB\-avoidpartialspends\fR -.IP -Group outputs by address, selecting all or none, instead of selecting on -a per\-output basis. Privacy is improved as an address is only -used once (unless someone sends to it after spending from it), -but may result in slightly higher fees as suboptimal coin -selection may result due to the added limitation (default: 0) -.HP -\fB\-changetype\fR -.IP -What type of change to use ("legacy", "p2sh\-segwit", or "bech32"). -Default is same as \fB\-addresstype\fR, except when -\fB\-addresstype\fR=\fI\,p2sh\-segwit\/\fR a native segwit output is used when -sending to a native segwit address) -.HP -\fB\-disablewallet\fR -.IP -Do not load the wallet and disable wallet RPC calls -.HP -\fB\-discardfee=\fR<amt> -.IP -The fee rate (in BTC/kB) that indicates your tolerance for discarding -change by adding it to the fee (default: 0.0001). Note: An output -is discarded if it is dust at this rate, but we will always -discard up to the dust relay fee and a discard fee above that is -limited by the fee estimate for the longest target -.HP -\fB\-fallbackfee=\fR<amt> -.IP -A fee rate (in BTC/kB) that will be used when fee estimation has -insufficient data (default: 0.0002) -.HP -\fB\-keypool=\fR<n> -.IP -Set key pool size to <n> (default: 1000) -.HP -\fB\-mintxfee=\fR<amt> -.IP -Fees (in BTC/kB) smaller than this are considered zero fee for -transaction creation (default: 0.00001) -.HP -\fB\-paytxfee=\fR<amt> -.IP -Fee (in BTC/kB) to add to transactions you send (default: 0.00) -.HP -\fB\-rescan\fR -.IP -Rescan the block chain for missing wallet transactions on startup -.HP -\fB\-salvagewallet\fR -.IP -Attempt to recover private keys from a corrupt wallet on startup -.HP -\fB\-spendzeroconfchange\fR -.IP -Spend unconfirmed change when sending transactions (default: 1) -.HP -\fB\-txconfirmtarget=\fR<n> -.IP -If paytxfee is not set, include enough fee so transactions begin -confirmation on average within n blocks (default: 6) -.HP -\fB\-upgradewallet\fR -.IP -Upgrade wallet to latest format on startup -.HP -\fB\-wallet=\fR<path> -.IP -Specify wallet database path. Can be specified multiple times to load -multiple wallets. Path is interpreted relative to <walletdir> if -it is not absolute, and will be created if it does not exist (as -a directory containing a wallet.dat file and log files). For -backwards compatibility this will also accept names of existing -data files in <walletdir>.) -.HP -\fB\-walletbroadcast\fR -.IP -Make the wallet broadcast transactions (default: 1) -.HP -\fB\-walletdir=\fR<dir> -.IP -Specify directory to hold wallets (default: <datadir>/wallets if it -exists, otherwise <datadir>) -.HP -\fB\-walletnotify=\fR<cmd> -.IP -Execute command when a wallet transaction changes (%s in cmd is replaced -by TxID) -.HP -\fB\-walletrbf\fR -.IP -Send transactions with full\-RBF opt\-in enabled (RPC only, default: 0) -.HP -\fB\-zapwallettxes=\fR<mode> -.IP -Delete all wallet transactions and only recover those parts of the -blockchain through \fB\-rescan\fR on startup (1 = keep tx meta data e.g. -payment request information, 2 = drop tx meta data) -.PP -ZeroMQ notification options: -.HP -\fB\-zmqpubhashblock=\fR<address> -.IP -Enable publish hash block in <address> -.HP -\fB\-zmqpubhashtx=\fR<address> -.IP -Enable publish hash transaction in <address> -.HP -\fB\-zmqpubrawblock=\fR<address> -.IP -Enable publish raw block in <address> -.HP -\fB\-zmqpubrawtx=\fR<address> -.IP -Enable publish raw transaction in <address> -.PP -Debugging/Testing options: -.HP -\fB\-debug=\fR<category> -.IP -Output debugging information (default: \fB\-nodebug\fR, supplying <category> is -optional). If <category> is not supplied or if <category> = 1, -output all debugging information. <category> can be: net, tor, -mempool, http, bench, zmq, db, rpc, estimatefee, addrman, -selectcoins, reindex, cmpctblock, rand, prune, proxy, mempoolrej, -libevent, coindb, qt, leveldb. -.HP -\fB\-debugexclude=\fR<category> -.IP -Exclude debugging information for a category. Can be used in conjunction -with \fB\-debug\fR=\fI\,1\/\fR to output debug logs for all categories except one -or more specified categories. -.HP -\fB\-help\-debug\fR -.IP -Print help message with debugging options and exit -.HP -\fB\-logips\fR -.IP -Include IP addresses in debug output (default: 0) -.HP -\fB\-logtimestamps\fR -.IP -Prepend debug output with timestamp (default: 1) -.HP -\fB\-maxtxfee=\fR<amt> -.IP -Maximum total fees (in BTC) to use in a single wallet transaction or raw -transaction; setting this too low may abort large transactions -(default: 0.10) -.HP -\fB\-printtoconsole\fR -.IP -Send trace/debug info to console (default: 1 when no \fB\-daemon\fR. To disable -logging to file, set \fB\-nodebuglogfile\fR) -.HP -\fB\-shrinkdebugfile\fR -.IP -Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR) -.HP -\fB\-uacomment=\fR<cmt> -.IP -Append comment to the user agent string -.PP -Chain selection options: -.HP -\fB\-testnet\fR -.IP -Use the test chain -.PP -Node relay options: -.HP -\fB\-bytespersigop\fR -.IP -Equivalent bytes per sigop in transactions for relay and mining -(default: 20) -.HP -\fB\-datacarrier\fR -.IP -Relay and mine data carrier transactions (default: 1) -.HP -\fB\-datacarriersize\fR -.IP -Maximum size of data in data carrier transactions we relay and mine -(default: 83) -.HP -.HP -\fB\-minrelaytxfee=\fR<amt> -.IP -Fees (in BTC/kB) smaller than this are considered zero fee for relaying, -mining and transaction creation (default: 0.00001) -.HP -\fB\-whitelistforcerelay\fR -.IP -Force relay of transactions from whitelisted peers even if they violate -local relay policy (default: 0) -.HP -\fB\-whitelistrelay\fR -.IP -Accept relayed transactions received from whitelisted peers even when -not relaying transactions (default: 1) -.PP -Block creation options: -.HP -\fB\-blockmaxweight=\fR<n> -.IP -Set maximum BIP141 block weight (default: 3996000) -.HP -\fB\-blockmintxfee=\fR<amt> -.IP -Set lowest fee rate (in BTC/kB) for transactions to be included in block -creation. (default: 0.00001) -.PP -RPC server options: -.HP -\fB\-rest\fR -.IP -Accept public REST requests (default: 0) -.HP -\fB\-rpcallowip=\fR<ip> -.IP -Allow JSON\-RPC connections from specified source. Valid for <ip> are a -single IP (e.g. 1.2.3.4), a network/netmask (e.g. -1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This -option can be specified multiple times -.HP -\fB\-rpcauth=\fR<userpw> -.IP -Username and HMAC\-SHA\-256 hashed password for JSON\-RPC connections. The -field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A -canonical python script is included in share/rpcauth. The client -then connects normally using the -rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This -option can be specified multiple times -.HP -\fB\-rpcbind=\fR<addr>[:port] -.IP -Bind to given address to listen for JSON\-RPC connections. Do not expose -the RPC server to untrusted networks such as the public internet! -This option is ignored unless \fB\-rpcallowip\fR is also passed. Port is -optional and overrides \fB\-rpcport\fR. Use [host]:port notation for -IPv6. This option can be specified multiple times (default: -127.0.0.1 and ::1 i.e., localhost) -.HP -\fB\-rpccookiefile=\fR<loc> -.IP -Location of the auth cookie. Relative paths will be prefixed by a -net\-specific datadir location. (default: data dir) -.HP -\fB\-rpcpassword=\fR<pw> -.IP -Password for JSON\-RPC connections -.HP -\fB\-rpcport=\fR<port> -.IP -Listen for JSON\-RPC connections on <port> (default: 8332, testnet: -18332, regtest: 18443) -.HP -\fB\-rpcserialversion\fR -.IP -Sets the serialization of raw transaction or block hex returned in -non\-verbose mode, non\-segwit(0) or segwit(1) (default: 1) -.HP -\fB\-rpcthreads=\fR<n> -.IP -Set the number of threads to service RPC calls (default: 4) -.HP -\fB\-rpcuser=\fR<user> -.IP -Username for JSON\-RPC connections -.HP -\fB\-server\fR -.IP -Accept command line and JSON\-RPC commands -.PP -UI Options: -.HP -\fB\-choosedatadir\fR -.IP -Choose data directory on startup (default: 0) -.HP -\fB\-lang=\fR<lang> -.IP -Set language, for example "de_DE" (default: system locale) -.HP -\fB\-min\fR -.IP -Start minimized -.HP -\fB\-resetguisettings\fR -.IP -Reset all settings changed in the GUI -.HP -\fB\-rootcertificates=\fR<file> -.IP -Set SSL root certificates for payment request (default: \fB\-system\-\fR) -.HP -\fB\-splash\fR -.IP -Show splash screen on startup (default: 1) -.SH COPYRIGHT -Copyright (C) 2009-2019 The Bitcoin Core developers +bitcoin-qt \- manual page for bitcoin-qt -Please contribute if you find Bitcoin Core useful. Visit -<https://bitcoincore.org> for further information about the software. -The source code is available from <https://github.com/bitcoin/bitcoin>. - -This is experimental software. -Distributed under the MIT software license, see the accompanying file COPYING -or <https://opensource.org/licenses/MIT> +This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release. diff --git a/doc/man/bitcoin-tx.1 b/doc/man/bitcoin-tx.1 index b4c7698896..148a5890b0 100644 --- a/doc/man/bitcoin-tx.1 +++ b/doc/man/bitcoin-tx.1 @@ -1,116 +1,5 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH BITCOIN-TX "1" "February 2019" "bitcoin-tx v0.17.99.0" "User Commands" +.TH BITCOIN-TX "1" .SH NAME -bitcoin-tx \- manual page for bitcoin-tx v0.17.99.0 -.SH SYNOPSIS -.B bitcoin-tx -[\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded bitcoin transaction\/\fR -.br -.B bitcoin-tx -[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded bitcoin transaction\/\fR -.SH DESCRIPTION -Bitcoin Core bitcoin\-tx utility version v0.17.99.0 -.SH OPTIONS -.HP -\-? -.IP -Print this help message and exit -.HP -\fB\-create\fR -.IP -Create new, empty TX. -.HP -\fB\-json\fR -.IP -Select JSON output -.HP -\fB\-txid\fR -.IP -Output only the hex\-encoded transaction id of the resultant transaction. -.PP -Chain selection options: -.HP -\fB\-testnet\fR -.IP -Use the test chain -.PP -Commands: -.IP -delin=N -.IP -Delete input N from TX -.IP -delout=N -.IP -Delete output N from TX -.IP -in=TXID:VOUT(:SEQUENCE_NUMBER) -.IP -Add input to TX -.IP -locktime=N -.IP -Set TX lock time to N -.IP -nversion=N -.IP -Set TX version to N -.IP -outaddr=VALUE:ADDRESS -.IP -Add address\-based output to TX -.IP -outdata=[VALUE:]DATA -.IP -Add data\-based output to TX -.IP -outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS] -.IP -Add Pay To n\-of\-m Multi\-sig output to TX. n = REQUIRED, m = PUBKEYS. -Optionally add the "W" flag to produce a -pay\-to\-witness\-script\-hash output. Optionally add the "S" flag to -wrap the output in a pay\-to\-script\-hash. -.IP -outpubkey=VALUE:PUBKEY[:FLAGS] -.IP -Add pay\-to\-pubkey output to TX. Optionally add the "W" flag to produce a -pay\-to\-witness\-pubkey\-hash output. Optionally add the "S" flag to -wrap the output in a pay\-to\-script\-hash. -.IP -outscript=VALUE:SCRIPT[:FLAGS] -.IP -Add raw script output to TX. Optionally add the "W" flag to produce a -pay\-to\-witness\-script\-hash output. Optionally add the "S" flag to -wrap the output in a pay\-to\-script\-hash. -.IP -replaceable(=N) -.IP -Set RBF opt\-in sequence number for input N (if not provided, opt\-in all -available inputs) -.IP -sign=SIGHASH\-FLAGS -.IP -Add zero or more signatures to transaction. This command requires JSON -registers:prevtxs=JSON object, privatekeys=JSON object. See -signrawtransactionwithkey docs for format of sighash flags, JSON -objects. -.PP -Register Commands: -.IP -load=NAME:FILENAME -.IP -Load JSON file FILENAME into register NAME -.IP -set=NAME:JSON\-STRING -.IP -Set register NAME to given JSON\-STRING -.SH COPYRIGHT -Copyright (C) 2009-2019 The Bitcoin Core developers +bitcoin-tx \- manual page for bitcoin-tx -Please contribute if you find Bitcoin Core useful. Visit -<https://bitcoincore.org> for further information about the software. -The source code is available from <https://github.com/bitcoin/bitcoin>. - -This is experimental software. -Distributed under the MIT software license, see the accompanying file COPYING -or <https://opensource.org/licenses/MIT> +This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release. diff --git a/doc/man/bitcoin-wallet.1 b/doc/man/bitcoin-wallet.1 index aadea09a2b..69133b33f7 100644 --- a/doc/man/bitcoin-wallet.1 +++ b/doc/man/bitcoin-wallet.1 @@ -1,63 +1,5 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH BITCOIN-WALLET "1" "February 2019" "bitcoin-wallet v0.17.99.0" "User Commands" +.TH BITCOIN-WALLET "1" .SH NAME -bitcoin-wallet \- manual page for bitcoin-wallet v0.17.99.0 -.SH DESCRIPTION -Bitcoin Core bitcoin\-wallet version v0.17.99.0 -.PP -wallet\-tool is an offline tool for creating and interacting with Bitcoin Core wallet files. -By default wallet\-tool will act on wallets in the default mainnet wallet directory in the datadir. -To change the target wallet, use the \fB\-datadir\fR, \fB\-wallet\fR and \fB\-testnet\fR/\-regtest arguments. -.SS "Usage:" -.IP -bitcoin\-wallet [options] <command> -.SH OPTIONS -.HP -\-? -.IP -Print this help message and exit -.HP -\fB\-datadir=\fR<dir> -.IP -Specify data directory -.HP -\fB\-wallet=\fR<wallet\-name> -.IP -Specify wallet name -.PP -Debugging/Testing options: -.HP -\fB\-debug=\fR<category> -.IP -Output debugging information (default: 0). -.HP -\fB\-printtoconsole\fR -.IP -Send trace/debug info to console (default: 1 when no \fB\-debug\fR is true, 0 -otherwise. -.PP -Chain selection options: -.HP -\fB\-testnet\fR -.IP -Use the test chain -.PP -Commands: -.IP -create -.IP -Create new wallet file -.IP -info -.IP -Get wallet info -.SH COPYRIGHT -Copyright (C) 2009-2019 The Bitcoin Core developers +bitcoin-wallet \- manual page for bitcoin-wallet -Please contribute if you find Bitcoin Core useful. Visit -<https://bitcoincore.org> for further information about the software. -The source code is available from <https://github.com/bitcoin/bitcoin>. - -This is experimental software. -Distributed under the MIT software license, see the accompanying file COPYING -or <https://opensource.org/licenses/MIT> +This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release. diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1 index 211ba10285..de338182ff 100644 --- a/doc/man/bitcoind.1 +++ b/doc/man/bitcoind.1 @@ -1,583 +1,5 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH BITCOIND "1" "February 2019" "bitcoind v0.17.99.0" "User Commands" +.TH BITCOIND "1" .SH NAME -bitcoind \- manual page for bitcoind v0.17.99.0 -.SH SYNOPSIS -.B bitcoind -[\fI\,options\/\fR] \fI\,Start Bitcoin Core Daemon\/\fR -.SH DESCRIPTION -Bitcoin Core Daemon version v0.17.99.0 -.SH OPTIONS -.HP -\-? -.IP -Print this help message and exit -.HP -\fB\-alertnotify=\fR<cmd> -.IP -Execute command when a relevant alert is received or we see a really -long fork (%s in cmd is replaced by message) -.HP -\fB\-assumevalid=\fR<hex> -.IP -If this block is in the chain assume that it and its ancestors are valid -and potentially skip their script verification (0 to verify all, -default: -0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8, -testnet: -0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75) -.HP -\fB\-blocknotify=\fR<cmd> -.IP -Execute command when the best block changes (%s in cmd is replaced by -block hash) -.HP -\fB\-blockreconstructionextratxn=\fR<n> -.IP -Extra transactions to keep in memory for compact block reconstructions -(default: 100) -.HP -\fB\-blocksdir=\fR<dir> -.IP -Specify blocks directory (default: <datadir>/blocks) -.HP -\fB\-conf=\fR<file> -.IP -Specify configuration file. Relative paths will be prefixed by datadir -location. (default: bitcoin.conf) -.HP -\fB\-daemon\fR -.IP -Run in the background as a daemon and accept commands -.HP -\fB\-datadir=\fR<dir> -.IP -Specify data directory -.HP -\fB\-dbcache=\fR<n> -.IP -Set database cache size in MiB (4 to 16384, default: 450) -.HP -\fB\-debuglogfile=\fR<file> -.IP -Specify location of debug log file. Relative paths will be prefixed by a -net\-specific datadir location. (\fB\-nodebuglogfile\fR to disable; -default: debug.log) -.HP -\fB\-includeconf=\fR<file> -.IP -Specify additional configuration file, relative to the \fB\-datadir\fR path -(only useable from configuration file, not command line) -.HP -\fB\-loadblock=\fR<file> -.IP -Imports blocks from external blk000??.dat file on startup -.HP -\fB\-maxmempool=\fR<n> -.IP -Keep the transaction memory pool below <n> megabytes (default: 300) -.HP -\fB\-maxorphantx=\fR<n> -.IP -Keep at most <n> unconnectable transactions in memory (default: 100) -.HP -\fB\-mempoolexpiry=\fR<n> -.IP -Do not keep transactions in the mempool longer than <n> hours (default: -336) -.HP -\fB\-par=\fR<n> -.IP -Set the number of script verification threads (\fB\-8\fR to 16, 0 = auto, <0 = -leave that many cores free, default: 0) -.HP -\fB\-persistmempool\fR -.IP -Whether to save the mempool on shutdown and load on restart (default: 1) -.HP -\fB\-pid=\fR<file> -.IP -Specify pid file. Relative paths will be prefixed by a net\-specific -datadir location. (default: bitcoind.pid) -.HP -\fB\-prune=\fR<n> -.IP -Reduce storage requirements by enabling pruning (deleting) of old -blocks. This allows the pruneblockchain RPC to be called to -delete specific blocks, and enables automatic pruning of old -blocks if a target size in MiB is provided. This mode is -incompatible with \fB\-txindex\fR and \fB\-rescan\fR. Warning: Reverting this -setting requires re\-downloading the entire blockchain. (default: -0 = disable pruning blocks, 1 = allow manual pruning via RPC, ->=550 = automatically prune block files to stay under the -specified target size in MiB) -.HP -\fB\-reindex\fR -.IP -Rebuild chain state and block index from the blk*.dat files on disk -.HP -\fB\-reindex\-chainstate\fR -.IP -Rebuild chain state from the currently indexed blocks. When in pruning -mode or if blocks on disk might be corrupted, use full \fB\-reindex\fR -instead. -.HP -\fB\-sysperms\fR -.IP -Create new files with system default permissions, instead of umask 077 -(only effective with disabled wallet functionality) -.HP -\fB\-txindex\fR -.IP -Maintain a full transaction index, used by the getrawtransaction rpc -call (default: 0) -.HP -\fB\-version\fR -.IP -Print version and exit -.PP -Connection options: -.HP -\fB\-addnode=\fR<ip> -.IP -Add a node to connect to and attempt to keep the connection open (see -the `addnode` RPC command help for more info). This option can be -specified multiple times to add multiple nodes. -.HP -\fB\-banscore=\fR<n> -.IP -Threshold for disconnecting misbehaving peers (default: 100) -.HP -\fB\-bantime=\fR<n> -.IP -Number of seconds to keep misbehaving peers from reconnecting (default: -86400) -.HP -\fB\-bind=\fR<addr> -.IP -Bind to given address and always listen on it. Use [host]:port notation -for IPv6 -.HP -\fB\-connect=\fR<ip> -.IP -Connect only to the specified node; \fB\-noconnect\fR disables automatic -connections (the rules for this peer are the same as for -\fB\-addnode\fR). This option can be specified multiple times to connect -to multiple nodes. -.HP -\fB\-discover\fR -.IP -Discover own IP addresses (default: 1 when listening and no \fB\-externalip\fR -or \fB\-proxy\fR) -.HP -\fB\-dns\fR -.IP -Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (default: 1) -.HP -\fB\-dnsseed\fR -.IP -Query for peer addresses via DNS lookup, if low on addresses (default: 1 -unless \fB\-connect\fR used) -.HP -\fB\-externalip=\fR<ip> -.IP -Specify your own public address -.HP -\fB\-forcednsseed\fR -.IP -Always query for peer addresses via DNS lookup (default: 0) -.HP -\fB\-listen\fR -.IP -Accept connections from outside (default: 1 if no \fB\-proxy\fR or \fB\-connect\fR) -.HP -\fB\-listenonion\fR -.IP -Automatically create Tor hidden service (default: 1) -.HP -\fB\-maxconnections=\fR<n> -.IP -Maintain at most <n> connections to peers (default: 125) -.HP -\fB\-maxreceivebuffer=\fR<n> -.IP -Maximum per\-connection receive buffer, <n>*1000 bytes (default: 5000) -.HP -\fB\-maxsendbuffer=\fR<n> -.IP -Maximum per\-connection send buffer, <n>*1000 bytes (default: 1000) -.HP -\fB\-maxtimeadjustment\fR -.IP -Maximum allowed median peer time offset adjustment. Local perspective of -time may be influenced by peers forward or backward by this -amount. (default: 4200 seconds) -.HP -\fB\-maxuploadtarget=\fR<n> -.IP -Tries to keep outbound traffic under the given target (in MiB per 24h), -0 = no limit (default: 0) -.HP -\fB\-onion=\fR<ip:port> -.IP -Use separate SOCKS5 proxy to reach peers via Tor hidden services, set -\fB\-noonion\fR to disable (default: \fB\-proxy\fR) -.HP -\fB\-onlynet=\fR<net> -.IP -Make outgoing connections only through network <net> (ipv4, ipv6 or -onion). Incoming connections are not affected by this option. -This option can be specified multiple times to allow multiple -networks. -.HP -\fB\-peerbloomfilters\fR -.IP -Support filtering of blocks and transaction with bloom filters (default: -1) -.HP -\fB\-permitbaremultisig\fR -.IP -Relay non\-P2SH multisig (default: 1) -.HP -\fB\-port=\fR<port> -.IP -Listen for connections on <port> (default: 8333, testnet: 18333, -regtest: 18444) -.HP -\fB\-proxy=\fR<ip:port> -.IP -Connect through SOCKS5 proxy, set \fB\-noproxy\fR to disable (default: -disabled) -.HP -\fB\-proxyrandomize\fR -.IP -Randomize credentials for every proxy connection. This enables Tor -stream isolation (default: 1) -.HP -\fB\-seednode=\fR<ip> -.IP -Connect to a node to retrieve peer addresses, and disconnect. This -option can be specified multiple times to connect to multiple -nodes. -.HP -\fB\-timeout=\fR<n> -.IP -Specify connection timeout in milliseconds (minimum: 1, default: 5000) -.HP -\fB\-torcontrol=\fR<ip>:<port> -.IP -Tor control port to use if onion listening enabled (default: -127.0.0.1:9051) -.HP -\fB\-torpassword=\fR<pass> -.IP -Tor control port password (default: empty) -.HP -\fB\-upnp\fR -.IP -Use UPnP to map the listening port (default: 0) -.HP -\fB\-whitebind=\fR<addr> -.IP -Bind to given address and whitelist peers connecting to it. Use -[host]:port notation for IPv6 -.HP -\fB\-whitelist=\fR<IP address or network> -.IP -Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or -CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple -times. Whitelisted peers cannot be DoS banned and their -transactions are always relayed, even if they are already in the -mempool, useful e.g. for a gateway -.PP -Wallet options: -.HP -\fB\-addresstype\fR -.IP -What type of addresses to use ("legacy", "p2sh\-segwit", or "bech32", -default: "p2sh\-segwit") -.HP -\fB\-avoidpartialspends\fR -.IP -Group outputs by address, selecting all or none, instead of selecting on -a per\-output basis. Privacy is improved as an address is only -used once (unless someone sends to it after spending from it), -but may result in slightly higher fees as suboptimal coin -selection may result due to the added limitation (default: 0) -.HP -\fB\-changetype\fR -.IP -What type of change to use ("legacy", "p2sh\-segwit", or "bech32"). -Default is same as \fB\-addresstype\fR, except when -\fB\-addresstype\fR=\fI\,p2sh\-segwit\/\fR a native segwit output is used when -sending to a native segwit address) -.HP -\fB\-disablewallet\fR -.IP -Do not load the wallet and disable wallet RPC calls -.HP -\fB\-discardfee=\fR<amt> -.IP -The fee rate (in BTC/kB) that indicates your tolerance for discarding -change by adding it to the fee (default: 0.0001). Note: An output -is discarded if it is dust at this rate, but we will always -discard up to the dust relay fee and a discard fee above that is -limited by the fee estimate for the longest target -.HP -\fB\-fallbackfee=\fR<amt> -.IP -A fee rate (in BTC/kB) that will be used when fee estimation has -insufficient data (default: 0.0002) -.HP -\fB\-keypool=\fR<n> -.IP -Set key pool size to <n> (default: 1000) -.HP -\fB\-mintxfee=\fR<amt> -.IP -Fees (in BTC/kB) smaller than this are considered zero fee for -transaction creation (default: 0.00001) -.HP -\fB\-paytxfee=\fR<amt> -.IP -Fee (in BTC/kB) to add to transactions you send (default: 0.00) -.HP -\fB\-rescan\fR -.IP -Rescan the block chain for missing wallet transactions on startup -.HP -\fB\-salvagewallet\fR -.IP -Attempt to recover private keys from a corrupt wallet on startup -.HP -\fB\-spendzeroconfchange\fR -.IP -Spend unconfirmed change when sending transactions (default: 1) -.HP -\fB\-txconfirmtarget=\fR<n> -.IP -If paytxfee is not set, include enough fee so transactions begin -confirmation on average within n blocks (default: 6) -.HP -\fB\-upgradewallet\fR -.IP -Upgrade wallet to latest format on startup -.HP -\fB\-wallet=\fR<path> -.IP -Specify wallet database path. Can be specified multiple times to load -multiple wallets. Path is interpreted relative to <walletdir> if -it is not absolute, and will be created if it does not exist (as -a directory containing a wallet.dat file and log files). For -backwards compatibility this will also accept names of existing -data files in <walletdir>.) -.HP -\fB\-walletbroadcast\fR -.IP -Make the wallet broadcast transactions (default: 1) -.HP -\fB\-walletdir=\fR<dir> -.IP -Specify directory to hold wallets (default: <datadir>/wallets if it -exists, otherwise <datadir>) -.HP -\fB\-walletnotify=\fR<cmd> -.IP -Execute command when a wallet transaction changes (%s in cmd is replaced -by TxID) -.HP -\fB\-walletrbf\fR -.IP -Send transactions with full\-RBF opt\-in enabled (RPC only, default: 0) -.HP -\fB\-zapwallettxes=\fR<mode> -.IP -Delete all wallet transactions and only recover those parts of the -blockchain through \fB\-rescan\fR on startup (1 = keep tx meta data e.g. -payment request information, 2 = drop tx meta data) -.PP -ZeroMQ notification options: -.HP -\fB\-zmqpubhashblock=\fR<address> -.IP -Enable publish hash block in <address> -.HP -\fB\-zmqpubhashtx=\fR<address> -.IP -Enable publish hash transaction in <address> -.HP -\fB\-zmqpubrawblock=\fR<address> -.IP -Enable publish raw block in <address> -.HP -\fB\-zmqpubrawtx=\fR<address> -.IP -Enable publish raw transaction in <address> -.PP -Debugging/Testing options: -.HP -\fB\-debug=\fR<category> -.IP -Output debugging information (default: \fB\-nodebug\fR, supplying <category> is -optional). If <category> is not supplied or if <category> = 1, -output all debugging information. <category> can be: net, tor, -mempool, http, bench, zmq, db, rpc, estimatefee, addrman, -selectcoins, reindex, cmpctblock, rand, prune, proxy, mempoolrej, -libevent, coindb, qt, leveldb. -.HP -\fB\-debugexclude=\fR<category> -.IP -Exclude debugging information for a category. Can be used in conjunction -with \fB\-debug\fR=\fI\,1\/\fR to output debug logs for all categories except one -or more specified categories. -.HP -\fB\-help\-debug\fR -.IP -Print help message with debugging options and exit -.HP -\fB\-logips\fR -.IP -Include IP addresses in debug output (default: 0) -.HP -\fB\-logtimestamps\fR -.IP -Prepend debug output with timestamp (default: 1) -.HP -\fB\-maxtxfee=\fR<amt> -.IP -Maximum total fees (in BTC) to use in a single wallet transaction or raw -transaction; setting this too low may abort large transactions -(default: 0.10) -.HP -\fB\-printtoconsole\fR -.IP -Send trace/debug info to console (default: 1 when no \fB\-daemon\fR. To disable -logging to file, set \fB\-nodebuglogfile\fR) -.HP -\fB\-shrinkdebugfile\fR -.IP -Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR) -.HP -\fB\-uacomment=\fR<cmt> -.IP -Append comment to the user agent string -.PP -Chain selection options: -.HP -\fB\-testnet\fR -.IP -Use the test chain -.PP -Node relay options: -.HP -\fB\-bytespersigop\fR -.IP -Equivalent bytes per sigop in transactions for relay and mining -(default: 20) -.HP -\fB\-datacarrier\fR -.IP -Relay and mine data carrier transactions (default: 1) -.HP -\fB\-datacarriersize\fR -.IP -Maximum size of data in data carrier transactions we relay and mine -(default: 83) -.HP -\fB\-minrelaytxfee=\fR<amt> -.IP -Fees (in BTC/kB) smaller than this are considered zero fee for relaying, -mining and transaction creation (default: 0.00001) -.HP -\fB\-whitelistforcerelay\fR -.IP -Force relay of transactions from whitelisted peers even if they violate -local relay policy (default: 0) -.HP -\fB\-whitelistrelay\fR -.IP -Accept relayed transactions received from whitelisted peers even when -not relaying transactions (default: 1) -.PP -Block creation options: -.HP -\fB\-blockmaxweight=\fR<n> -.IP -Set maximum BIP141 block weight (default: 3996000) -.HP -\fB\-blockmintxfee=\fR<amt> -.IP -Set lowest fee rate (in BTC/kB) for transactions to be included in block -creation. (default: 0.00001) -.PP -RPC server options: -.HP -\fB\-rest\fR -.IP -Accept public REST requests (default: 0) -.HP -\fB\-rpcallowip=\fR<ip> -.IP -Allow JSON\-RPC connections from specified source. Valid for <ip> are a -single IP (e.g. 1.2.3.4), a network/netmask (e.g. -1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This -option can be specified multiple times -.HP -\fB\-rpcauth=\fR<userpw> -.IP -Username and HMAC\-SHA\-256 hashed password for JSON\-RPC connections. The -field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A -canonical python script is included in share/rpcauth. The client -then connects normally using the -rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This -option can be specified multiple times -.HP -\fB\-rpcbind=\fR<addr>[:port] -.IP -Bind to given address to listen for JSON\-RPC connections. Do not expose -the RPC server to untrusted networks such as the public internet! -This option is ignored unless \fB\-rpcallowip\fR is also passed. Port is -optional and overrides \fB\-rpcport\fR. Use [host]:port notation for -IPv6. This option can be specified multiple times (default: -127.0.0.1 and ::1 i.e., localhost) -.HP -\fB\-rpccookiefile=\fR<loc> -.IP -Location of the auth cookie. Relative paths will be prefixed by a -net\-specific datadir location. (default: data dir) -.HP -\fB\-rpcpassword=\fR<pw> -.IP -Password for JSON\-RPC connections -.HP -\fB\-rpcport=\fR<port> -.IP -Listen for JSON\-RPC connections on <port> (default: 8332, testnet: -18332, regtest: 18443) -.HP -\fB\-rpcserialversion\fR -.IP -Sets the serialization of raw transaction or block hex returned in -non\-verbose mode, non\-segwit(0) or segwit(1) (default: 1) -.HP -\fB\-rpcthreads=\fR<n> -.IP -Set the number of threads to service RPC calls (default: 4) -.HP -\fB\-rpcuser=\fR<user> -.IP -Username for JSON\-RPC connections -.HP -\fB\-server\fR -.IP -Accept command line and JSON\-RPC commands -.SH COPYRIGHT -Copyright (C) 2009-2019 The Bitcoin Core developers +bitcoind \- manual page for bitcoind -Please contribute if you find Bitcoin Core useful. Visit -<https://bitcoincore.org> for further information about the software. -The source code is available from <https://github.com/bitcoin/bitcoin>. - -This is experimental software. -Distributed under the MIT software license, see the accompanying file COPYING -or <https://opensource.org/licenses/MIT> +This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release. diff --git a/doc/release-notes.md b/doc/release-notes.md index d3983b1689..57067138b0 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -45,11 +45,6 @@ wallet versions of Bitcoin Core are generally supported. Compatibility ============== -During this release cycle, work has been done to ensure that the codebase is fully -compatible with C++17. The intention is to begin using C++17 features starting -with the 0.22.0 release. This means that a compiler that supports C++17 will be -required to compile 0.22.0. - Bitcoin Core is supported and extensively tested on operating systems using the Linux kernel, macOS 10.12+, and Windows 7 and newer. Bitcoin Core should also work on most other Unix-like systems but is not as @@ -60,422 +55,49 @@ From Bitcoin Core 0.20.0 onwards, macOS versions earlier than 10.12 are no longer supported. Additionally, Bitcoin Core does not yet change appearance when macOS "dark mode" is activated. -The node's known peers are persisted to disk in a file called `peers.dat`. The -format of this file has been changed in a backwards-incompatible way in order to -accommodate the storage of Tor v3 and other BIP155 addresses. This means that if -the file is modified by 0.21.0 or newer then older versions will not be able to -read it. Those old versions, in the event of a downgrade, will log an error -message that deserialization has failed and will continue normal operation -as if the file was missing, creating a new empty one. (#19954) - Notable changes =============== P2P and network changes ----------------------- -- The mempool now tracks whether transactions submitted via the wallet or RPCs - have been successfully broadcast. Every 10-15 minutes, the node will try to - announce unbroadcast transactions until a peer requests it via a `getdata` - message or the transaction is removed from the mempool for other reasons. - The node will not track the broadcast status of transactions submitted to the - node using P2P relay. This version reduces the initial broadcast guarantees - for wallet transactions submitted via P2P to a node running the wallet. (#18038) - -- The size of the set of transactions that peers have announced and we consider - for requests has been reduced from 100000 to 5000 (per peer), and further - announcements will be ignored when that limit is reached. If you need to dump - (very) large batches of transactions, exceptions can be made for trusted - peers using the "relay" network permission. For localhost for example it can - be enabled using the command line option `-whitelist=relay@127.0.0.1`. - (#19988) - -- The Tor onion service that is automatically created by setting the - `-listenonion` configuration parameter will now be created as a Tor v3 service - instead of Tor v2. The private key that was used for Tor v2 (if any) will be - left untouched in the `onion_private_key` file in the data directory (see - `-datadir`) and can be removed if not needed. Bitcoin Core will no longer - attempt to read it. The private key for the Tor v3 service will be saved in a - file named `onion_v3_private_key`. To use the deprecated Tor v2 service (not - recommended), then `onion_private_key` can be copied over - `onion_v3_private_key`, e.g. - `cp -f onion_private_key onion_v3_private_key`. (#19954) - Updated RPCs ------------ -- The `getpeerinfo` RPC now has additional `last_block` and `last_transaction` - fields that return the UNIX epoch time of the last block and the last valid - transaction received from each peer. (#19731) - -- `getnetworkinfo` now returns two new fields, `connections_in` and - `connections_out`, that provide the number of inbound and outbound peer - connections. These new fields are in addition to the existing `connections` - field, which returns the total number of peer connections. (#19405) - -- Exposed transaction version numbers are now treated as unsigned 32-bit - integers instead of signed 32-bit integers. This matches their treatment in - consensus logic. Versions greater than 2 continue to be non-standard - (matching previous behavior of smaller than 1 or greater than 2 being - non-standard). Note that this includes the joinpsbt command, which combines - partially-signed transactions by selecting the highest version number. - (#16525) - -- `getmempoolinfo` now returns an additional `unbroadcastcount` field. The - mempool tracks locally submitted transactions until their initial broadcast - is acknowledged by a peer. This field returns the count of transactions - waiting for acknowledgement. - -- Mempool RPCs such as `getmempoolentry` and `getrawmempool` with - `verbose=true` now return an additional `unbroadcast` field. This indicates - whether initial broadcast of the transaction has been acknowledged by a - peer. `getmempoolancestors` and `getmempooldescendants` are also updated. - -- The `bumpfee`, `fundrawtransaction`, `sendmany`, `sendtoaddress`, and `walletcreatefundedpsbt` -RPC commands have been updated to include two new fee estimation methods "BTC/kB" and "sat/B". -The target is the fee expressed explicitly in the given form. Note that use of this feature -will trigger BIP 125 (replace-by-fee) opt-in. (#11413) - -- In addition, the `estimate_mode` parameter is now case insensitive for all of - the above RPC commands. (#11413) - -- The `bumpfee` command now uses `conf_target` rather than `confTarget` in the - options. (#11413) - -- The `getpeerinfo` RPC no longer returns the `banscore` field unless the configuration - option `-deprecatedrpc=banscore` is used. The `banscore` field will be fully - removed in the next major release. (#19469) - -- The `testmempoolaccept` RPC returns `vsize` and a `fees` object with the `base` fee - if the transaction would pass validation. (#19940) - -- The `getpeerinfo` RPC now returns a `connection_type` field. This indicates - the type of connection established with the peer. It will return one of six - options. For more information, see the `getpeerinfo` help documentation. - (#19725) - -- The `getpeerinfo` RPC no longer returns the `addnode` field by default. This - field will be fully removed in the next major release. It can be accessed - with the configuration option `-deprecatedrpc=getpeerinfo_addnode`. However, - it is recommended to instead use the `connection_type` field (it will return - `manual` when addnode is true). (#19725) - -- The `walletcreatefundedpsbt` RPC call will now fail with - `Insufficient funds` when inputs are manually selected but are not enough to cover - the outputs and fee. Additional inputs can automatically be added through the - new `add_inputs` option. (#16377) - -- The `fundrawtransaction` RPC now supports `add_inputs` option that when `false` - prevents adding more inputs if necessary and consequently the RPC fails. - Changes to Wallet or GUI related RPCs can be found in the GUI or Wallet section below. New RPCs -------- -- The `getindexinfo` RPC returns the actively running indices of the node, - including their current sync status and height. It also accepts an `index_name` - to specify returning only the status of that index. (#19550) - Build System ------------ +New settings +------------ + Updated settings ---------------- -- The same ZeroMQ notification (e.g. `-zmqpubhashtx=address`) can now be - specified multiple times to publish the same notification to different ZeroMQ - sockets. (#18309) - -- The `-banscore` configuration option, which modified the default threshold for - disconnecting and discouraging misbehaving peers, has been removed as part of - changes in 0.20.1 and in this release to the handling of misbehaving peers. - Refer to "Changes regarding misbehaving peers" in the 0.20.1 release notes for - details. (#19464) - -- The `-debug=db` logging category, which was deprecated in 0.20 and replaced by - `-debug=walletdb` to distinguish it from `coindb`, has been removed. (#19202) - -- A `download` permission has been extracted from the `noban` permission. For - compatibility, `noban` implies the `download` permission, but this may change - in future releases. Refer to the help of the affected settings `-whitebind` - and `-whitelist` for more details. (#19191) - -- Netmasks that contain 1-bits after 0-bits (the 1-bits are not contiguous on - the left side, e.g. 255.0.255.255) are no longer accepted. They are invalid - according to RFC 4632. Netmasks are used in the `-rpcallowip` and `-whitelist` - configuration options and in the `setban` RPC. (#19628) - -Changes to Wallet or GUI related settings can be found in the GUI or Wallet section below. +Changes to Wallet or GUI related settings can be found in the GUI or Wallet section below. Tools and Utilities ------------------- -- The `connections` field of `bitcoin-cli -getinfo` is expanded to return a JSON - object with `in`, `out` and `total` numbers of peer connections. It previously - returned a single integer value for the total number of peer connections. (#19405) - -- A new `bitcoin-cli -generate` command, equivalent to RPC `generatenewaddress` - followed by `generatetoaddress`, can generate blocks for command line testing - purposes. This is a client-side version of the - former `generate` RPC. See the help for details. (#19133) - -- The `bitcoin-cli -getinfo` command now displays the wallet name and balance for - each of the loaded wallets when more than one is loaded (e.g. in multiwallet - mode) and a wallet is not specified with `-rpcwallet`. (#18594) - -New settings ------------- - -- The `startupnotify` option is used to specify a command to - execute when Bitcoin Core has finished with its startup - sequence. (#15367) - Wallet ------ -- Backwards compatibility has been dropped for two `getaddressinfo` RPC - deprecations, as notified in the 0.20 release notes. The deprecated `label` - field has been removed as well as the deprecated `labels` behavior of - returning a JSON object containing `name` and `purpose` key-value pairs. Since - 0.20, the `labels` field returns a JSON array of label names. (#19200) - -- To improve wallet privacy, the frequency of wallet rebroadcast attempts is - reduced from approximately once every 15 minutes to once every 12-36 hours. - To maintain a similar level of guarantee for initial broadcast of wallet - transactions, the mempool tracks these transactions as a part of the newly - introduced unbroadcast set. See the "P2P and network changes" section for - more information on the unbroadcast set. (#18038) - -- The `sendtoaddress` and `sendmany` RPCs accept an optional `verbose=True` - argument to also return the fee reason about the sent tx. (#19501) - -- The wallet can create a transaction without change even when the keypool is - empty. Previously it failed. (#17219) - -- The `-salvagewallet` startup option has been removed. A new `salvage` command - has been added to the `bitcoin-wallet` tool which performs the salvage - operations that `-salvagewallet` did. (#18918) - -- A new configuration flag `-maxapsfee` has been added, which sets the max - allowed avoid partial spends (APS) fee. It defaults to 0 (i.e. fee is the - same with and without APS). Setting it to -1 will disable APS, unless - `-avoidpartialspends` is set. (#14582) - -- The wallet will now avoid partial spends (APS) by default, if this does not - result in a difference in fees compared to the non-APS variant. The allowed - fee threshold can be adjusted using the new `-maxapsfee` configuration - option. (#14582) - -- The `createwallet`, `loadwallet`, and `unloadwallet` RPCs now accept - `load_on_startup` options to modify the settings list. Unless these options - are explicitly set to true or false, the list is not modified, so the RPC - methods remain backwards compatible. (#15937) - -- A new `send` RPC with similar syntax to `walletcreatefundedpsbt`, including - support for coin selection and a custom fee rate. The `send` RPC is - experimental and may change in subsequent releases. Using it is encouraged - once it's no longer experimental: `sendmany` and `sendtoaddress` may be - deprecated in a future release. (#16378) - -- `fundrawtransaction` and `walletcreatefundedpsbt` when used with the - `lockUnspents` argument now lock manually selected coins, in addition to - automatically selected coins. Note that locked coins are never used in - automatic coin selection, but can still be manually selected. (#18244) - -- The `-zapwallettxes` startup option has been removed and its functionality - removed from the wallet. This option was originally intended to allow for - the fee bumping of transactions that did not signal RBF. This functionality - has been superseded with the abandon transaction feature. (#19671) - -- The error code when no wallet is loaded, but a wallet RPC is called, has been - changed from `-32601` (method not found) to `-18` (wallet not found). - (#20101) - -### Automatic wallet creation removed - -Bitcoin Core will no longer automatically create new wallets on startup. It will -load existing wallets specified by `-wallet` options on the command line or in -`bitcoin.conf` or `settings.json` files. And by default it will also load a -top-level unnamed ("") wallet. However, if specified wallets don't exist, -Bitcoin Core will now just log warnings instead of creating new wallets with -new keys and addresses like previous releases did. - -New wallets can be created through the GUI (which has a more prominent create -wallet option), through the `bitcoin-cli createwallet` or `bitcoin-wallet -create` commands, or the `createwallet` RPC. (#15454) - -### Experimental Descriptor Wallets - -Please note that Descriptor Wallets are still experimental and not all expected functionality -is available. Additionally there may be some bugs and current functions may change in the future. -Bugs and missing functionality can be reported to the [issue tracker](https://github.com/bitcoin/bitcoin/issues). - -0.21 introduces a new type of wallet - Descriptor Wallets. Descriptor Wallets store -scriptPubKey information using descriptors. This is in contrast to the Legacy Wallet -structure where keys are used to generate scriptPubKeys and addresses. Because of this -shift to being script based instead of key based, many of the confusing things that Legacy -Wallets do are not possible with Descriptor Wallets. Descriptor Wallets use a definition -of "mine" for scripts which is simpler and more intuitive than that used by Legacy Wallets. -Descriptor Wallets also uses different semantics for watch-only things and imports. - -As Descriptor Wallets are a new type of wallet, their introduction does not affect existing wallets. -Users who already have a Bitcoin Core wallet can continue to use it as they did before without -any change in behavior. Newly created Legacy Wallets (which is the default type of wallet) will -behave as they did in previous versions of Bitcoin Core. - -The differences between Descriptor Wallets and Legacy Wallets are largely limited to non user facing -things. They are intended to behave similarly except for the import/export and watchonly functionality -as described below. - -#### Creating Descriptor Wallets - -Descriptor Wallets are not created by default. They must be explicitly created using the -`createwallet` RPC or via the GUI. A `descriptors` option has been added to `createwallet`. -Setting `descriptors` to `true` will create a Descriptor Wallet instead of a Legacy Wallet. - -In the GUI, a checkbox has been added to the Create Wallet Dialog to indicate that a -Descriptor Wallet should be created. - -Without those options being set, a Legacy Wallet will be created instead. Additionally the -Default Wallet created upon first startup of Bitcoin Core will be a Legacy Wallet. - -#### `IsMine` Semantics - -`IsMine` refers to the function used to determine whether a script belongs to the wallet. -This is used to determine whether an output belongs to the wallet. `IsMine` in Legacy Wallets -returns true if the wallet would be able to sign an input that spends an output with that script. -Since keys can be involved in a variety of different scripts, this definition for `IsMine` can -lead to many unexpected scripts being considered part of the wallet. - -With Descriptor Wallets, descriptors explicitly specify the set of scripts that are owned by -the wallet. Since descriptors are deterministic and easily enumerable, users will know exactly -what scripts the wallet will consider to belong to it. Additionally the implementation of `IsMine` -in Descriptor Wallets is far simpler than for Legacy Wallets. Notably, in Legacy Wallets, `IsMine` -allowed for users to take one type of address (e.g. P2PKH), mutate it into another address type -(e.g. P2WPKH), and the wallet would still detect outputs sending to the new address type -even without that address being requested from the wallet. Descriptor Wallets does not -allow for this and will only watch for the addresses that were explicitly requested from the wallet. - -These changes to `IsMine` will make it easier to reason about what scripts the wallet will -actually be watching for in outputs. However for the vast majority of users, this change is -largely transparent and will not have noticeable effect. - -#### Imports and Exports - -In Legacy Wallets, raw scripts and keys could be imported to the wallet. Those imported scripts -and keys are treated separately from the keys generated by the wallet. This complicates the `IsMine` -logic as it has to distinguish between spendable and watchonly. - -Descriptor Wallets handle importing scripts and keys differently. Only complete descriptors can be -imported. These descriptors are then added to the wallet as if it were a descriptor generated by -the wallet itself. This simplifies the `IsMine` logic so that it no longer has to distinguish -between spendable and watchonly. As such, the watchonly model for Descriptor Wallets is also -different and described in more detail in the next section. - -To import into a Descriptor Wallet, a new `importdescriptors` RPC has been added that uses a syntax -similar to that of `importmulti`. - -As Legacy Wallets and Descriptor Wallets use different mechanisms for storing and importing scripts and keys -the existing import RPCs have been disabled for descriptor wallets. -New export RPCs for Descriptor Wallets have not yet been added. - -The following RPCs are disabled for Descriptor Wallets: - -* importprivkey -* importpubkey -* importaddress -* importwallet -* dumpprivkey -* dumpwallet -* importmulti -* addmultisigaddress -* sethdseed - -#### Watchonly Wallets - -A Legacy Wallet contains both private keys and scripts that were being watched. -Those watched scripts would not contribute to your normal balance. In order to see the watchonly -balance and to use watchonly things in transactions, an `include_watchonly` option was added -to many RPCs that would allow users to do that. However it is easy to forget to include this option. - -Descriptor Wallets move to a per-wallet watchonly model. Instead an entire wallet is considered to be -watchonly depending on whether it was created with private keys disabled. This eliminates the need -to distinguish between things that are watchonly and things that are not within a wallet itself. - -This change does have a caveat. If a Descriptor Wallet with private keys *enabled* has -a multiple key descriptor without all of the private keys (e.g. `multi(...)` with only one private key), -then the wallet will fail to sign and broadcast transactions. Such wallets would need to use the PSBT -workflow but the typical GUI Send, `sendtoaddress`, etc. workflows would still be available, just -non-functional. - -This issue is worsened if the wallet contains both single key (e.g. `wpkh(...)`) descriptors and such -multiple key descriptors as some transactions could be signed and broadast and others not. This is -due to some transactions containing only single key inputs, while others would contain both single -key and multiple key inputs, depending on which are available and how the coin selection algorithm -selects inputs. However this is not considered to be a supported use case; multisigs -should be in their own wallets which do not already have descriptors. Although users cannot export -descriptors with private keys for now as explained earlier. - -#### BIP 44/49/84 Support - -The change to using descriptors changes the default derivation paths used by Bitcoin Core -to adhere to BIP 44/49/84. Descriptors with different derivation paths can be imported without -issue. - -### Wallet RPC changes - -- The `upgradewallet` RPC replaces the `-upgradewallet` command line option. - (#15761) -- The `settxfee` RPC will fail if the fee was set higher than the `-maxtxfee` - command line setting. The wallet will already fail to create transactions - with fees higher than `-maxtxfee`. (#18467) - GUI changes ----------- -- Wallets created or loaded in the GUI will now be automatically loaded on - startup, so they don't need to be manually reloaded next time Bitcoin Core is - started. The list of wallets to load on startup is stored in - `\<datadir\>/settings.json` and augments any command line or `bitcoin.conf` - `-wallet=` settings that specify more wallets to load. Wallets that are - unloaded in the GUI get removed from the settings list so they won't load - again automatically next startup. (#19754) - -- The GUI Peers window no longer displays a "Ban Score" field. This is part of - changes in 0.20.1 and in this release to the handling of misbehaving - peers. Refer to "Changes regarding misbehaving peers" in the 0.20.1 release - notes for details. (#19512) - Low-level changes ================= RPC --- -- To make RPC `sendtoaddress` more consistent with `sendmany` the following error - `sendtoaddress` codes were changed from `-4` to `-6`: - - Insufficient funds - - Fee estimation failed - - Transaction has too long of a mempool chain - -- The `sendrawtransaction` error code for exceeding `maxfeerate` has been changed from - `-26` to `-25`. The error string has been changed from "absurdly-high-fee" to - "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)." The - `testmempoolaccept` RPC returns `max-fee-exceeded` rather than `absurdly-high-fee` - as the `reject-reason`. (#19339) - -- To make wallet and rawtransaction RPCs more consistent, the error message for - exceeding maximum feerate has been changed to "Fee exceeds maximum configured by user - (e.g. -maxtxfee, maxfeerate)." (#19339) - Tests ----- -- The BIP 325 default signet can be enabled by the `-chain=signet` or `-signet` - setting. The settings `-signetchallenge` and `-signetseednode` allow - enabling a custom signet. - Credits ======= diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 7fac78f973..f6c5a06f6f 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -7,6 +7,7 @@ FUZZ_TARGETS = \ test/fuzz/addr_info_deserialize \ test/fuzz/addrdb \ test/fuzz/address_deserialize \ + test/fuzz/addrman \ test/fuzz/addrman_deserialize \ test/fuzz/asmap \ test/fuzz/asmap_direct \ @@ -35,6 +36,7 @@ FUZZ_TARGETS = \ test/fuzz/checkqueue \ test/fuzz/coins_deserialize \ test/fuzz/coins_view \ + test/fuzz/connman \ test/fuzz/crypto \ test/fuzz/crypto_aes256 \ test/fuzz/crypto_aes256cbc \ @@ -293,6 +295,7 @@ BITCOIN_TESTS += \ wallet/test/db_tests.cpp \ wallet/test/psbt_wallet_tests.cpp \ wallet/test/wallet_tests.cpp \ + wallet/test/walletdb_tests.cpp \ wallet/test/wallet_crypto_tests.cpp \ wallet/test/coinselector_tests.cpp \ wallet/test/init_tests.cpp \ @@ -352,6 +355,12 @@ test_fuzz_address_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_address_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON) test_fuzz_address_deserialize_SOURCES = test/fuzz/deserialize.cpp +test_fuzz_addrman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_addrman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_addrman_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_addrman_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON) +test_fuzz_addrman_SOURCES = test/fuzz/addrman.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) @@ -520,6 +529,12 @@ test_fuzz_coins_view_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_coins_view_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON) test_fuzz_coins_view_SOURCES = test/fuzz/coins_view.cpp +test_fuzz_connman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_connman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_connman_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_connman_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON) +test_fuzz_connman_SOURCES = test/fuzz/connman.cpp + test_fuzz_crypto_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) test_fuzz_crypto_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_crypto_LDADD = $(FUZZ_SUITE_LD_COMMON) diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include index d7bc73defb..0621da8ddf 100644 --- a/src/Makefile.test_util.include +++ b/src/Makefile.test_util.include @@ -15,6 +15,7 @@ TEST_UTIL_H = \ test/util/setup_common.h \ test/util/str.h \ test/util/transaction_utils.h \ + test/util/validation.h \ test/util/wallet.h libtest_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) @@ -27,6 +28,7 @@ libtest_util_a_SOURCES = \ test/util/setup_common.cpp \ test/util/str.cpp \ test/util/transaction_utils.cpp \ + test/util/validation.cpp \ test/util/wallet.cpp \ $(TEST_UTIL_H) diff --git a/src/addrman.h b/src/addrman.h index b4089dc894..9ac67b7af6 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -7,6 +7,7 @@ #define BITCOIN_ADDRMAN_H #include <clientversion.h> +#include <config/bitcoin-config.h> #include <netaddress.h> #include <protocol.h> #include <random.h> @@ -176,6 +177,28 @@ protected: mutable RecursiveMutex cs; private: + //! Serialization versions. + enum Format : uint8_t { + V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88 + V1_DETERMINISTIC = 1, //!< for pre-asmap files + V2_ASMAP = 2, //!< for files including asmap version + V3_BIP155 = 3, //!< same as V2_ASMAP plus addresses are in BIP155 format + }; + + //! The maximum format this software knows it can unserialize. Also, we always serialize + //! in this format. + //! The format (first byte in the serialized stream) can be higher than this and + //! still this software may be able to unserialize the file - if the second byte + //! (see `lowest_compatible` in `Unserialize()`) is less or equal to this. + static constexpr Format FILE_FORMAT = Format::V3_BIP155; + + //! The initial value of a field that is incremented every time an incompatible format + //! change is made (such that old software versions would not be able to parse and + //! understand the new file format). This is 32 because we overtook the "key size" + //! field which was 32 historically. + //! @note Don't increment this. Increment `lowest_compatible` in `Serialize()` instead. + static constexpr uint8_t INCOMPATIBILITY_BASE = 32; + //! last used nId int nIdCount GUARDED_BY(cs); @@ -258,21 +281,23 @@ protected: //! Select several addresses at once. void GetAddr_(std::vector<CAddress> &vAddr, size_t max_addresses, size_t max_pct) EXCLUSIVE_LOCKS_REQUIRED(cs); - //! Mark an entry as currently-connected-to. - void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs); + /** We have successfully connected to this peer. Calling this function + * updates the CAddress's nTime, which is used in our IsTerrible() + * decisions and gossiped to peers. Callers should be careful that updating + * this information doesn't leak topology information to network spies. + * + * net_processing calls this function when it *disconnects* from a peer to + * not leak information about currently connected peers. + * + * @param[in] addr The address of the peer we were connected to + * @param[in] nTime The time that we were last connected to this peer + */ + void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs); //! Update an entry's service bits. void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs); public: - //! Serialization versions. - enum class Format : uint8_t { - V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88 - V1_DETERMINISTIC = 1, //!< for pre-asmap files - V2_ASMAP = 2, //!< for files including asmap version - V3_BIP155 = 3, //!< same as V2_ASMAP plus addresses are in BIP155 format - }; - // Compressed IP->ASN mapping, loaded from a file when a node starts. // Should be always empty if no file was provided. // This mapping is then used for bucketing nodes in Addrman. @@ -295,8 +320,18 @@ public: /** * Serialized format. - * * version byte (@see `Format`) - * * 0x20 + nKey (serialized as if it were a vector, for backward compatibility) + * * format version byte (@see `Format`) + * * lowest compatible format version byte. This is used to help old software decide + * whether to parse the file. For example: + * * Bitcoin Core version N knows how to parse up to format=3. If a new format=4 is + * introduced in version N+1 that is compatible with format=3 and it is known that + * version N will be able to parse it, then version N+1 will write + * (format=4, lowest_compatible=3) in the first two bytes of the file, and so + * version N will still try to parse it. + * * Bitcoin Core version N+2 introduces a new incompatible format=5. It will write + * (format=5, lowest_compatible=5) and so any versions that do not know how to parse + * format=5 will not try to read the file. + * * nKey * * nNew * * nTried * * number of "new" buckets XOR 2**30 @@ -327,12 +362,17 @@ public: { LOCK(cs); - // Always serialize in the latest version (currently Format::V3_BIP155). + // Always serialize in the latest version (FILE_FORMAT). OverrideStream<Stream> s(&s_, s_.GetType(), s_.GetVersion() | ADDRV2_FORMAT); - s << static_cast<uint8_t>(Format::V3_BIP155); - s << ((unsigned char)32); + s << static_cast<uint8_t>(FILE_FORMAT); + + // Increment `lowest_compatible` iff a newly introduced format is incompatible with + // the previous one. + static constexpr uint8_t lowest_compatible = Format::V3_BIP155; + s << static_cast<uint8_t>(INCOMPATIBILITY_BASE + lowest_compatible); + s << nKey; s << nNew; s << nTried; @@ -392,15 +432,6 @@ public: Format format; s_ >> Using<CustomUintFormatter<1>>(format); - static constexpr Format maximum_supported_format = Format::V3_BIP155; - if (format > maximum_supported_format) { - throw std::ios_base::failure(strprintf( - "Unsupported format of addrman database: %u. Maximum supported is %u. " - "Continuing operation without using the saved list of peers.", - static_cast<uint8_t>(format), - static_cast<uint8_t>(maximum_supported_format))); - } - int stream_version = s_.GetVersion(); if (format >= Format::V3_BIP155) { // Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress @@ -410,9 +441,16 @@ public: OverrideStream<Stream> s(&s_, s_.GetType(), stream_version); - unsigned char nKeySize; - s >> nKeySize; - if (nKeySize != 32) throw std::ios_base::failure("Incorrect keysize in addrman deserialization"); + uint8_t compat; + s >> compat; + const uint8_t lowest_compatible = compat - INCOMPATIBILITY_BASE; + if (lowest_compatible > FILE_FORMAT) { + throw std::ios_base::failure(strprintf( + "Unsupported format of addrman database: %u. It is compatible with formats >=%u, " + "but the maximum supported by this version of %s is %u.", + format, lowest_compatible, PACKAGE_NAME, static_cast<uint8_t>(FILE_FORMAT))); + } + s >> nKey; s >> nNew; s >> nTried; @@ -676,7 +714,7 @@ public: return vAddr; } - //! Mark an entry as currently-connected-to. + //! Outer function for Connected_() void Connected(const CService &addr, int64_t nTime = GetAdjustedTime()) { LOCK(cs); diff --git a/src/bloom.h b/src/bloom.h index 9307257852..24dc607cd9 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -94,7 +94,18 @@ public: * insert()'ed ... but may also return true for items that were not inserted. * * It needs around 1.8 bytes per element per factor 0.1 of false positive rate. - * (More accurately: 3/(log(256)*log(2)) * log(1/fpRate) * nElements bytes) + * For example, if we want 1000 elements, we'd need: + * - ~1800 bytes for a false positive rate of 0.1 + * - ~3600 bytes for a false positive rate of 0.01 + * - ~5400 bytes for a false positive rate of 0.001 + * + * If we make these simplifying assumptions: + * - logFpRate / log(0.5) doesn't get rounded or clamped in the nHashFuncs calculation + * - nElements is even, so that nEntriesPerGeneration == nElements / 2 + * + * Then we get a more accurate estimate for filter bytes: + * + * 3/(log(256)*log(2)) * log(1/fpRate) * nElements */ class CRollingBloomFilter { diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 9c32f0db4c..fedb032db2 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -322,8 +322,8 @@ public: consensus.nPowTargetSpacing = 10 * 60; consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowNoRetargeting = false; - consensus.nRuleChangeActivationThreshold = 1916; - consensus.nMinerConfirmationWindow = 2016; + consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016 + consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing consensus.MinBIP9WarningHeight = 0; consensus.powLimit = uint256S("00000377ae000000000000000000000000000000000000000000000000000000"); consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; diff --git a/src/core_read.cpp b/src/core_read.cpp index 121e62457c..c6416e6f07 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -15,7 +15,6 @@ #include <version.h> #include <boost/algorithm/string/classification.hpp> -#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> #include <algorithm> @@ -40,8 +39,9 @@ CScript ParseScript(const std::string& s) continue; mapOpNames[strName] = static_cast<opcodetype>(op); // Convenience: OP_ADD and just ADD are both recognized: - boost::algorithm::replace_first(strName, "OP_", ""); - mapOpNames[strName] = static_cast<opcodetype>(op); + if (strName.compare(0, 3, "OP_") == 0) { // strName starts with "OP_" + mapOpNames[strName.substr(3)] = static_cast<opcodetype>(op); + } } } diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp index 8d2dcd0279..4543f098a1 100644 --- a/src/dummywallet.cpp +++ b/src/dummywallet.cpp @@ -40,7 +40,6 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const "-salvagewallet", "-spendzeroconfchange", "-txconfirmtarget=<n>", - "-upgradewallet", "-wallet=<path>", "-walletbroadcast", "-walletdir=<dir>", diff --git a/src/init.cpp b/src/init.cpp index 1387d6b982..1e41616e94 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1039,7 +1039,7 @@ bool AppInitParameterInteraction(const ArgsManager& args) // Trim requested connection counts, to fit into system limitations // <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695 - nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS); + nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS + nBind); #ifdef USE_POLL int fd_max = nFD; #else @@ -1145,7 +1145,7 @@ bool AppInitParameterInteraction(const ArgsManager& args) if (!ParseMoney(args.GetArg("-minrelaytxfee", ""), n)) { return InitError(AmountErrMsg("minrelaytxfee", args.GetArg("-minrelaytxfee", ""))); } - // High fee check is done afterward in CWallet::CreateWalletFromFile() + // High fee check is done afterward in CWallet::Create() ::minRelayTxFee = CFeeRate(n); } else if (incrementalRelayFee > ::minRelayTxFee) { // Allow only setting incrementalRelayFee to control both diff --git a/src/net.cpp b/src/net.cpp index cf987b6995..20c1763ea6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2445,17 +2445,6 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) { Init(connOptions); - { - LOCK(cs_totalBytesRecv); - nTotalBytesRecv = 0; - } - { - LOCK(cs_totalBytesSent); - nTotalBytesSent = 0; - nMaxOutboundTotalBytesSentInCycle = 0; - nMaxOutboundCycleStartTime = 0; - } - if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds, connOptions.onion_binds)) { if (clientInterface) { clientInterface->ThreadSafeMessageBox( @@ -478,8 +478,8 @@ private: uint64_t nTotalBytesSent GUARDED_BY(cs_totalBytesSent) {0}; // outbound limit & stats - uint64_t nMaxOutboundTotalBytesSentInCycle GUARDED_BY(cs_totalBytesSent); - uint64_t nMaxOutboundCycleStartTime GUARDED_BY(cs_totalBytesSent); + uint64_t nMaxOutboundTotalBytesSentInCycle GUARDED_BY(cs_totalBytesSent) {0}; + uint64_t nMaxOutboundCycleStartTime GUARDED_BY(cs_totalBytesSent) {0}; uint64_t nMaxOutboundLimit GUARDED_BY(cs_totalBytesSent); uint64_t nMaxOutboundTimeframe GUARDED_BY(cs_totalBytesSent); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index c649cf7757..e9915a3091 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -290,8 +290,6 @@ namespace { struct CNodeState { //! The peer's address const CService address; - //! Whether we have a fully established connection. - bool fCurrentlyConnected; //! The best known block we know this peer has announced. const CBlockIndex *pindexBestKnownBlock; //! The hash of the last unknown block this peer has announced. @@ -390,7 +388,6 @@ struct CNodeState { CNodeState(CAddress addrIn, bool is_inbound, bool is_manual) : address(addrIn), m_is_inbound(is_inbound), m_is_manual_connection(is_manual) { - fCurrentlyConnected = false; pindexBestKnownBlock = nullptr; hashLastUnknownBlock.SetNull(); pindexLastCommonBlock = nullptr; @@ -857,8 +854,9 @@ void PeerManager::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) { if (state->fSyncStarted) nSyncStarted--; - if (misbehavior == 0 && state->fCurrentlyConnected && !node.IsBlockOnlyConn()) { - // Note: we avoid changing visible addrman state for block-relay-only peers + if (node.fSuccessfullyConnected && misbehavior == 0 && + !node.IsBlockOnlyConn() && !node.IsInboundConn()) { + // Only change visible addrman state for outbound, full-relay peers fUpdateConnectionTime = true; } @@ -2488,9 +2486,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat if (pfrom.fSuccessfullyConnected) return; if (!pfrom.IsInboundConn()) { - // Mark this node as currently connected, so we update its timestamp later. - LOCK(cs_main); - State(pfrom.GetId())->fCurrentlyConnected = true; LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n", pfrom.nVersion.load(), pfrom.nStartingHeight, pfrom.GetId(), (fLogIPs ? strprintf(", peeraddr=%s", pfrom.addr.ToString()) : ""), diff --git a/src/netaddress.cpp b/src/netaddress.cpp index c0193fa2e9..35e9161f58 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -255,10 +255,14 @@ bool CNetAddr::SetSpecial(const std::string& str) Span<const uint8_t> input_checksum{input.data() + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN}; Span<const uint8_t> input_version{input.data() + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, sizeof(torv3::VERSION)}; + if (input_version != torv3::VERSION) { + return false; + } + uint8_t calculated_checksum[torv3::CHECKSUM_LEN]; torv3::Checksum(input_pubkey, calculated_checksum); - if (input_checksum != calculated_checksum || input_version != torv3::VERSION) { + if (input_checksum != calculated_checksum) { return false; } diff --git a/src/netaddress.h b/src/netaddress.h index f35b01d202..29b2eaafeb 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -29,7 +29,7 @@ * Make sure that this does not collide with any of the values in `version.h` * or with `SERIALIZE_TRANSACTION_NO_WITNESS`. */ -static const int ADDRV2_FORMAT = 0x20000000; +static constexpr int ADDRV2_FORMAT = 0x20000000; /** * A network type. diff --git a/src/policy/feerate.cpp b/src/policy/feerate.cpp index a01e259731..04e0e117a5 100644 --- a/src/policy/feerate.cpp +++ b/src/policy/feerate.cpp @@ -38,7 +38,7 @@ CAmount CFeeRate::GetFee(size_t nBytes_) const std::string CFeeRate::ToString(const FeeEstimateMode& fee_estimate_mode) const { switch (fee_estimate_mode) { - case FeeEstimateMode::SAT_B: return strprintf("%d.%03d %s/B", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM); - default: return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT); + case FeeEstimateMode::SAT_VB: return strprintf("%d.%03d %s/vB", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM); + default: return strprintf("%d.%08d %s/kvB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT); } } diff --git a/src/policy/feerate.h b/src/policy/feerate.h index 883940f73c..7c5660ac8a 100644 --- a/src/policy/feerate.h +++ b/src/policy/feerate.h @@ -19,8 +19,8 @@ enum class FeeEstimateMode { UNSET, //!< Use default settings based on other criteria ECONOMICAL, //!< Force estimateSmartFee to use non-conservative estimates CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates - BTC_KB, //!< Use explicit BTC/kB fee given in coin control - SAT_B, //!< Use explicit sat/B fee given in coin control + BTC_KVB, //!< Use BTC/kvB fee rate unit + SAT_VB, //!< Use sat/vB fee rate unit }; /** @@ -39,7 +39,16 @@ public: // We've previously had bugs creep in from silent double->int conversion... static_assert(std::is_integral<I>::value, "CFeeRate should be used without floats"); } - /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/ + /** Constructor for a fee rate in satoshis per kvB (sat/kvB). The size in bytes must not exceed (2^63 - 1). + * + * Passing an nBytes value of COIN (1e8) returns a fee rate in satoshis per vB (sat/vB), + * e.g. (nFeePaid * 1e8 / 1e3) == (nFeePaid / 1e5), + * where 1e5 is the ratio to convert from BTC/kvB to sat/vB. + * + * @param[in] nFeePaid CAmount fee rate to construct with + * @param[in] nBytes size_t bytes (units) to construct with + * @returns fee rate + */ CFeeRate(const CAmount& nFeePaid, size_t nBytes); /** * Return the fee in satoshis for the given size in bytes. @@ -56,7 +65,7 @@ public: friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } friend bool operator!=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK != b.nSatoshisPerK; } CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; } - std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BTC_KB) const; + std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BTC_KVB) const; SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); } }; diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 3d1963b6e6..3b4967421a 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -58,14 +58,6 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent, SecureStri ui->passEdit3->hide(); setWindowTitle(tr("Unlock wallet")); break; - case Decrypt: // Ask passphrase - ui->warningLabel->setText(tr("This operation needs your wallet passphrase to decrypt the wallet.")); - ui->passLabel2->hide(); - ui->passEdit2->hide(); - ui->passLabel3->hide(); - ui->passEdit3->hide(); - setWindowTitle(tr("Decrypt wallet")); - break; case ChangePass: // Ask old passphrase + new passphrase x2 setWindowTitle(tr("Change passphrase")); ui->warningLabel->setText(tr("Enter the old passphrase and new passphrase for the wallet.")); @@ -133,8 +125,7 @@ void AskPassphraseDialog::accept() "</b></qt>"); } else { assert(model != nullptr); - if(model->setWalletEncrypted(true, newpass1)) - { + if (model->setWalletEncrypted(newpass1)) { QMessageBox::warning(this, tr("Wallet encrypted"), "<qt>" + tr("Your wallet is now encrypted. ") + encryption_reminder + @@ -144,9 +135,7 @@ void AskPassphraseDialog::accept() "For security reasons, previous backups of the unencrypted wallet file " "will become useless as soon as you start using the new, encrypted wallet.") + "</b></qt>"); - } - else - { + } else { QMessageBox::critical(this, tr("Wallet encryption failed"), tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted.")); } @@ -176,17 +165,6 @@ void AskPassphraseDialog::accept() QMessageBox::critical(this, tr("Wallet unlock failed"), e.what()); } break; - case Decrypt: - if(!model->setWalletEncrypted(false, oldpass)) - { - QMessageBox::critical(this, tr("Wallet decryption failed"), - tr("The passphrase entered for the wallet decryption was incorrect.")); - } - else - { - QDialog::accept(); // Success - } - break; case ChangePass: if(newpass1 == newpass2) { @@ -221,9 +199,6 @@ void AskPassphraseDialog::textChanged() acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); break; case Unlock: // Old passphrase x1 - case Decrypt: - acceptable = !ui->passEdit1->text().isEmpty(); - break; case ChangePass: // Old passphrase x1, new passphrase x2 acceptable = !ui->passEdit1->text().isEmpty() && !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); break; diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h index 9557e72936..f3ba882277 100644 --- a/src/qt/askpassphrasedialog.h +++ b/src/qt/askpassphrasedialog.h @@ -26,7 +26,6 @@ public: Encrypt, /**< Ask passphrase twice and encrypt */ Unlock, /**< Ask passphrase and unlock */ ChangePass, /**< Ask old passphrase + new passphrase twice */ - Decrypt /**< Ask passphrase and decrypt wallet */ }; explicit AskPassphraseDialog(Mode mode, QWidget *parent, SecureString* passphrase_out = nullptr); diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 193098ed82..27e512d075 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -129,7 +129,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: Private keys can only be di QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: Wallet corrupted"), QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: Wallet requires newer version of %s"), QT_TRANSLATE_NOOP("bitcoin-core", "Error loading block database"), -QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet %s. Duplicate -wallet filename specified."), QT_TRANSLATE_NOOP("bitcoin-core", "Error opening block database"), QT_TRANSLATE_NOOP("bitcoin-core", "Error reading from database, shutting down."), QT_TRANSLATE_NOOP("bitcoin-core", "Error upgrading chainstate database"), @@ -139,6 +138,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 i QT_TRANSLATE_NOOP("bitcoin-core", "Failed to rescan the wallet during initialization"), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to verify database"), QT_TRANSLATE_NOOP("bitcoin-core", "Fee rate (%s) is lower than the minimum fee rate setting (%s)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Ignoring duplicate -wallet %s."), QT_TRANSLATE_NOOP("bitcoin-core", "Importing..."), QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"), QT_TRANSLATE_NOOP("bitcoin-core", "Initialization sanity check failed. %s is shutting down."), diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp index 38c6bfe56a..2ded6a1d89 100644 --- a/src/qt/createwalletdialog.cpp +++ b/src/qt/createwalletdialog.cpp @@ -35,11 +35,28 @@ CreateWalletDialog::CreateWalletDialog(QWidget* parent) : } }); -#ifndef USE_SQLITE - ui->descriptor_checkbox->setToolTip(tr("Compiled without sqlite support (required for descriptor wallets)")); - ui->descriptor_checkbox->setEnabled(false); - ui->descriptor_checkbox->setChecked(false); -#endif + connect(ui->disable_privkeys_checkbox, &QCheckBox::toggled, [this](bool checked) { + // Disable the encrypt_wallet_checkbox when isDisablePrivateKeysChecked is + // set to true, enable it when isDisablePrivateKeysChecked is false. + ui->encrypt_wallet_checkbox->setEnabled(!checked); + + // Wallets without private keys start out blank + if (checked) { + ui->blank_wallet_checkbox->setChecked(true); + } + + // When the encrypt_wallet_checkbox is disabled, uncheck it. + if (!ui->encrypt_wallet_checkbox->isEnabled()) { + ui->encrypt_wallet_checkbox->setChecked(false); + } + }); + + #ifndef USE_SQLITE + ui->descriptor_checkbox->setToolTip(tr("Compiled without sqlite support (required for descriptor wallets)")); + ui->descriptor_checkbox->setEnabled(false); + ui->descriptor_checkbox->setChecked(false); + #endif + } CreateWalletDialog::~CreateWalletDialog() diff --git a/src/qt/forms/createwalletdialog.ui b/src/qt/forms/createwalletdialog.ui index b592140dd7..ea713e1abd 100644 --- a/src/qt/forms/createwalletdialog.ui +++ b/src/qt/forms/createwalletdialog.ui @@ -38,6 +38,9 @@ <height>24</height> </rect> </property> + <property name="placeholderText"> + <string>Wallet</string> + </property> </widget> <widget class="QLabel" name="label"> <property name="geometry"> @@ -68,17 +71,33 @@ <string>Encrypt Wallet</string> </property> <property name="checked"> - <bool>true</bool> + <bool>false</bool> + </property> + </widget> + <widget class="QLabel" name="advanced_options_label"> + <property name="geometry"> + <rect> + <x>20</x> + <y>90</y> + <width>130</width> + <height>21</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">font-weight:bold;</string> + </property> + <property name="text"> + <string>Advanced options</string> </property> </widget> <widget class="QCheckBox" name="disable_privkeys_checkbox"> <property name="enabled"> - <bool>false</bool> + <bool>true</bool> </property> <property name="geometry"> <rect> <x>20</x> - <y>80</y> + <y>115</y> <width>171</width> <height>22</height> </rect> @@ -94,8 +113,8 @@ <property name="geometry"> <rect> <x>20</x> - <y>110</y> - <width>171</width> + <y>135</y> + <width>220</width> <height>22</height> </rect> </property> @@ -110,7 +129,7 @@ <property name="geometry"> <rect> <x>20</x> - <y>140</y> + <y>155</y> <width>171</width> <height>22</height> </rect> @@ -128,6 +147,7 @@ <tabstop>encrypt_wallet_checkbox</tabstop> <tabstop>disable_privkeys_checkbox</tabstop> <tabstop>blank_wallet_checkbox</tabstop> + <tabstop>descriptor_checkbox</tabstop> </tabstops> <resources/> <connections> diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index d210faec03..139c8e161e 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -109,39 +109,13 @@ </widget> </item> <item row="3" column="0"> - <widget class="QLabel" name="label_berkeleyDBVersion"> - <property name="text"> - <string>Using BerkeleyDB version</string> - </property> - <property name="indent"> - <number>10</number> - </property> - </widget> - </item> - <item row="3" column="1" colspan="2"> - <widget class="QLabel" name="berkeleyDBVersion"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="4" column="0"> <widget class="QLabel" name="label_12"> <property name="text"> <string>Datadir</string> </property> </widget> </item> - <item row="4" column="1" colspan="2"> + <item row="3" column="1" colspan="2"> <widget class="QLabel" name="dataDir"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -163,14 +137,14 @@ </property> </widget> </item> - <item row="5" column="0"> + <item row="4" column="0"> <widget class="QLabel" name="label_11"> <property name="text"> <string>Blocksdir</string> </property> </widget> </item> - <item row="5" column="1" colspan="2"> + <item row="4" column="1" colspan="2"> <widget class="QLabel" name="blocksDir"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -192,14 +166,14 @@ </property> </widget> </item> - <item row="6" column="0"> + <item row="5" column="0"> <widget class="QLabel" name="label_13"> <property name="text"> <string>Startup time</string> </property> </widget> </item> - <item row="6" column="1" colspan="2"> + <item row="5" column="1" colspan="2"> <widget class="QLabel" name="startupTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -215,7 +189,7 @@ </property> </widget> </item> - <item row="7" column="0"> + <item row="6" column="0"> <widget class="QLabel" name="labelNetwork"> <property name="font"> <font> @@ -228,14 +202,14 @@ </property> </widget> </item> - <item row="8" column="0"> + <item row="7" column="0"> <widget class="QLabel" name="label_8"> <property name="text"> <string>Name</string> </property> </widget> </item> - <item row="8" column="1" colspan="2"> + <item row="7" column="1" colspan="2"> <widget class="QLabel" name="networkName"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -251,14 +225,14 @@ </property> </widget> </item> - <item row="9" column="0"> + <item row="8" column="0"> <widget class="QLabel" name="label_7"> <property name="text"> <string>Number of connections</string> </property> </widget> </item> - <item row="9" column="1" colspan="2"> + <item row="8" column="1" colspan="2"> <widget class="QLabel" name="numberOfConnections"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -274,7 +248,7 @@ </property> </widget> </item> - <item row="10" column="0"> + <item row="9" column="0"> <widget class="QLabel" name="label_10"> <property name="font"> <font> @@ -287,14 +261,14 @@ </property> </widget> </item> - <item row="11" column="0"> + <item row="10" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>Current block height</string> </property> </widget> </item> - <item row="11" column="1" colspan="2"> + <item row="10" column="1" colspan="2"> <widget class="QLabel" name="numberOfBlocks"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -310,14 +284,14 @@ </property> </widget> </item> - <item row="12" column="0"> + <item row="11" column="0"> <widget class="QLabel" name="labelLastBlockTime"> <property name="text"> <string>Last block time</string> </property> </widget> </item> - <item row="12" column="1" colspan="2"> + <item row="11" column="1" colspan="2"> <widget class="QLabel" name="lastBlockTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -333,7 +307,7 @@ </property> </widget> </item> - <item row="13" column="0"> + <item row="12" column="0"> <widget class="QLabel" name="labelMempoolTitle"> <property name="font"> <font> @@ -346,14 +320,14 @@ </property> </widget> </item> - <item row="14" column="0"> + <item row="13" column="0"> <widget class="QLabel" name="labelNumberOfTransactions"> <property name="text"> <string>Current number of transactions</string> </property> </widget> </item> - <item row="14" column="1"> + <item row="13" column="1"> <widget class="QLabel" name="mempoolNumberTxs"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -369,14 +343,14 @@ </property> </widget> </item> - <item row="15" column="0"> + <item row="14" column="0"> <widget class="QLabel" name="labelMemoryUsage"> <property name="text"> <string>Memory usage</string> </property> </widget> </item> - <item row="15" column="1"> + <item row="14" column="1"> <widget class="QLabel" name="mempoolSize"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -392,7 +366,7 @@ </property> </widget> </item> - <item row="13" column="2" rowspan="3"> + <item row="12" column="2" rowspan="3"> <layout class="QVBoxLayout" name="verticalLayoutDebugButton"> <property name="spacing"> <number>3</number> @@ -432,7 +406,7 @@ </item> </layout> </item> - <item row="16" column="0"> + <item row="15" column="0"> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts index 2a7d68f61d..ed59d98664 100644 --- a/src/qt/locale/bitcoin_bg.ts +++ b/src/qt/locale/bitcoin_bg.ts @@ -450,6 +450,22 @@ <translation>Актуално</translation> </message> <message> + <source>Close Wallet...</source> + <translation>Затвори Портфейла</translation> + </message> + <message> + <source>Close wallet</source> + <translation>Затвори портфейла</translation> + </message> + <message> + <source>Close All Wallets...</source> + <translation>Затвори Всички Портфейли...</translation> + </message> + <message> + <source>Close all wallets</source> + <translation>Затвори всички портфейли</translation> + </message> + <message> <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source> <translation>Покажи %1 помощно съобщение за да получиш лист с възможни Биткойн команди</translation> </message> @@ -466,6 +482,14 @@ <translation>Минимизирай</translation> </message> <message> + <source>Zoom</source> + <translation>Увеличи</translation> + </message> + <message> + <source>Main Window</source> + <translation>Главен Прозорец</translation> + </message> + <message> <source>%1 client</source> <translation>%1 клиент</translation> </message> @@ -2191,6 +2215,14 @@ </context> <context> <name>WalletController</name> + <message> + <source>Close wallet</source> + <translation>Затвори портфейла</translation> + </message> + <message> + <source>Close all wallets</source> + <translation>Затвори всички портфейли</translation> + </message> </context> <context> <name>WalletFrame</name> diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts index 2b4a283813..4faab2e7fb 100644 --- a/src/qt/locale/bitcoin_ca.ts +++ b/src/qt/locale/bitcoin_ca.ts @@ -23,7 +23,7 @@ </message> <message> <source>C&lose</source> - <translation>&Tanca</translation> + <translation>T&anca</translation> </message> <message> <source>Delete the currently selected address from the list</source> @@ -484,6 +484,22 @@ Només és possible firmar amb adreces del tipus "legacy".</translation> <translation>Actualitzat</translation> </message> <message> + <source>&Load PSBT from file...</source> + <translation>&Carrega el PSBT des del fitxer ...</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction</source> + <translation>Carrega la transacció Bitcoin signada parcialment</translation> + </message> + <message> + <source>Load PSBT from clipboard...</source> + <translation>Carrega PSBT des del porta-retalls ...</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction from clipboard</source> + <translation>Carrega la transacció de Bitcoin signada parcialment des del porta-retalls</translation> + </message> + <message> <source>Node window</source> <translation>Finestra node</translation> </message> @@ -520,10 +536,26 @@ Només és possible firmar amb adreces del tipus "legacy".</translation> <translation>Tanca la cartera</translation> </message> <message> + <source>Close All Wallets...</source> + <translation>Tanca totes les carteres ...</translation> + </message> + <message> + <source>Close all wallets</source> + <translation>Tanqueu totes les carteres</translation> + </message> + <message> <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source> <translation>Mostra el missatge d'ajuda del %1 per obtenir una llista amb les possibles opcions de línia d'ordres de Bitcoin</translation> </message> <message> + <source>&Mask values</source> + <translation>&Emmascara els valors</translation> + </message> + <message> + <source>Mask the values in the Overview tab</source> + <translation>Emmascara els valors en la pestanya Visió general</translation> + </message> + <message> <source>default wallet</source> <translation>cartera predeterminada</translation> </message> @@ -631,7 +663,15 @@ Només és possible firmar amb adreces del tipus "legacy".</translation> <source>Wallet is <b>encrypted</b> and currently <b>locked</b></source> <translation>La cartera està <b>encriptada</b> i actualment <b>blocada</b></translation> </message> - </context> + <message> + <source>Original message:</source> + <translation>Missatge original:</translation> + </message> + <message> + <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source> + <translation>S'ha produït un error fatal. %1 ja no pot continuar amb seguretat i sortirà.</translation> + </message> +</context> <context> <name>CoinControlDialog</name> <message> @@ -834,6 +874,14 @@ Això és ideal per a carteres de mode només lectura.</translation> <translation>Fes cartera en blanc</translation> </message> <message> + <source>Use descriptors for scriptPubKey management</source> + <translation>Utilitzeu descriptors per a la gestió de scriptPubKey</translation> + </message> + <message> + <source>Descriptor Wallet</source> + <translation>Cartera del descriptor</translation> + </message> + <message> <source>Create</source> <translation>Crear</translation> </message> @@ -1310,6 +1358,14 @@ Això és ideal per a carteres de mode només lectura.</translation> <translation>Si voleu mostrar les funcions de control de monedes o no.</translation> </message> <message> + <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source> + <translation>Connecteu-vos a la xarxa Bitcoin mitjançant un servidor intermediari SOCKS5 separat per als serveis de ceba Tor.</translation> + </message> + <message> + <source>Use separate SOCKS&5 proxy to reach peers via Tor onion services:</source> + <translation>Utilitzeu el servidor intermediari SOCKS&5 per arribar als peers mitjançant els serveis d'onion de Tor:</translation> + </message> + <message> <source>&Third party transaction URLs</source> <translation>URL de transaccions de tercers</translation> </message> @@ -1444,10 +1500,34 @@ Això és ideal per a carteres de mode només lectura.</translation> <source>Current total balance in watch-only addresses</source> <translation>Balanç total actual en adreces de només lectura</translation> </message> - </context> + <message> + <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</source> + <translation>El mode de privadesa està activat a la pestanya d'Overview. Per desenmascarar els valors, desmarqueu Configuració-> Valors de màscara.</translation> + </message> +</context> <context> <name>PSBTOperationsDialog</name> <message> + <source>Dialog</source> + <translation>Diàleg</translation> + </message> + <message> + <source>Sign Tx</source> + <translation>Signa Tx</translation> + </message> + <message> + <source>Broadcast Tx</source> + <translation>Emet Tx</translation> + </message> + <message> + <source>Copy to Clipboard</source> + <translation>Còpia al Clipboard</translation> + </message> + <message> + <source>Save...</source> + <translation>Desa...</translation> + </message> + <message> <source>Total Amount</source> <translation>Import total</translation> </message> @@ -3168,6 +3248,10 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1 <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source> <translation>Si tanqueu la cartera durant massa temps, es pot haver de tornar a sincronitzar tota la cadena si teniu el sistema de poda habilitat.</translation> </message> + <message> + <source>Close all wallets</source> + <translation>Tanqueu totes les carteres</translation> + </message> </context> <context> <name>WalletFrame</name> diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts index 919a62664b..1ba16439a7 100644 --- a/src/qt/locale/bitcoin_cs.ts +++ b/src/qt/locale/bitcoin_cs.ts @@ -43,7 +43,7 @@ </message> <message> <source>&Delete</source> - <translation>S&maž</translation> + <translation>&Smaž</translation> </message> <message> <source>Choose the address to send coins to</source> @@ -70,6 +70,11 @@ <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. +Signing is only possible with addresses of the type 'legacy'.</source> + <translation>Tohle jsou tvé bitcoinové adresy pro přijmaní plateb. Použij "Vytvoř novou přijimací adresu" pro vytvoření nových adres. Přihlašování je povoleno jen s adresami typu "Legacy"</translation> + </message> + <message> <source>&Copy Address</source> <translation>&Kopíruj adresu</translation> </message> @@ -271,7 +276,7 @@ </message> <message> <source>Browse transaction history</source> - <translation>Procházej historii transakcí</translation> + <translation>Procházet historii transakcí</translation> </message> <message> <source>E&xit</source> diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index a0faa91255..659a29bc29 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -1147,7 +1147,7 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation> </message> <message> <source>Opening Wallet <b>%1</b>...</source> - <translation>Öffne Wallet<b>%1</b> ...</translation> + <translation>Öffne Wallet <b>%1</b> ...</translation> </message> </context> <context> @@ -3572,6 +3572,10 @@ Gehen Sie zu Datei > Öffnen Sie die Brieftasche, um eine Brieftasche zu lade <translation>Wenn sie %s nützlich finden, sind Helfer sehr gern gesehen. Besuchen Sie %s um mehr über das Softwareprojekt zu erfahren.</translation> </message> <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source> + <translation>SQLiteDatabase: Konnte das Statement zum Abholen der Anwendungs-ID %s nicht vorbereiten.</translation> + </message> + <message> <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> <translation>Die Block-Datenbank enthält einen Block, der in der Zukunft auftaucht. Dies kann daran liegen, dass die Systemzeit Ihres Computers falsch eingestellt ist. Stellen Sie die Block-Datenbank nur wieder her, wenn Sie sich sicher sind, dass Ihre Systemzeit korrekt eingestellt ist.</translation> </message> @@ -3677,6 +3681,10 @@ Gehen Sie zu Datei > Öffnen Sie die Brieftasche, um eine Brieftasche zu lade <translation>Fehler: Wallet konnte während der Initialisierung nicht erneut gescannt werden.</translation> </message> <message> + <source>Failed to verify database</source> + <translation>Verifizierung der Datenbank fehlgeschlagen</translation> + </message> + <message> <source>Importing...</source> <translation>Importiere...</translation> </message> @@ -3705,6 +3713,15 @@ Gehen Sie zu Datei > Öffnen Sie die Brieftasche, um eine Brieftasche zu lade <translation>Ungültiger Betrag für -fallbackfee=<amount>: '%s'</translation> </message> <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>Datenbank konnte nicht gelesen werden +Verifikations-Error: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>SQLiteDatabase: Unerwartete Anwendungs-ID. %u statt %u erhalten.</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation>Angegebener Blöcke-Ordner "%s" existiert nicht.</translation> </message> diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index ca9df98969..c55cc65b63 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -1108,6 +1108,11 @@ Signing is only possible with addresses of the type 'legacy'.</source> <source>Create</source> <translation type="unfinished"></translation> </message> + <message> + <location line="+20"/> + <source>Compiled without sqlite support (required for descriptor wallets)</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>EditAddressDialog</name> @@ -3991,7 +3996,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satos <context> <name>TransactionTableModel</name> <message> - <location filename="../transactiontablemodel.cpp" line="+221"/> + <location filename="../transactiontablemodel.cpp" line="+251"/> <source>Date</source> <translation type="unfinished">Date</translation> </message> @@ -4723,7 +4728,7 @@ Go to File > Open Wallet to load a wallet. <translation>Error loading block database</translation> </message> <message> - <location line="+2"/> + <location line="+1"/> <source>Error opening block database</source> <translation>Error opening block database</translation> </message> @@ -4744,6 +4749,11 @@ Go to File > Open Wallet to load a wallet. </message> <message> <location line="+2"/> + <source>Ignoring duplicate -wallet %s.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> <source>Importing...</source> <translation type="unfinished"></translation> </message> @@ -4968,7 +4978,7 @@ Go to File > Open Wallet to load a wallet. <translation type="unfinished"></translation> </message> <message> - <location line="+12"/> + <location line="+11"/> <source>Error reading from database, shutting down.</source> <translation type="unfinished"></translation> </message> @@ -4993,7 +5003,7 @@ Go to File > Open Wallet to load a wallet. <translation type="unfinished"></translation> </message> <message> - <location line="+5"/> + <location line="+6"/> <source>Invalid -onion address or hostname: '%s'</source> <translation type="unfinished"></translation> </message> @@ -5134,12 +5144,7 @@ Go to File > Open Wallet to load a wallet. <translation type="unfinished"></translation> </message> <message> - <location line="+23"/> - <source>Error loading wallet %s. Duplicate -wallet filename specified.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+49"/> + <location line="+72"/> <source>Starting network threads...</source> <translation type="unfinished"></translation> </message> diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index 3a0a8608f6..0b32703779 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -70,6 +70,12 @@ <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. +Signing is only possible with addresses of the type 'legacy'.</source> + <translation>Estas son sus direcciones Bitcoin para la recepción de pagos. Use el botón 'Crear una nueva dirección para recepción' en la pestaña Recibir para crear nuevas direcciones. +Firmar solo es posible con correos del tipo Legacy.</translation> + </message> + <message> <source>&Copy Address</source> <translation>&Copiar dirección</translation> </message> @@ -478,6 +484,22 @@ <translation>Actualizado</translation> </message> <message> + <source>&Load PSBT from file...</source> + <translation>&Cargar PSBT desde el archivo...</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction</source> + <translation>Cargar una transacción de Bitcoin parcialmente firmada</translation> + </message> + <message> + <source>Load PSBT from clipboard...</source> + <translation>Cargar PSBT desde el portapapeles...</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction from clipboard</source> + <translation>Cargar una transacción de Bitcoin parcialmente firmada desde el Portapapeles</translation> + </message> + <message> <source>Node window</source> <translation>Ventana de nodo</translation> </message> @@ -526,6 +548,14 @@ <translation>Muestra el mensaje de ayuda %1 para obtener una lista con posibles opciones de línea de comandos de Bitcoin.</translation> </message> <message> + <source>&Mask values</source> + <translation>&Esconder valores</translation> + </message> + <message> + <source>Mask the values in the Overview tab</source> + <translation>Esconder los valores de la ventana de previsualización</translation> + </message> + <message> <source>default wallet</source> <translation>Cartera predeterminada</translation> </message> @@ -637,7 +667,11 @@ <source>Original message:</source> <translation>Mensaje original:</translation> </message> - </context> + <message> + <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source> + <translation>Ha ocurrido un error fatal. %1 no puede seguir seguro y se cerrará.</translation> + </message> +</context> <context> <name>CoinControlDialog</name> <message> @@ -839,6 +873,14 @@ <translation>Crear monedero vacío</translation> </message> <message> + <source>Use descriptors for scriptPubKey management</source> + <translation>Use descriptores para la gestión de scriptPubKey</translation> + </message> + <message> + <source>Descriptor Wallet</source> + <translation>Descriptor del monedero</translation> + </message> + <message> <source>Create</source> <translation>Crear</translation> </message> @@ -1315,6 +1357,14 @@ <translation>Mostrar o no características de control de moneda</translation> </message> <message> + <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source> + <translation>Conéctese a la red de Bitcoin a través de un proxy SOCKS5 separado para los servicios Tor ocultos.</translation> + </message> + <message> + <source>Use separate SOCKS&5 proxy to reach peers via Tor onion services:</source> + <translation>Usar proxy SOCKS&5 para alcanzar nodos via servicios ocultos Tor:</translation> + </message> + <message> <source>&Third party transaction URLs</source> <translation>URLs de transacciones de terceros</translation> </message> @@ -1449,7 +1499,11 @@ <source>Current total balance in watch-only addresses</source> <translation>Saldo total actual en direcciones de solo-ver</translation> </message> - </context> + <message> + <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</source> + <translation>Modo de privacidad activado para la pestaña de visión general. Para desenmascarar los valores, desmarcar los valores de Configuración->Máscara.</translation> + </message> +</context> <context> <name>PSBTOperationsDialog</name> <message> @@ -1477,10 +1531,66 @@ <translation>Cerrar</translation> </message> <message> + <source>Failed to load transaction: %1</source> + <translation>Error en la carga de la transacción: %1</translation> + </message> + <message> + <source>Failed to sign transaction: %1</source> + <translation>Error en la firma de la transacción: %1</translation> + </message> + <message> + <source>Could not sign any more inputs.</source> + <translation>No se han podido firmar más entradas.</translation> + </message> + <message> + <source>Signed %1 inputs, but more signatures are still required.</source> + <translation>Se han firmado %1 entradas, pero aún se requieren más firmas.</translation> + </message> + <message> + <source>Signed transaction successfully. Transaction is ready to broadcast.</source> + <translation>Se ha firmado correctamente. La transacción está lista para difundirse.</translation> + </message> + <message> + <source>Unknown error processing transaction.</source> + <translation>Error desconocido al procesar la transacción.</translation> + </message> + <message> + <source>Transaction broadcast successfully! Transaction ID: %1</source> + <translation>¡La transacción se ha difundido correctamente! Código ID de la transacción: %1</translation> + </message> + <message> + <source>Transaction broadcast failed: %1</source> + <translation>Ha habido un error en la difusión de la transacción: %1</translation> + </message> + <message> <source>PSBT copied to clipboard.</source> <translation>PSBT copiado al portapapeles</translation> </message> <message> + <source>Save Transaction Data</source> + <translation>Guardar datos de la transacción</translation> + </message> + <message> + <source>Partially Signed Transaction (Binary) (*.psbt)</source> + <translation>Transacción firmada de manera parcial (Binaria) (*.psbt)</translation> + </message> + <message> + <source>PSBT saved to disk.</source> + <translation>PSBT guardado en la memoria.</translation> + </message> + <message> + <source> * Sends %1 to %2</source> + <translation>* Envia %1 a %2</translation> + </message> + <message> + <source>Unable to calculate transaction fee or total transaction amount.</source> + <translation>No se ha podido calcular la comisión por transacción o la totalidad de la cantidad de la transacción.</translation> + </message> + <message> + <source>Pays transaction fee: </source> + <translation>Pagar comisión de transacción:</translation> + </message> + <message> <source>Total Amount</source> <translation>Monto total</translation> </message> @@ -1488,7 +1598,35 @@ <source>or</source> <translation>o</translation> </message> - </context> + <message> + <source>Transaction has %1 unsigned inputs.</source> + <translation>La transacción tiene %1 entradas no firmadas.</translation> + </message> + <message> + <source>Transaction is missing some information about inputs.</source> + <translation>Le falta alguna información sobre entradas a la transacción.</translation> + </message> + <message> + <source>Transaction still needs signature(s).</source> + <translation>La transacción aún necesita firma(s).</translation> + </message> + <message> + <source>(But this wallet cannot sign transactions.)</source> + <translation>(Este monedero no puede firmar transacciones.)</translation> + </message> + <message> + <source>(But this wallet does not have the right keys.)</source> + <translation>(Este monedero no tiene las claves adecuadas.)</translation> + </message> + <message> + <source>Transaction is fully signed and ready for broadcast.</source> + <translation>La transacción se ha firmado correctamente y está lista para difundirse.</translation> + </message> + <message> + <source>Transaction status is unknown.</source> + <translation>El estatus de la transacción es desconocido.</translation> + </message> +</context> <context> <name>PaymentServer</name> <message> @@ -1832,6 +1970,10 @@ <translation>Ventana de nodo</translation> </message> <message> + <source>Current block height</source> + <translation>Altura del bloque actual</translation> + </message> + <message> <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source> <translation>Abrir el archivo de depuración %1 desde el directorio de datos actual. Puede tardar unos segundos para ficheros de gran tamaño.</translation> </message> @@ -1844,6 +1986,10 @@ <translation>Aumentar el tamaño de la fuente</translation> </message> <message> + <source>Permissions</source> + <translation>Permisos</translation> + </message> + <message> <source>Services</source> <translation>Servicios</translation> </message> @@ -2098,10 +2244,22 @@ <source>Could not unlock wallet.</source> <translation>No se pudo desbloquear el monedero.</translation> </message> - </context> + <message> + <source>Could not generate new %1 address</source> + <translation>No se ha podido generar una nueva dirección %1</translation> + </message> +</context> <context> <name>ReceiveRequestDialog</name> <message> + <source>Request payment to ...</source> + <translation>Solicitar pago a...</translation> + </message> + <message> + <source>Address:</source> + <translation>Dirección:</translation> + </message> + <message> <source>Amount:</source> <translation>Cantidad:</translation> </message> @@ -2380,6 +2538,22 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis <translation>¿Seguro que quiere enviar?</translation> </message> <message> + <source>Create Unsigned</source> + <translation>Crear sin firmar</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>Guardar datos de la transacción</translation> + </message> + <message> + <source>Partially Signed Transaction (Binary) (*.psbt)</source> + <translation>Transacción firmaa de manera parcial (Binaria) (*.psbt)</translation> + </message> + <message> + <source>PSBT saved</source> + <translation>PSBT guardado </translation> + </message> + <message> <source>or</source> <translation>o</translation> </message> @@ -3205,10 +3379,22 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis <source>Close all wallets</source> <translation>Cerrar todas las carteras</translation> </message> - </context> + <message> + <source>Are you sure you wish to close all wallets?</source> + <translation>¿Está seguro de que desea cerrar todos los monederos?</translation> + </message> +</context> <context> <name>WalletFrame</name> <message> + <source>No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR -</source> + <translation>No se ha cargado ningún monedero. +Vaya a Archivo> Abrir monedero para cargar un monedero. +- O -</translation> + </message> + <message> <source>Create a new wallet</source> <translation>Crear monedero nuevo</translation> </message> @@ -3287,6 +3473,22 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis <translation>Error</translation> </message> <message> + <source>Load Transaction Data</source> + <translation>Cargar datos de la transacción</translation> + </message> + <message> + <source>Partially Signed Transaction (*.psbt)</source> + <translation>Transacción firmada de manera parcial (*.psbt)</translation> + </message> + <message> + <source>PSBT file must be smaller than 100 MiB</source> + <translation>El archivo PSBT debe ser más pequeño de 100 MiB</translation> + </message> + <message> + <source>Unable to decode PSBT</source> + <translation>Imposible descodificar PSBT</translation> + </message> + <message> <source>Backup Wallet</source> <translation>Respaldar monedero</translation> </message> @@ -3466,6 +3668,10 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis <translation>Fallo al escanear el monedero durante la inicialización</translation> </message> <message> + <source>Failed to verify database</source> + <translation>No se ha podido verificar la base de datos</translation> + </message> + <message> <source>Importing...</source> <translation>Importando...</translation> </message> @@ -3590,6 +3796,14 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis <translation>Necesita reconstruir la base de datos utilizando -reindex para volver al modo sin recorte. Esto volverá a descargar toda la cadena de bloques</translation> </message> <message> + <source>A fatal internal error occurred, see debug.log for details</source> + <translation>Ha ocurrido un error interno grave. Consulte debug.log para más detalles.</translation> + </message> + <message> + <source>Disk space is too low!</source> + <translation>¡El espacio en el disco es demasiado bajo!</translation> + </message> + <message> <source>Error reading from database, shutting down.</source> <translation>Error al leer la base de datos, cerrando la aplicación.</translation> </message> @@ -3622,6 +3836,10 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis <translation>Necesita especificar un puerto con -whitebind: '%s'</translation> </message> <message> + <source>No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>.</source> + <translation>No se ha especificado un servidor de proxy. Use -proxy=<ip>o -proxy=<ip:port>.</translation> + </message> + <message> <source>Prune mode is incompatible with -blockfilterindex.</source> <translation>El modo de poda es incompatible con -blockfilterindex</translation> </message> diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts index b1bc8e87cb..c045a23262 100644 --- a/src/qt/locale/bitcoin_es_MX.ts +++ b/src/qt/locale/bitcoin_es_MX.ts @@ -70,6 +70,12 @@ <translation>Estas son tus direcciones de Bitcoin para enviar pagos. Siempre revisa el monto y la dirección de envío antes de enviar monedas.</translation> </message> <message> + <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses. +Signing is only possible with addresses of the type 'legacy'.</source> + <translation>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses. +Signing is only possible with addresses of the type 'legacy'.</translation> + </message> + <message> <source>&Copy Address</source> <translation>&Copiar dirección</translation> </message> @@ -436,6 +442,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <source>&Command-line options</source> <translation>opciones de la &Linea de comandos</translation> </message> + <message numerus="yes"> + <source>%n active connection(s) to Bitcoin network</source> + <translation><numerusform>%n active connection to Bitcoin network</numerusform><numerusform>%n active connections to Bitcoin network</numerusform></translation> + </message> <message> <source>Indexing blocks on disk...</source> <translation>Indexando bloques en el disco...</translation> @@ -444,6 +454,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <source>Processing blocks on disk...</source> <translation>Procesando bloques en el disco...</translation> </message> + <message numerus="yes"> + <source>Processed %n block(s) of transaction history.</source> + <translation><numerusform>Processed %n block of transaction history.</numerusform><numerusform>Processed %n blocks of transaction history.</numerusform></translation> + </message> + <message> + <source>%1 behind</source> + <translation>%1 behind</translation> + </message> + <message> + <source>Last received block was generated %1 ago.</source> + <translation>Last received block was generated %1 ago.</translation> + </message> <message> <source>Transactions after this will not yet be visible.</source> <translation>Las transacciones después de esto todavía no serán visibles.</translation> @@ -465,6 +487,42 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Actualizado al dia </translation> </message> <message> + <source>&Load PSBT from file...</source> + <translation>&Load PSBT from file...</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction</source> + <translation>Load Partially Signed Bitcoin Transaction</translation> + </message> + <message> + <source>Load PSBT from clipboard...</source> + <translation>Load PSBT from clipboard...</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction from clipboard</source> + <translation>Load Partially Signed Bitcoin Transaction from clipboard</translation> + </message> + <message> + <source>Node window</source> + <translation>Node window</translation> + </message> + <message> + <source>Open node debugging and diagnostic console</source> + <translation>Open node debugging and diagnostic console</translation> + </message> + <message> + <source>&Sending addresses</source> + <translation>&Sending addresses</translation> + </message> + <message> + <source>&Receiving addresses</source> + <translation>&Receiving addresses</translation> + </message> + <message> + <source>Open a bitcoin: URI</source> + <translation>Open a bitcoin: URI</translation> + </message> + <message> <source>Open Wallet</source> <translation>Abrir Cartera</translation> </message> @@ -481,6 +539,26 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Cerrar cartera</translation> </message> <message> + <source>Close All Wallets...</source> + <translation>Close All Wallets...</translation> + </message> + <message> + <source>Close all wallets</source> + <translation>Close all wallets</translation> + </message> + <message> + <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source> + <translation>Show the %1 help message to get a list with possible Bitcoin command-line options</translation> + </message> + <message> + <source>&Mask values</source> + <translation>&Mask values</translation> + </message> + <message> + <source>Mask the values in the Overview tab</source> + <translation>Mask the values in the Overview tab</translation> + </message> + <message> <source>default wallet</source> <translation>cartera predeterminada</translation> </message> @@ -497,10 +575,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Minimizar</translation> </message> <message> + <source>Zoom</source> + <translation>Zoom</translation> + </message> + <message> <source>Main Window</source> <translation>Ventana Principal</translation> </message> <message> + <source>%1 client</source> + <translation>%1 client</translation> + </message> + <message> <source>Connecting to peers...</source> <translation>Conectando con los compañeros...</translation> </message> @@ -523,6 +609,36 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) </translation> </message> <message> + <source>Amount: %1 +</source> + <translation>Amount: %1 +</translation> + </message> + <message> + <source>Wallet: %1 +</source> + <translation>Wallet: %1 +</translation> + </message> + <message> + <source>Type: %1 +</source> + <translation>Type: %1 +</translation> + </message> + <message> + <source>Label: %1 +</source> + <translation>Label: %1 +</translation> + </message> + <message> + <source>Address: %1 +</source> + <translation>Address: %1 +</translation> + </message> + <message> <source>Sent transaction</source> <translation>Enviar Transacción</translation> </message> @@ -531,6 +647,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Transacción entrante</translation> </message> <message> + <source>HD key generation is <b>enabled</b></source> + <translation>HD key generation is <b>enabled</b></translation> + </message> + <message> + <source>HD key generation is <b>disabled</b></source> + <translation>HD key generation is <b>disabled</b></translation> + </message> + <message> + <source>Private key <b>disabled</b></source> + <translation>Private key <b>disabled</b></translation> + </message> + <message> <source>Wallet is <b>encrypted</b> and currently <b>unlocked</b></source> <translation>La cartera esta <b>encriptada</b> y <b>desbloqueada</b> actualmente </translation> </message> @@ -538,7 +666,15 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <source>Wallet is <b>encrypted</b> and currently <b>locked</b></source> <translation>La cartera esta <b>encriptada</b> y <b>bloqueada</b> actualmente </translation> </message> - </context> + <message> + <source>Original message:</source> + <translation>Original message:</translation> + </message> + <message> + <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source> + <translation>A fatal error occurred. %1 can no longer continue safely and will quit.</translation> + </message> +</context> <context> <name>CoinControlDialog</name> <message> @@ -626,6 +762,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Copiar identificación de la transacción. </translation> </message> <message> + <source>Lock unspent</source> + <translation>Lock unspent</translation> + </message> + <message> + <source>Unlock unspent</source> + <translation>Unlock unspent</translation> + </message> + <message> <source>Copy quantity</source> <translation>Copiar cantidad</translation> </message> @@ -642,10 +786,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Copiar bytes</translation> </message> <message> + <source>Copy dust</source> + <translation>Copy dust</translation> + </message> + <message> <source>Copy change</source> <translation>Copiar cambio</translation> </message> <message> + <source>(%1 locked)</source> + <translation>(%1 locked)</translation> + </message> + <message> <source>yes</source> <translation>si</translation> </message> @@ -658,10 +810,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Esta capa se vuelve roja si algún destinatario recibe un monto menor al actual limite del remanente monetario </translation> </message> <message> + <source>Can vary +/- %1 satoshi(s) per input.</source> + <translation>Can vary +/- %1 satoshi(s) per input.</translation> + </message> + <message> <source>(no label)</source> <translation>(sin etiqueta)</translation> </message> <message> + <source>change from %1 (%2)</source> + <translation>change from %1 (%2)</translation> + </message> + <message> <source>(change)</source> <translation>cambio</translation> </message> @@ -669,6 +829,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <context> <name>CreateWalletActivity</name> <message> + <source>Creating Wallet <b>%1</b>...</source> + <translation>Creating Wallet <b>%1</b>...</translation> + </message> + <message> <source>Create wallet failed</source> <translation>La creación de la cartera falló</translation> </message> @@ -704,6 +868,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Desactivar las claves privadas</translation> </message> <message> + <source>Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time.</source> + <translation>Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time.</translation> + </message> + <message> + <source>Make Blank Wallet</source> + <translation>Make Blank Wallet</translation> + </message> + <message> + <source>Use descriptors for scriptPubKey management</source> + <translation>Use descriptors for scriptPubKey management</translation> + </message> + <message> + <source>Descriptor Wallet</source> + <translation>Descriptor Wallet</translation> + </message> + <message> <source>Create</source> <translation>Crear</translation> </message> @@ -743,6 +923,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Editar dirección de envío</translation> </message> <message> + <source>The entered address "%1" is not a valid Bitcoin address.</source> + <translation>The entered address "%1" is not a valid Bitcoin address.</translation> + </message> + <message> + <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source> + <translation>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</translation> + </message> + <message> + <source>The entered address "%1" is already in the address book with label "%2".</source> + <translation>The entered address "%1" is already in the address book with label "%2".</translation> + </message> + <message> <source>Could not unlock wallet.</source> <translation>No se puede desbloquear la cartera</translation> </message> @@ -762,6 +954,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>nombre</translation> </message> <message> + <source>Directory already exists. Add %1 if you intend to create a new directory here.</source> + <translation>Directory already exists. Add %1 if you intend to create a new directory here.</translation> + </message> + <message> <source>Path already exists, and is not a directory.</source> <translation>El camino ya existe, y no es un directorio.</translation> </message> @@ -777,6 +973,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>versión</translation> </message> <message> + <source>About %1</source> + <translation>About %1</translation> + </message> + <message> <source>Command-line options</source> <translation>opciones de la Linea de comandos</translation> </message> @@ -788,6 +988,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Bienvenido</translation> </message> <message> + <source>Welcome to %1.</source> + <translation>Welcome to %1.</translation> + </message> + <message> + <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source> + <translation>As this is the first time the program is launched, you can choose where %1 will store its data.</translation> + </message> + <message> + <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source> + <translation>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</translation> + </message> + <message> <source>Reverting this setting requires re-downloading the entire blockchain. It is faster to download the full chain first and prune it later. Disables some advanced features.</source> <translation>Revertir esta configuración requiere descargar nuevamente la cadena de bloques en su totalidad. es mas eficaz descargar la cadena de bloques completa y después reducirla. Desabilitará algunas funciones avanzadas.</translation> </message> @@ -796,6 +1008,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>La sincronización inicial es muy demandante, por lo que algunos problemas en su equipo de computo que no hayan sido detectados pueden verse reflejados. Cada vez que corra al %1, continuará descargando donde se le dejó.</translation> </message> <message> + <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source> + <translation>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</translation> + </message> + <message> <source>Use the default data directory</source> <translation>Usar el directorio de datos predeterminado</translation> </message> @@ -808,14 +1024,46 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Bitcoin</translation> </message> <message> + <source>Discard blocks after verification, except most recent %1 GB (prune)</source> + <translation>Discard blocks after verification, except most recent %1 GB (prune)</translation> + </message> + <message> + <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source> + <translation>At least %1 GB of data will be stored in this directory, and it will grow over time.</translation> + </message> + <message> + <source>Approximately %1 GB of data will be stored in this directory.</source> + <translation>Approximately %1 GB of data will be stored in this directory.</translation> + </message> + <message> + <source>%1 will download and store a copy of the Bitcoin block chain.</source> + <translation>%1 will download and store a copy of the Bitcoin block chain.</translation> + </message> + <message> <source>The wallet will also be stored in this directory.</source> <translation>La cartera también se almacenará en este directorio.</translation> </message> <message> + <source>Error: Specified data directory "%1" cannot be created.</source> + <translation>Error: Specified data directory "%1" cannot be created.</translation> + </message> + <message> <source>Error</source> <translation>Error</translation> </message> - </context> + <message numerus="yes"> + <source>%n GB of free space available</source> + <translation><numerusform>%n GB of free space available</numerusform><numerusform>%n GB of free space available</numerusform></translation> + </message> + <message numerus="yes"> + <source>(of %n GB needed)</source> + <translation><numerusform>(of %n GB needed)</numerusform><numerusform>(of %n GB needed)</numerusform></translation> + </message> + <message numerus="yes"> + <source>(%n GB needed for full chain)</source> + <translation><numerusform>(%n GB needed for full chain)</numerusform><numerusform>(%n GB needed for full chain)</numerusform></translation> + </message> +</context> <context> <name>ModalOverlay</name> <message> @@ -839,6 +1087,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Desconocido...</translation> </message> <message> + <source>Last block time</source> + <translation>Last block time</translation> + </message> + <message> <source>Progress</source> <translation>Progreso </translation> </message> @@ -862,7 +1114,15 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <source>Esc</source> <translation>Esc</translation> </message> - </context> + <message> + <source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source> + <translation>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</translation> + </message> + <message> + <source>Unknown. Syncing Headers (%1, %2%)...</source> + <translation>Unknown. Syncing Headers (%1, %2%)...</translation> + </message> +</context> <context> <name>OpenURIDialog</name> <message> @@ -881,10 +1141,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Abrir la cartera falló</translation> </message> <message> + <source>Open wallet warning</source> + <translation>Open wallet warning</translation> + </message> + <message> <source>default wallet</source> <translation>cartera predeterminada</translation> </message> - </context> + <message> + <source>Opening Wallet <b>%1</b>...</source> + <translation>Opening Wallet <b>%1</b>...</translation> + </message> +</context> <context> <name>OptionsDialog</name> <message> @@ -892,18 +1160,106 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Opciones</translation> </message> <message> + <source>&Main</source> + <translation>&Main</translation> + </message> + <message> + <source>Automatically start %1 after logging in to the system.</source> + <translation>Automatically start %1 after logging in to the system.</translation> + </message> + <message> + <source>&Start %1 on system login</source> + <translation>&Start %1 on system login</translation> + </message> + <message> + <source>Size of &database cache</source> + <translation>Size of &database cache</translation> + </message> + <message> + <source>Number of script &verification threads</source> + <translation>Number of script &verification threads</translation> + </message> + <message> + <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> + <translation>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</translation> + </message> + <message> + <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source> + <translation>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</translation> + </message> + <message> + <source>Hide the icon from the system tray.</source> + <translation>Hide the icon from the system tray.</translation> + </message> + <message> + <source>&Hide tray icon</source> + <translation>&Hide tray icon</translation> + </message> + <message> <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source> <translation>Minimizar en lugar de salir de la aplicación cuando la ventana se cierra. Cuando esta opción está activada, la aplicación se cerrará sólo después de seleccionar Salir en el menú.</translation> </message> <message> + <source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source> + <translation>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</translation> + </message> + <message> + <source>Open the %1 configuration file from the working directory.</source> + <translation>Open the %1 configuration file from the working directory.</translation> + </message> + <message> <source>Open Configuration File</source> <translation>Abrir Configuración de Archivo</translation> </message> <message> + <source>Reset all client options to default.</source> + <translation>Reset all client options to default.</translation> + </message> + <message> + <source>&Reset Options</source> + <translation>&Reset Options</translation> + </message> + <message> + <source>&Network</source> + <translation>&Network</translation> + </message> + <message> + <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source> + <translation>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</translation> + </message> + <message> + <source>Prune &block storage to</source> + <translation>Prune &block storage to</translation> + </message> + <message> + <source>GB</source> + <translation>GB</translation> + </message> + <message> + <source>Reverting this setting requires re-downloading the entire blockchain.</source> + <translation>Reverting this setting requires re-downloading the entire blockchain.</translation> + </message> + <message> + <source>MiB</source> + <translation>MiB</translation> + </message> + <message> + <source>(0 = auto, <0 = leave that many cores free)</source> + <translation>(0 = auto, <0 = leave that many cores free)</translation> + </message> + <message> <source>W&allet</source> <translation>Cartera</translation> </message> <message> + <source>Expert</source> + <translation>Expert</translation> + </message> + <message> + <source>Enable coin &control features</source> + <translation>Enable coin &control features</translation> + </message> + <message> <source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source> <translation>Si usted desactiva el gasto de cambio no confirmado, el cambio de una transacción no puede ser utilizado hasta que esa transacción tenga al menos una confirmación. Esto también afecta la manera en que se calcula su saldo.</translation> </message> @@ -912,30 +1268,166 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>&Gastar el cambio no confirmado</translation> </message> <message> + <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source> + <translation>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</translation> + </message> + <message> + <source>Map port using &UPnP</source> + <translation>Map port using &UPnP</translation> + </message> + <message> <source>Accept connections from outside.</source> <translation>Aceptar las conexiones del exterior.</translation> </message> <message> + <source>Allow incomin&g connections</source> + <translation>Allow incomin&g connections</translation> + </message> + <message> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation>Connect to the Bitcoin network through a SOCKS5 proxy.</translation> + </message> + <message> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation>&Connect through SOCKS5 proxy (default proxy):</translation> + </message> + <message> + <source>Proxy &IP:</source> + <translation>Proxy &IP:</translation> + </message> + <message> + <source>&Port:</source> + <translation>&Port:</translation> + </message> + <message> + <source>Port of the proxy (e.g. 9050)</source> + <translation>Port of the proxy (e.g. 9050)</translation> + </message> + <message> + <source>Used for reaching peers via:</source> + <translation>Used for reaching peers via:</translation> + </message> + <message> + <source>IPv4</source> + <translation>IPv4</translation> + </message> + <message> + <source>IPv6</source> + <translation>IPv6</translation> + </message> + <message> + <source>Tor</source> + <translation>Tor</translation> + </message> + <message> <source>&Window</source> <translation>&Ventana</translation> </message> <message> + <source>Show only a tray icon after minimizing the window.</source> + <translation>Show only a tray icon after minimizing the window.</translation> + </message> + <message> + <source>&Minimize to the tray instead of the taskbar</source> + <translation>&Minimize to the tray instead of the taskbar</translation> + </message> + <message> + <source>M&inimize on close</source> + <translation>M&inimize on close</translation> + </message> + <message> + <source>&Display</source> + <translation>&Display</translation> + </message> + <message> <source>User Interface &language:</source> <translation>Idioma de la interfaz de usuario:</translation> </message> <message> + <source>The user interface language can be set here. This setting will take effect after restarting %1.</source> + <translation>The user interface language can be set here. This setting will take effect after restarting %1.</translation> + </message> + <message> + <source>&Unit to show amounts in:</source> + <translation>&Unit to show amounts in:</translation> + </message> + <message> + <source>Choose the default subdivision unit to show in the interface and when sending coins.</source> + <translation>Choose the default subdivision unit to show in the interface and when sending coins.</translation> + </message> + <message> + <source>Whether to show coin control features or not.</source> + <translation>Whether to show coin control features or not.</translation> + </message> + <message> + <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source> + <translation>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</translation> + </message> + <message> + <source>Use separate SOCKS&5 proxy to reach peers via Tor onion services:</source> + <translation>Use separate SOCKS&5 proxy to reach peers via Tor onion services:</translation> + </message> + <message> + <source>&Third party transaction URLs</source> + <translation>&Third party transaction URLs</translation> + </message> + <message> + <source>Options set in this dialog are overridden by the command line or in the configuration file:</source> + <translation>Options set in this dialog are overridden by the command line or in the configuration file:</translation> + </message> + <message> + <source>&OK</source> + <translation>&OK</translation> + </message> + <message> + <source>&Cancel</source> + <translation>&Cancel</translation> + </message> + <message> + <source>default</source> + <translation>default</translation> + </message> + <message> <source>none</source> <translation>Ninguno </translation> </message> <message> + <source>Confirm options reset</source> + <translation>Confirm options reset</translation> + </message> + <message> + <source>Client restart required to activate changes.</source> + <translation>Client restart required to activate changes.</translation> + </message> + <message> + <source>Client will be shut down. Do you want to proceed?</source> + <translation>Client will be shut down. Do you want to proceed?</translation> + </message> + <message> + <source>Configuration options</source> + <translation>Configuration options</translation> + </message> + <message> + <source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source> + <translation>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</translation> + </message> + <message> <source>Error</source> <translation>Error</translation> </message> <message> + <source>The configuration file could not be opened.</source> + <translation>The configuration file could not be opened.</translation> + </message> + <message> <source>This change would require a client restart.</source> <translation>Este cambio requeriría un reinicio del cliente.</translation> </message> - </context> + <message> + <source>The supplied proxy address is invalid.</source> + <translation>The supplied proxy address is invalid.</translation> + </message> +</context> <context> <name>OverviewPage</name> <message> @@ -943,13 +1435,165 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <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>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</translation> + </message> + <message> + <source>Watch-only:</source> + <translation>Watch-only:</translation> + </message> + <message> + <source>Available:</source> + <translation>Available:</translation> + </message> + <message> + <source>Your current spendable balance</source> + <translation>Your current spendable balance</translation> + </message> + <message> + <source>Pending:</source> + <translation>Pending:</translation> + </message> + <message> + <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source> + <translation>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</translation> + </message> + <message> + <source>Immature:</source> + <translation>Immature:</translation> + </message> + <message> + <source>Mined balance that has not yet matured</source> + <translation>Mined balance that has not yet matured</translation> + </message> + <message> + <source>Balances</source> + <translation>Balances</translation> + </message> + <message> + <source>Total:</source> + <translation>Total:</translation> + </message> + <message> + <source>Your current total balance</source> + <translation>Your current total balance</translation> + </message> + <message> + <source>Your current balance in watch-only addresses</source> + <translation>Your current balance in watch-only addresses</translation> + </message> + <message> + <source>Spendable:</source> + <translation>Spendable:</translation> + </message> + <message> <source>Recent transactions</source> <translation><b>Transacciones recientes</b></translation> </message> - </context> + <message> + <source>Unconfirmed transactions to watch-only addresses</source> + <translation>Unconfirmed transactions to watch-only addresses</translation> + </message> + <message> + <source>Mined balance in watch-only addresses that has not yet matured</source> + <translation>Mined balance in watch-only addresses that has not yet matured</translation> + </message> + <message> + <source>Current total balance in watch-only addresses</source> + <translation>Current total balance in watch-only addresses</translation> + </message> + <message> + <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</source> + <translation>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</translation> + </message> +</context> <context> <name>PSBTOperationsDialog</name> <message> + <source>Dialog</source> + <translation>Dialog</translation> + </message> + <message> + <source>Sign Tx</source> + <translation>Sign Tx</translation> + </message> + <message> + <source>Broadcast Tx</source> + <translation>Broadcast Tx</translation> + </message> + <message> + <source>Copy to Clipboard</source> + <translation>Copy to Clipboard</translation> + </message> + <message> + <source>Save...</source> + <translation>Save...</translation> + </message> + <message> + <source>Close</source> + <translation>Close</translation> + </message> + <message> + <source>Failed to load transaction: %1</source> + <translation>Failed to load transaction: %1</translation> + </message> + <message> + <source>Failed to sign transaction: %1</source> + <translation>Failed to sign transaction: %1</translation> + </message> + <message> + <source>Could not sign any more inputs.</source> + <translation>Could not sign any more inputs.</translation> + </message> + <message> + <source>Signed %1 inputs, but more signatures are still required.</source> + <translation>Signed %1 inputs, but more signatures are still required.</translation> + </message> + <message> + <source>Signed transaction successfully. Transaction is ready to broadcast.</source> + <translation>Signed transaction successfully. Transaction is ready to broadcast.</translation> + </message> + <message> + <source>Unknown error processing transaction.</source> + <translation>Unknown error processing transaction.</translation> + </message> + <message> + <source>Transaction broadcast successfully! Transaction ID: %1</source> + <translation>Transaction broadcast successfully! Transaction ID: %1</translation> + </message> + <message> + <source>Transaction broadcast failed: %1</source> + <translation>Transaction broadcast failed: %1</translation> + </message> + <message> + <source>PSBT copied to clipboard.</source> + <translation>PSBT copied to clipboard.</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>Save Transaction Data</translation> + </message> + <message> + <source>Partially Signed Transaction (Binary) (*.psbt)</source> + <translation>Partially Signed Transaction (Binary) (*.psbt)</translation> + </message> + <message> + <source>PSBT saved to disk.</source> + <translation>PSBT saved to disk.</translation> + </message> + <message> + <source> * Sends %1 to %2</source> + <translation> * Sends %1 to %2</translation> + </message> + <message> + <source>Unable to calculate transaction fee or total transaction amount.</source> + <translation>Unable to calculate transaction fee or total transaction amount.</translation> + </message> + <message> + <source>Pays transaction fee: </source> + <translation>Pays transaction fee: </translation> + </message> + <message> <source>Total Amount</source> <translation>Cantidad total</translation> </message> @@ -957,13 +1601,97 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <source>or</source> <translation>o</translation> </message> - </context> + <message> + <source>Transaction has %1 unsigned inputs.</source> + <translation>Transaction has %1 unsigned inputs.</translation> + </message> + <message> + <source>Transaction is missing some information about inputs.</source> + <translation>Transaction is missing some information about inputs.</translation> + </message> + <message> + <source>Transaction still needs signature(s).</source> + <translation>Transaction still needs signature(s).</translation> + </message> + <message> + <source>(But this wallet cannot sign transactions.)</source> + <translation>(But this wallet cannot sign transactions.)</translation> + </message> + <message> + <source>(But this wallet does not have the right keys.)</source> + <translation>(But this wallet does not have the right keys.)</translation> + </message> + <message> + <source>Transaction is fully signed and ready for broadcast.</source> + <translation>Transaction is fully signed and ready for broadcast.</translation> + </message> + <message> + <source>Transaction status is unknown.</source> + <translation>Transaction status is unknown.</translation> + </message> +</context> <context> <name>PaymentServer</name> - </context> + <message> + <source>Payment request error</source> + <translation>Payment request error</translation> + </message> + <message> + <source>Cannot start bitcoin: click-to-pay handler</source> + <translation>Cannot start bitcoin: click-to-pay handler</translation> + </message> + <message> + <source>URI handling</source> + <translation>URI handling</translation> + </message> + <message> + <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source> + <translation>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</translation> + </message> + <message> + <source>Cannot process payment request because BIP70 is not supported.</source> + <translation>Cannot process payment request because BIP70 is not supported.</translation> + </message> + <message> + <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source> + <translation>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</translation> + </message> + <message> + <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source> + <translation>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</translation> + </message> + <message> + <source>Invalid payment address %1</source> + <translation>Invalid payment address %1</translation> + </message> + <message> + <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source> + <translation>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation> + </message> + <message> + <source>Payment request file handling</source> + <translation>Payment request file handling</translation> + </message> +</context> <context> <name>PeerTableModel</name> <message> + <source>User Agent</source> + <translation>User Agent</translation> + </message> + <message> + <source>Node/Service</source> + <translation>Node/Service</translation> + </message> + <message> + <source>NodeId</source> + <translation>NodeId</translation> + </message> + <message> + <source>Ping</source> + <translation>Ping</translation> + </message> + <message> <source>Sent</source> <translation>Enviado</translation> </message> @@ -979,14 +1707,102 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Monto</translation> </message> <message> + <source>Enter a Bitcoin address (e.g. %1)</source> + <translation>Enter a Bitcoin address (e.g. %1)</translation> + </message> + <message> + <source>%1 d</source> + <translation>%1 d</translation> + </message> + <message> + <source>%1 h</source> + <translation>%1 h</translation> + </message> + <message> + <source>%1 m</source> + <translation>%1 m</translation> + </message> + <message> + <source>%1 s</source> + <translation>%1 s</translation> + </message> + <message> + <source>None</source> + <translation>None</translation> + </message> + <message> <source>N/A</source> <translation>N/A</translation> </message> <message> + <source>%1 ms</source> + <translation>%1 ms</translation> + </message> + <message numerus="yes"> + <source>%n second(s)</source> + <translation><numerusform>%n second</numerusform><numerusform>%n seconds</numerusform></translation> + </message> + <message numerus="yes"> + <source>%n minute(s)</source> + <translation><numerusform>%n minute</numerusform><numerusform>%n minutes</numerusform></translation> + </message> + <message numerus="yes"> + <source>%n hour(s)</source> + <translation><numerusform>%n hour</numerusform><numerusform>%n hours</numerusform></translation> + </message> + <message numerus="yes"> + <source>%n day(s)</source> + <translation><numerusform>%n day</numerusform><numerusform>%n days</numerusform></translation> + </message> + <message numerus="yes"> + <source>%n week(s)</source> + <translation><numerusform>%n week</numerusform><numerusform>%n weeks</numerusform></translation> + </message> + <message> + <source>%1 and %2</source> + <translation>%1 and %2</translation> + </message> + <message numerus="yes"> + <source>%n year(s)</source> + <translation><numerusform>%n year</numerusform><numerusform>%n years</numerusform></translation> + </message> + <message> + <source>%1 B</source> + <translation>%1 B</translation> + </message> + <message> + <source>%1 KB</source> + <translation>%1 KB</translation> + </message> + <message> + <source>%1 MB</source> + <translation>%1 MB</translation> + </message> + <message> + <source>%1 GB</source> + <translation>%1 GB</translation> + </message> + <message> + <source>Error: Specified data directory "%1" does not exist.</source> + <translation>Error: Specified data directory "%1" does not exist.</translation> + </message> + <message> + <source>Error: Cannot parse configuration file: %1.</source> + <translation>Error: Cannot parse configuration file: %1.</translation> + </message> + <message> <source>Error: %1</source> <translation>Error: %1</translation> </message> <message> + <source>Error initializing settings: %1</source> + <translation>Error initializing settings: %1</translation> + </message> + <message> + <source>%1 didn't yet exit safely...</source> + <translation>%1 didn't yet exit safely...</translation> + </message> + <message> <source>unknown</source> <translation>desconocido</translation> </message> @@ -1002,6 +1818,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>&Copiar Imagen</translation> </message> <message> + <source>Resulting URI too long, try to reduce the text for label / message.</source> + <translation>Resulting URI too long, try to reduce the text for label / message.</translation> + </message> + <message> <source>Error encoding URI into QR Code.</source> <translation>Error codificando la URI en el Código QR.</translation> </message> @@ -1037,6 +1857,30 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>General</translation> </message> <message> + <source>Using BerkeleyDB version</source> + <translation>Using BerkeleyDB version</translation> + </message> + <message> + <source>Datadir</source> + <translation>Datadir</translation> + </message> + <message> + <source>To specify a non-default location of the data directory use the '%1' option.</source> + <translation>To specify a non-default location of the data directory use the '%1' option.</translation> + </message> + <message> + <source>Blocksdir</source> + <translation>Blocksdir</translation> + </message> + <message> + <source>To specify a non-default location of the blocks directory use the '%1' option.</source> + <translation>To specify a non-default location of the blocks directory use the '%1' option.</translation> + </message> + <message> + <source>Startup time</source> + <translation>Startup time</translation> + </message> + <message> <source>Network</source> <translation>Red</translation> </message> @@ -1045,6 +1889,26 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Nombre</translation> </message> <message> + <source>Number of connections</source> + <translation>Number of connections</translation> + </message> + <message> + <source>Block chain</source> + <translation>Block chain</translation> + </message> + <message> + <source>Memory Pool</source> + <translation>Memory Pool</translation> + </message> + <message> + <source>Current number of transactions</source> + <translation>Current number of transactions</translation> + </message> + <message> + <source>Memory usage</source> + <translation>Memory usage</translation> + </message> + <message> <source>Wallet: </source> <translation>Cartera:</translation> </message> @@ -1053,6 +1917,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>(ninguno)</translation> </message> <message> + <source>&Reset</source> + <translation>&Reset</translation> + </message> + <message> <source>Received</source> <translation>Recibido</translation> </message> @@ -1061,6 +1929,62 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Enviado</translation> </message> <message> + <source>&Peers</source> + <translation>&Peers</translation> + </message> + <message> + <source>Banned peers</source> + <translation>Banned peers</translation> + </message> + <message> + <source>Select a peer to view detailed information.</source> + <translation>Select a peer to view detailed information.</translation> + </message> + <message> + <source>Direction</source> + <translation>Direction</translation> + </message> + <message> + <source>Version</source> + <translation>Version</translation> + </message> + <message> + <source>Starting Block</source> + <translation>Starting Block</translation> + </message> + <message> + <source>Synced Headers</source> + <translation>Synced Headers</translation> + </message> + <message> + <source>Synced Blocks</source> + <translation>Synced Blocks</translation> + </message> + <message> + <source>The mapped Autonomous System used for diversifying peer selection.</source> + <translation>The mapped Autonomous System used for diversifying peer selection.</translation> + </message> + <message> + <source>Mapped AS</source> + <translation>Mapped AS</translation> + </message> + <message> + <source>User Agent</source> + <translation>User Agent</translation> + </message> + <message> + <source>Node window</source> + <translation>Node window</translation> + </message> + <message> + <source>Current block height</source> + <translation>Current block height</translation> + </message> + <message> + <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source> + <translation>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</translation> + </message> + <message> <source>Decrease font size</source> <translation>Reducir el tamaño de la letra</translation> </message> @@ -1069,6 +1993,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Aumentar el tamaño de la letra</translation> </message> <message> + <source>Permissions</source> + <translation>Permissions</translation> + </message> + <message> <source>Services</source> <translation>Servicios</translation> </message> @@ -1085,6 +2013,110 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Última recepción</translation> </message> <message> + <source>Ping Time</source> + <translation>Ping Time</translation> + </message> + <message> + <source>The duration of a currently outstanding ping.</source> + <translation>The duration of a currently outstanding ping.</translation> + </message> + <message> + <source>Ping Wait</source> + <translation>Ping Wait</translation> + </message> + <message> + <source>Min Ping</source> + <translation>Min Ping</translation> + </message> + <message> + <source>Time Offset</source> + <translation>Time Offset</translation> + </message> + <message> + <source>Last block time</source> + <translation>Last block time</translation> + </message> + <message> + <source>&Open</source> + <translation>&Open</translation> + </message> + <message> + <source>&Console</source> + <translation>&Console</translation> + </message> + <message> + <source>&Network Traffic</source> + <translation>&Network Traffic</translation> + </message> + <message> + <source>Totals</source> + <translation>Totals</translation> + </message> + <message> + <source>In:</source> + <translation>In:</translation> + </message> + <message> + <source>Out:</source> + <translation>Out:</translation> + </message> + <message> + <source>Debug log file</source> + <translation>Debug log file</translation> + </message> + <message> + <source>Clear console</source> + <translation>Clear console</translation> + </message> + <message> + <source>1 &hour</source> + <translation>1 &hour</translation> + </message> + <message> + <source>1 &day</source> + <translation>1 &day</translation> + </message> + <message> + <source>1 &week</source> + <translation>1 &week</translation> + </message> + <message> + <source>1 &year</source> + <translation>1 &year</translation> + </message> + <message> + <source>&Disconnect</source> + <translation>&Disconnect</translation> + </message> + <message> + <source>Ban for</source> + <translation>Ban for</translation> + </message> + <message> + <source>&Unban</source> + <translation>&Unban</translation> + </message> + <message> + <source>Welcome to the %1 RPC console.</source> + <translation>Welcome to the %1 RPC console.</translation> + </message> + <message> + <source>Use up and down arrows to navigate history, and %1 to clear screen.</source> + <translation>Use up and down arrows to navigate history, and %1 to clear screen.</translation> + </message> + <message> + <source>Type %1 for an overview of available commands.</source> + <translation>Type %1 for an overview of available commands.</translation> + </message> + <message> + <source>For more information on using this console type %1.</source> + <translation>For more information on using this console type %1.</translation> + </message> + <message> + <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source> + <translation>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</translation> + </message> + <message> <source>Network activity disabled</source> <translation>Actividad de la red desactivada</translation> </message> @@ -1093,6 +2125,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Ejecutando el comando sin ninguna cartera</translation> </message> <message> + <source>Executing command using "%1" wallet</source> + <translation>Executing command using "%1" wallet</translation> + </message> + <message> + <source>(node id: %1)</source> + <translation>(node id: %1)</translation> + </message> + <message> + <source>via %1</source> + <translation>via %1</translation> + </message> + <message> <source>never</source> <translation>nunca</translation> </message> @@ -1160,6 +2204,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Borrar </translation> </message> <message> + <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source> + <translation>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</translation> + </message> + <message> + <source>Generate native segwit (Bech32) address</source> + <translation>Generate native segwit (Bech32) address</translation> + </message> + <message> <source>Requested payments history</source> <translation>Historial de pagos solicitados</translation> </message> @@ -1180,10 +2232,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Eliminar </translation> </message> <message> + <source>Copy URI</source> + <translation>Copy URI</translation> + </message> + <message> <source>Copy label</source> <translation>Copiar capa </translation> </message> <message> + <source>Copy message</source> + <translation>Copy message</translation> + </message> + <message> <source>Copy amount</source> <translation>copiar monto</translation> </message> @@ -1191,14 +2251,30 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <source>Could not unlock wallet.</source> <translation>No se puede desbloquear la cartera</translation> </message> - </context> + <message> + <source>Could not generate new %1 address</source> + <translation>Could not generate new %1 address</translation> + </message> +</context> <context> <name>ReceiveRequestDialog</name> <message> + <source>Request payment to ...</source> + <translation>Request payment to ...</translation> + </message> + <message> + <source>Address:</source> + <translation>Address:</translation> + </message> + <message> <source>Amount:</source> <translation>Monto:</translation> </message> <message> + <source>Label:</source> + <translation>Label:</translation> + </message> + <message> <source>Message:</source> <translation>Mensaje:</translation> </message> @@ -1207,6 +2283,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Cartera:</translation> </message> <message> + <source>Copy &URI</source> + <translation>Copy &URI</translation> + </message> + <message> <source>Copy &Address</source> <translation>&Copiar dirección</translation> </message> @@ -1214,7 +2294,15 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <source>&Save Image...</source> <translation>&Guardar imagen...</translation> </message> - </context> + <message> + <source>Request payment to %1</source> + <translation>Request payment to %1</translation> + </message> + <message> + <source>Payment information</source> + <translation>Payment information</translation> + </message> +</context> <context> <name>RecentRequestsTableModel</name> <message> @@ -1233,7 +2321,19 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <source>(no label)</source> <translation>(sin etiqueta)</translation> </message> - </context> + <message> + <source>(no message)</source> + <translation>(no message)</translation> + </message> + <message> + <source>(no amount requested)</source> + <translation>(no amount requested)</translation> + </message> + <message> + <source>Requested</source> + <translation>Requested</translation> + </message> +</context> <context> <name>SendCoinsDialog</name> <message> @@ -1241,6 +2341,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Enviar monedas</translation> </message> <message> + <source>Coin Control Features</source> + <translation>Coin Control Features</translation> + </message> + <message> + <source>Inputs...</source> + <translation>Inputs...</translation> + </message> + <message> + <source>automatically selected</source> + <translation>automatically selected</translation> + </message> + <message> + <source>Insufficient funds!</source> + <translation>Insufficient funds!</translation> + </message> + <message> <source>Quantity:</source> <translation>Cantidad</translation> </message> @@ -1265,14 +2381,66 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Cambio</translation> </message> <message> + <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source> + <translation>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</translation> + </message> + <message> + <source>Custom change address</source> + <translation>Custom change address</translation> + </message> + <message> + <source>Transaction Fee:</source> + <translation>Transaction Fee:</translation> + </message> + <message> + <source>Choose...</source> + <translation>Choose...</translation> + </message> + <message> + <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source> + <translation>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</translation> + </message> + <message> + <source>Warning: Fee estimation is currently not possible.</source> + <translation>Warning: Fee estimation is currently not possible.</translation> + </message> + <message> + <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size. + +Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source> + <translation>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size. + +Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</translation> + </message> + <message> + <source>per kilobyte</source> + <translation>per kilobyte</translation> + </message> + <message> <source>Hide</source> <translation>Ocultar </translation> </message> <message> + <source>Recommended:</source> + <translation>Recommended:</translation> + </message> + <message> + <source>Custom:</source> + <translation>Custom:</translation> + </message> + <message> + <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source> + <translation>(Smart fee not initialized yet. This usually takes a few blocks...)</translation> + </message> + <message> <source>Send to multiple recipients at once</source> <translation>Enviar a múltiples receptores a la vez</translation> </message> <message> + <source>Add &Recipient</source> + <translation>Add &Recipient</translation> + </message> + <message> <source>Clear all fields of the form.</source> <translation>Despeja todos los campos del formulario.</translation> </message> @@ -1281,6 +2449,34 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Remanente monetario:</translation> </message> <message> + <source>Hide transaction fee settings</source> + <translation>Hide transaction fee settings</translation> + </message> + <message> + <source>When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> + <translation>When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</translation> + </message> + <message> + <source>A too low fee might result in a never confirming transaction (read the tooltip)</source> + <translation>A too low fee might result in a never confirming transaction (read the tooltip)</translation> + </message> + <message> + <source>Confirmation time target:</source> + <translation>Confirmation time target:</translation> + </message> + <message> + <source>Enable Replace-By-Fee</source> + <translation>Enable Replace-By-Fee</translation> + </message> + <message> + <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source> + <translation>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</translation> + </message> + <message> + <source>Clear &All</source> + <translation>Clear &All</translation> + </message> + <message> <source>Balance:</source> <translation>Saldo:</translation> </message> @@ -1289,6 +2485,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Confirme la acción de enviar</translation> </message> <message> + <source>S&end</source> + <translation>S&end</translation> + </message> + <message> <source>Copy quantity</source> <translation>Copiar cantidad</translation> </message> @@ -1309,10 +2509,38 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Copiar bytes</translation> </message> <message> + <source>Copy dust</source> + <translation>Copy dust</translation> + </message> + <message> <source>Copy change</source> <translation>Copiar cambio</translation> </message> <message> + <source>%1 (%2 blocks)</source> + <translation>%1 (%2 blocks)</translation> + </message> + <message> + <source>Cr&eate Unsigned</source> + <translation>Cr&eate Unsigned</translation> + </message> + <message> + <source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source> + <translation>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation> + </message> + <message> + <source> from wallet '%1'</source> + <translation> from wallet '%1'</translation> + </message> + <message> + <source>%1 to '%2'</source> + <translation>%1 to '%2'</translation> + </message> + <message> + <source>%1 to %2</source> + <translation>%1 to %2</translation> + </message> + <message> <source>Do you want to draft this transaction?</source> <translation>¿Quiere redactar esta transacción?</translation> </message> @@ -1321,10 +2549,34 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>¿Está seguro de que quiere enviar?</translation> </message> <message> + <source>Create Unsigned</source> + <translation>Create Unsigned</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>Save Transaction Data</translation> + </message> + <message> + <source>Partially Signed Transaction (Binary) (*.psbt)</source> + <translation>Partially Signed Transaction (Binary) (*.psbt)</translation> + </message> + <message> + <source>PSBT saved</source> + <translation>PSBT saved</translation> + </message> + <message> <source>or</source> <translation>o</translation> </message> <message> + <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source> + <translation>You can increase the fee later (signals Replace-By-Fee, BIP-125).</translation> + </message> + <message> + <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can save or copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source> + <translation>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can save or copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation> + </message> + <message> <source>Please, review your transaction.</source> <translation>Por favor, revise su transacción.</translation> </message> @@ -1333,6 +2585,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Cuota de transacción</translation> </message> <message> + <source>Not signalling Replace-By-Fee, BIP-125.</source> + <translation>Not signalling Replace-By-Fee, BIP-125.</translation> + </message> + <message> <source>Total Amount</source> <translation>Cantidad total</translation> </message> @@ -1353,6 +2609,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Enviar</translation> </message> <message> + <source>Watch-only balance:</source> + <translation>Watch-only balance:</translation> + </message> + <message> <source>The recipient address is not valid. Please recheck.</source> <translation>La dirección del destinatario no es válida. Por favor, vuelva a verificarla.</translation> </message> @@ -1365,6 +2625,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>La cantidad excede su saldo.</translation> </message> <message> + <source>The total exceeds your balance when the %1 transaction fee is included.</source> + <translation>The total exceeds your balance when the %1 transaction fee is included.</translation> + </message> + <message> <source>Duplicate address found: addresses should only be used once each.</source> <translation>Duplicado de la dirección encontrada: las direcciones sólo deben ser utilizadas una vez cada una.</translation> </message> @@ -1373,9 +2637,17 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>¡La creación de la transación falló!</translation> </message> <message> + <source>A fee higher than %1 is considered an absurdly high fee.</source> + <translation>A fee higher than %1 is considered an absurdly high fee.</translation> + </message> + <message> <source>Payment request expired.</source> <translation>La solicitud de pago expiró.</translation> </message> + <message numerus="yes"> + <source>Estimated to begin confirmation within %n block(s).</source> + <translation><numerusform>Estimated to begin confirmation within %n block.</numerusform><numerusform>Estimated to begin confirmation within %n blocks.</numerusform></translation> + </message> <message> <source>Warning: Invalid Bitcoin address</source> <translation>Advertencia: Dirección de Bitcoin invalida</translation> @@ -1389,6 +2661,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Confirmar la dirección de cambio personalizada</translation> </message> <message> + <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source> + <translation>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</translation> + </message> + <message> <source>(no label)</source> <translation>(sin etiqueta)</translation> </message> @@ -1432,6 +2708,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Quitar esta entrada</translation> </message> <message> + <source>The amount to send in the selected unit</source> + <translation>The amount to send in the selected unit</translation> + </message> + <message> + <source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source> + <translation>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</translation> + </message> + <message> + <source>S&ubtract fee from amount</source> + <translation>S&ubtract fee from amount</translation> + </message> + <message> <source>Use available balance</source> <translation>Usar el saldo disponible</translation> </message> @@ -1452,13 +2740,25 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Introducir una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation> </message> <message> + <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source> + <translation>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</translation> + </message> + <message> <source>Pay To:</source> <translation>Pago para:</translation> </message> - </context> + <message> + <source>Memo:</source> + <translation>Memo:</translation> + </message> +</context> <context> <name>ShutdownWindow</name> <message> + <source>%1 is shutting down...</source> + <translation>%1 is shutting down...</translation> + </message> + <message> <source>Do not shut down the computer until this window disappears.</source> <translation>No apague su computadora hasta que esta ventana desaparesca.</translation> </message> @@ -1466,6 +2766,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <context> <name>SignVerifyMessageDialog</name> <message> + <source>Signatures - Sign / Verify a Message</source> + <translation>Signatures - Sign / Verify a Message</translation> + </message> + <message> + <source>&Sign Message</source> + <translation>&Sign Message</translation> + </message> + <message> + <source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source> + <translation>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</translation> + </message> + <message> + <source>The Bitcoin address to sign the message with</source> + <translation>The Bitcoin address to sign the message with</translation> + </message> + <message> <source>Choose previously used address</source> <translation>Elegir la dirección utilizada anteriormente</translation> </message> @@ -1482,20 +2798,160 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Alt+P</translation> </message> <message> + <source>Enter the message you want to sign here</source> + <translation>Enter the message you want to sign here</translation> + </message> + <message> <source>Signature</source> <translation>Firma</translation> </message> - </context> + <message> + <source>Copy the current signature to the system clipboard</source> + <translation>Copy the current signature to the system clipboard</translation> + </message> + <message> + <source>Sign the message to prove you own this Bitcoin address</source> + <translation>Sign the message to prove you own this Bitcoin address</translation> + </message> + <message> + <source>Sign &Message</source> + <translation>Sign &Message</translation> + </message> + <message> + <source>Reset all sign message fields</source> + <translation>Reset all sign message fields</translation> + </message> + <message> + <source>Clear &All</source> + <translation>Clear &All</translation> + </message> + <message> + <source>&Verify Message</source> + <translation>&Verify Message</translation> + </message> + <message> + <source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source> + <translation>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</translation> + </message> + <message> + <source>The Bitcoin address the message was signed with</source> + <translation>The Bitcoin address the message was signed with</translation> + </message> + <message> + <source>The signed message to verify</source> + <translation>The signed message to verify</translation> + </message> + <message> + <source>The signature given when the message was signed</source> + <translation>The signature given when the message was signed</translation> + </message> + <message> + <source>Verify the message to ensure it was signed with the specified Bitcoin address</source> + <translation>Verify the message to ensure it was signed with the specified Bitcoin address</translation> + </message> + <message> + <source>Verify &Message</source> + <translation>Verify &Message</translation> + </message> + <message> + <source>Reset all verify message fields</source> + <translation>Reset all verify message fields</translation> + </message> + <message> + <source>Click "Sign Message" to generate signature</source> + <translation>Click "Sign Message" to generate signature</translation> + </message> + <message> + <source>The entered address is invalid.</source> + <translation>The entered address is invalid.</translation> + </message> + <message> + <source>Please check the address and try again.</source> + <translation>Please check the address and try again.</translation> + </message> + <message> + <source>The entered address does not refer to a key.</source> + <translation>The entered address does not refer to a key.</translation> + </message> + <message> + <source>Wallet unlock was cancelled.</source> + <translation>Wallet unlock was cancelled.</translation> + </message> + <message> + <source>No error</source> + <translation>No error</translation> + </message> + <message> + <source>Private key for the entered address is not available.</source> + <translation>Private key for the entered address is not available.</translation> + </message> + <message> + <source>Message signing failed.</source> + <translation>Message signing failed.</translation> + </message> + <message> + <source>Message signed.</source> + <translation>Message signed.</translation> + </message> + <message> + <source>The signature could not be decoded.</source> + <translation>The signature could not be decoded.</translation> + </message> + <message> + <source>Please check the signature and try again.</source> + <translation>Please check the signature and try again.</translation> + </message> + <message> + <source>The signature did not match the message digest.</source> + <translation>The signature did not match the message digest.</translation> + </message> + <message> + <source>Message verification failed.</source> + <translation>Message verification failed.</translation> + </message> + <message> + <source>Message verified.</source> + <translation>Message verified.</translation> + </message> +</context> <context> <name>TrafficGraphWidget</name> - </context> + <message> + <source>KB/s</source> + <translation>KB/s</translation> + </message> +</context> <context> <name>TransactionDesc</name> + <message numerus="yes"> + <source>Open for %n more block(s)</source> + <translation><numerusform>Open for %n more block</numerusform><numerusform>Open for %n more blocks</numerusform></translation> + </message> <message> <source>Open until %1</source> <translation>Abrir hasta %1</translation> </message> <message> + <source>conflicted with a transaction with %1 confirmations</source> + <translation>conflicted with a transaction with %1 confirmations</translation> + </message> + <message> + <source>0/unconfirmed, %1</source> + <translation>0/unconfirmed, %1</translation> + </message> + <message> + <source>in memory pool</source> + <translation>in memory pool</translation> + </message> + <message> + <source>not in memory pool</source> + <translation>not in memory pool</translation> + </message> + <message> + <source>abandoned</source> + <translation>abandoned</translation> + </message> + <message> <source>%1/unconfirmed</source> <translation>%1/No confirmado</translation> </message> @@ -1512,6 +2968,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Fecha</translation> </message> <message> + <source>Source</source> + <translation>Source</translation> + </message> + <message> + <source>Generated</source> + <translation>Generated</translation> + </message> + <message> <source>From</source> <translation>De</translation> </message> @@ -1524,14 +2988,50 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Para</translation> </message> <message> + <source>own address</source> + <translation>own address</translation> + </message> + <message> + <source>watch-only</source> + <translation>watch-only</translation> + </message> + <message> <source>label</source> <translation>etiqueta</translation> </message> <message> + <source>Credit</source> + <translation>Credit</translation> + </message> + <message numerus="yes"> + <source>matures in %n more block(s)</source> + <translation><numerusform>matures in %n more block</numerusform><numerusform>matures in %n more blocks</numerusform></translation> + </message> + <message> + <source>not accepted</source> + <translation>not accepted</translation> + </message> + <message> + <source>Debit</source> + <translation>Debit</translation> + </message> + <message> + <source>Total debit</source> + <translation>Total debit</translation> + </message> + <message> + <source>Total credit</source> + <translation>Total credit</translation> + </message> + <message> <source>Transaction fee</source> <translation>Cuota de transacción</translation> </message> <message> + <source>Net amount</source> + <translation>Net amount</translation> + </message> + <message> <source>Message</source> <translation>Mensaje</translation> </message> @@ -1544,21 +3044,65 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>ID</translation> </message> <message> + <source>Transaction total size</source> + <translation>Transaction total size</translation> + </message> + <message> + <source>Transaction virtual size</source> + <translation>Transaction virtual size</translation> + </message> + <message> + <source>Output index</source> + <translation>Output index</translation> + </message> + <message> + <source> (Certificate was not verified)</source> + <translation> (Certificate was not verified)</translation> + </message> + <message> + <source>Merchant</source> + <translation>Merchant</translation> + </message> + <message> + <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source> + <translation>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</translation> + </message> + <message> + <source>Debug information</source> + <translation>Debug information</translation> + </message> + <message> <source>Transaction</source> <translation>Transacción</translation> </message> <message> + <source>Inputs</source> + <translation>Inputs</translation> + </message> + <message> <source>Amount</source> <translation>Monto</translation> </message> - </context> + <message> + <source>true</source> + <translation>true</translation> + </message> + <message> + <source>false</source> + <translation>false</translation> + </message> +</context> <context> <name>TransactionDescDialog</name> <message> <source>This pane shows a detailed description of the transaction</source> <translation>Este panel muestras una descripción detallada de la transacción</translation> </message> - </context> + <message> + <source>Details for %1</source> + <translation>Details for %1</translation> + </message> +</context> <context> <name>TransactionTableModel</name> <message> @@ -1573,15 +3117,39 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <source>Label</source> <translation>Etiqueta</translation> </message> + <message numerus="yes"> + <source>Open for %n more block(s)</source> + <translation><numerusform>Open for %n more block</numerusform><numerusform>Open for %n more blocks</numerusform></translation> + </message> <message> <source>Open until %1</source> <translation>Abrir hasta %1</translation> </message> <message> + <source>Unconfirmed</source> + <translation>Unconfirmed</translation> + </message> + <message> + <source>Abandoned</source> + <translation>Abandoned</translation> + </message> + <message> + <source>Confirming (%1 of %2 recommended confirmations)</source> + <translation>Confirming (%1 of %2 recommended confirmations)</translation> + </message> + <message> <source>Confirmed (%1 confirmations)</source> <translation>Confimado (%1 confirmaciones)</translation> </message> <message> + <source>Conflicted</source> + <translation>Conflicted</translation> + </message> + <message> + <source>Immature (%1 confirmations, will be available after %2)</source> + <translation>Immature (%1 confirmations, will be available after %2)</translation> + </message> + <message> <source>Generated but not accepted</source> <translation>Generado pero no aprovado</translation> </message> @@ -1590,6 +3158,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Recibido con</translation> </message> <message> + <source>Received from</source> + <translation>Received from</translation> + </message> + <message> <source>Sent to</source> <translation>Enviar a</translation> </message> @@ -1602,6 +3174,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Minado </translation> </message> <message> + <source>watch-only</source> + <translation>watch-only</translation> + </message> + <message> <source>(n/a)</source> <translation>(n/a)</translation> </message> @@ -1610,6 +3186,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>(sin etiqueta)</translation> </message> <message> + <source>Transaction status. Hover over this field to show number of confirmations.</source> + <translation>Transaction status. Hover over this field to show number of confirmations.</translation> + </message> + <message> <source>Date and time that the transaction was received.</source> <translation>Fecha y hora en que la transacción fue recibida </translation> </message> @@ -1618,6 +3198,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Escriba una transacción</translation> </message> <message> + <source>Whether or not a watch-only address is involved in this transaction.</source> + <translation>Whether or not a watch-only address is involved in this transaction.</translation> + </message> + <message> + <source>User-defined intent/purpose of the transaction.</source> + <translation>User-defined intent/purpose of the transaction.</translation> + </message> + <message> <source>Amount removed from or added to balance.</source> <translation>Cantidad removida del saldo o agregada </translation> </message> @@ -1649,6 +3237,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Este año</translation> </message> <message> + <source>Range...</source> + <translation>Range...</translation> + </message> + <message> <source>Received with</source> <translation>Recibido con</translation> </message> @@ -1669,10 +3261,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Otro</translation> </message> <message> + <source>Enter address, transaction id, or label to search</source> + <translation>Enter address, transaction id, or label to search</translation> + </message> + <message> <source>Min amount</source> <translation>Monto minimo </translation> </message> <message> + <source>Abandon transaction</source> + <translation>Abandon transaction</translation> + </message> + <message> + <source>Increase transaction fee</source> + <translation>Increase transaction fee</translation> + </message> + <message> <source>Copy address</source> <translation>Copiar dirección </translation> </message> @@ -1689,10 +3293,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Copiar identificación de la transacción. </translation> </message> <message> + <source>Copy raw transaction</source> + <translation>Copy raw transaction</translation> + </message> + <message> + <source>Copy full transaction details</source> + <translation>Copy full transaction details</translation> + </message> + <message> <source>Edit label</source> <translation>Editar capa </translation> </message> <message> + <source>Show transaction details</source> + <translation>Show transaction details</translation> + </message> + <message> <source>Export Transaction History</source> <translation>Exportar el historial de transacción</translation> </message> @@ -1705,6 +3321,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Confirmado </translation> </message> <message> + <source>Watch-only</source> + <translation>Watch-only</translation> + </message> + <message> <source>Date</source> <translation>Fecha</translation> </message> @@ -1741,23 +3361,55 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>el historial de transaciones ha sido guardado exitosamente en %1</translation> </message> <message> + <source>Range:</source> + <translation>Range:</translation> + </message> + <message> <source>to</source> <translation>Para</translation> </message> </context> <context> <name>UnitDisplayStatusBarControl</name> - </context> + <message> + <source>Unit to show amounts in. Click to select another unit.</source> + <translation>Unit to show amounts in. Click to select another unit.</translation> + </message> +</context> <context> <name>WalletController</name> <message> <source>Close wallet</source> <translation>Cerrar cartera</translation> </message> - </context> + <message> + <source>Are you sure you wish to close the wallet <i>%1</i>?</source> + <translation>Are you sure you wish to close the wallet <i>%1</i>?</translation> + </message> + <message> + <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source> + <translation>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</translation> + </message> + <message> + <source>Close all wallets</source> + <translation>Close all wallets</translation> + </message> + <message> + <source>Are you sure you wish to close all wallets?</source> + <translation>Are you sure you wish to close all wallets?</translation> + </message> +</context> <context> <name>WalletFrame</name> <message> + <source>No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR -</source> + <translation>No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR -</translation> + </message> + <message> <source>Create a new wallet</source> <translation>Crear una nueva cartera</translation> </message> @@ -1769,6 +3421,54 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Enviar monedas</translation> </message> <message> + <source>Fee bump error</source> + <translation>Fee bump error</translation> + </message> + <message> + <source>Increasing transaction fee failed</source> + <translation>Increasing transaction fee failed</translation> + </message> + <message> + <source>Do you want to increase the fee?</source> + <translation>Do you want to increase the fee?</translation> + </message> + <message> + <source>Do you want to draft a transaction with fee increase?</source> + <translation>Do you want to draft a transaction with fee increase?</translation> + </message> + <message> + <source>Current fee:</source> + <translation>Current fee:</translation> + </message> + <message> + <source>Increase:</source> + <translation>Increase:</translation> + </message> + <message> + <source>New fee:</source> + <translation>New fee:</translation> + </message> + <message> + <source>Confirm fee bump</source> + <translation>Confirm fee bump</translation> + </message> + <message> + <source>Can't draft transaction.</source> + <translation>Can't draft transaction.</translation> + </message> + <message> + <source>PSBT copied</source> + <translation>PSBT copied</translation> + </message> + <message> + <source>Can't sign transaction.</source> + <translation>Can't sign transaction.</translation> + </message> + <message> + <source>Could not commit transaction</source> + <translation>Could not commit transaction</translation> + </message> + <message> <source>default wallet</source> <translation>cartera predeterminada</translation> </message> @@ -1788,17 +3488,201 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Error</translation> </message> <message> + <source>Unable to decode PSBT from clipboard (invalid base64)</source> + <translation>Unable to decode PSBT from clipboard (invalid base64)</translation> + </message> + <message> + <source>Load Transaction Data</source> + <translation>Load Transaction Data</translation> + </message> + <message> + <source>Partially Signed Transaction (*.psbt)</source> + <translation>Partially Signed Transaction (*.psbt)</translation> + </message> + <message> + <source>PSBT file must be smaller than 100 MiB</source> + <translation>PSBT file must be smaller than 100 MiB</translation> + </message> + <message> + <source>Unable to decode PSBT</source> + <translation>Unable to decode PSBT</translation> + </message> + <message> + <source>Backup Wallet</source> + <translation>Backup Wallet</translation> + </message> + <message> + <source>Wallet Data (*.dat)</source> + <translation>Wallet Data (*.dat)</translation> + </message> + <message> + <source>Backup Failed</source> + <translation>Backup Failed</translation> + </message> + <message> <source>There was an error trying to save the wallet data to %1.</source> <translation>Ocurrio un error tratando de guardar la información de la cartera %1</translation> </message> <message> + <source>Backup Successful</source> + <translation>Backup Successful</translation> + </message> + <message> <source>The wallet data was successfully saved to %1.</source> <translation>La información de la cartera fué guardada exitosamente a %1</translation> </message> - </context> + <message> + <source>Cancel</source> + <translation>Cancel</translation> + </message> +</context> <context> <name>bitcoin-core</name> <message> + <source>Distributed under the MIT software license, see the accompanying file %s or %s</source> + <translation>Distributed under the MIT software license, see the accompanying file %s or %s</translation> + </message> + <message> + <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source> + <translation>Prune configured below the minimum of %d MiB. Please use a higher number.</translation> + </message> + <message> + <source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source> + <translation>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</translation> + </message> + <message> + <source>Pruning blockstore...</source> + <translation>Pruning blockstore...</translation> + </message> + <message> + <source>Unable to start HTTP server. See debug log for details.</source> + <translation>Unable to start HTTP server. See debug log for details.</translation> + </message> + <message> + <source>The %s developers</source> + <translation>The %s developers</translation> + </message> + <message> + <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source> + <translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation> + </message> + <message> + <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source> + <translation>Cannot provide specific connections and have addrman find outgoing connections at the same.</translation> + </message> + <message> + <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source> + <translation>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</translation> + </message> + <message> + <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> + <translation>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</translation> + </message> + <message> + <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source> + <translation>Please contribute if you find %s useful. Visit %s for further information about the software.</translation> + </message> + <message> + <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> + <translation>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</translation> + </message> + <message> + <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source> + <translation>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</translation> + </message> + <message> + <source>This is the transaction fee you may discard if change is smaller than dust at this level</source> + <translation>This is the transaction fee you may discard if change is smaller than dust at this level</translation> + </message> + <message> + <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source> + <translation>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</translation> + </message> + <message> + <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source> + <translation>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</translation> + </message> + <message> + <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source> + <translation>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</translation> + </message> + <message> + <source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source> + <translation>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation> + </message> + <message> + <source>-maxmempool must be at least %d MB</source> + <translation>-maxmempool must be at least %d MB</translation> + </message> + <message> + <source>Cannot resolve -%s address: '%s'</source> + <translation>Cannot resolve -%s address: '%s'</translation> + </message> + <message> + <source>Change index out of range</source> + <translation>Change index out of range</translation> + </message> + <message> + <source>Config setting for %s only applied on %s network when in [%s] section.</source> + <translation>Config setting for %s only applied on %s network when in [%s] section.</translation> + </message> + <message> + <source>Copyright (C) %i-%i</source> + <translation>Copyright (C) %i-%i</translation> + </message> + <message> + <source>Corrupted block database detected</source> + <translation>Corrupted block database detected</translation> + </message> + <message> + <source>Could not find asmap file %s</source> + <translation>Could not find asmap file %s</translation> + </message> + <message> + <source>Could not parse asmap file %s</source> + <translation>Could not parse asmap file %s</translation> + </message> + <message> + <source>Do you want to rebuild the block database now?</source> + <translation>Do you want to rebuild the block database now?</translation> + </message> + <message> + <source>Error initializing block database</source> + <translation>Error initializing block database</translation> + </message> + <message> + <source>Error initializing wallet database environment %s!</source> + <translation>Error initializing wallet database environment %s!</translation> + </message> + <message> + <source>Error loading %s</source> + <translation>Error loading %s</translation> + </message> + <message> + <source>Error loading %s: Private keys can only be disabled during creation</source> + <translation>Error loading %s: Private keys can only be disabled during creation</translation> + </message> + <message> + <source>Error loading %s: Wallet corrupted</source> + <translation>Error loading %s: Wallet corrupted</translation> + </message> + <message> + <source>Error loading %s: Wallet requires newer version of %s</source> + <translation>Error loading %s: Wallet requires newer version of %s</translation> + </message> + <message> + <source>Error loading block database</source> + <translation>Error loading block database</translation> + </message> + <message> + <source>Error opening block database</source> + <translation>Error opening block database</translation> + </message> + <message> + <source>Failed to listen on any port. Use -listen=0 if you want this.</source> + <translation>Failed to listen on any port. Use -listen=0 if you want this.</translation> + </message> + <message> <source>Failed to rescan the wallet during initialization</source> <translation>Falló al volver a escanear la cartera durante la inicialización</translation> </message> @@ -1807,6 +3691,50 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Importando...</translation> </message> <message> + <source>Incorrect or no genesis block found. Wrong datadir for network?</source> + <translation>Incorrect or no genesis block found. Wrong datadir for network?</translation> + </message> + <message> + <source>Initialization sanity check failed. %s is shutting down.</source> + <translation>Initialization sanity check failed. %s is shutting down.</translation> + </message> + <message> + <source>Invalid P2P permission: '%s'</source> + <translation>Invalid P2P permission: '%s'</translation> + </message> + <message> + <source>Invalid amount for -%s=<amount>: '%s'</source> + <translation>Invalid amount for -%s=<amount>: '%s'</translation> + </message> + <message> + <source>Invalid amount for -discardfee=<amount>: '%s'</source> + <translation>Invalid amount for -discardfee=<amount>: '%s'</translation> + </message> + <message> + <source>Invalid amount for -fallbackfee=<amount>: '%s'</source> + <translation>Invalid amount for -fallbackfee=<amount>: '%s'</translation> + </message> + <message> + <source>Specified blocks directory "%s" does not exist.</source> + <translation>Specified blocks directory "%s" does not exist.</translation> + </message> + <message> + <source>Unknown address type '%s'</source> + <translation>Unknown address type '%s'</translation> + </message> + <message> + <source>Unknown change type '%s'</source> + <translation>Unknown change type '%s'</translation> + </message> + <message> + <source>Upgrading txindex database</source> + <translation>Upgrading txindex database</translation> + </message> + <message> + <source>Loading P2P addresses...</source> + <translation>Loading P2P addresses...</translation> + </message> + <message> <source>Loading banlist...</source> <translation>Cargando la lista de anuncios...</translation> </message> @@ -1815,30 +3743,184 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>No hay suficientes descriptores de archivos disponibles.</translation> </message> <message> + <source>Prune cannot be configured with a negative value.</source> + <translation>Prune cannot be configured with a negative value.</translation> + </message> + <message> + <source>Prune mode is incompatible with -txindex.</source> + <translation>Prune mode is incompatible with -txindex.</translation> + </message> + <message> + <source>Replaying blocks...</source> + <translation>Replaying blocks...</translation> + </message> + <message> + <source>Rewinding blocks...</source> + <translation>Rewinding blocks...</translation> + </message> + <message> + <source>The source code is available from %s.</source> + <translation>The source code is available from %s.</translation> + </message> + <message> <source>Transaction fee and change calculation failed</source> <translation>La tarifa de la transacción y el cálculo del cambio fallaron</translation> </message> <message> + <source>Unable to bind to %s on this computer. %s is probably already running.</source> + <translation>Unable to bind to %s on this computer. %s is probably already running.</translation> + </message> + <message> <source>Unable to generate keys</source> <translation>Incapaz de generar claves</translation> </message> <message> + <source>Unsupported logging category %s=%s.</source> + <translation>Unsupported logging category %s=%s.</translation> + </message> + <message> + <source>Upgrading UTXO database</source> + <translation>Upgrading UTXO database</translation> + </message> + <message> + <source>User Agent comment (%s) contains unsafe characters.</source> + <translation>User Agent comment (%s) contains unsafe characters.</translation> + </message> + <message> <source>Verifying blocks...</source> <translation>Verificando bloques...</translation> </message> <message> + <source>Wallet needed to be rewritten: restart %s to complete</source> + <translation>Wallet needed to be rewritten: restart %s to complete</translation> + </message> + <message> + <source>Error: Listening for incoming connections failed (listen returned error %s)</source> + <translation>Error: Listening for incoming connections failed (listen returned error %s)</translation> + </message> + <message> + <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source> + <translation>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</translation> + </message> + <message> + <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source> + <translation>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</translation> + </message> + <message> + <source>Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source> + <translation>Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</translation> + </message> + <message> <source>The transaction amount is too small to send after the fee has been deducted</source> <translation>La cantidad de la transacción es demasiado pequeña para enviarla después de que se haya deducido la tarifa</translation> </message> <message> + <source>This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet</source> + <translation>This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet</translation> + </message> + <message> + <source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source> + <translation>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</translation> + </message> + <message> + <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source> + <translation>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</translation> + </message> + <message> + <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source> + <translation>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</translation> + </message> + <message> + <source>A fatal internal error occurred, see debug.log for details</source> + <translation>A fatal internal error occurred, see debug.log for details</translation> + </message> + <message> + <source>Cannot set -peerblockfilters without -blockfilterindex.</source> + <translation>Cannot set -peerblockfilters without -blockfilterindex.</translation> + </message> + <message> + <source>Disk space is too low!</source> + <translation>Disk space is too low!</translation> + </message> + <message> <source>Error reading from database, shutting down.</source> <translation>Error de lectura de la base de datos, apagando.</translation> </message> <message> + <source>Error upgrading chainstate database</source> + <translation>Error upgrading chainstate database</translation> + </message> + <message> + <source>Error: Disk space is low for %s</source> + <translation>Error: Disk space is low for %s</translation> + </message> + <message> + <source>Error: Keypool ran out, please call keypoolrefill first</source> + <translation>Error: Keypool ran out, please call keypoolrefill first</translation> + </message> + <message> + <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source> + <translation>Fee rate (%s) is lower than the minimum fee rate setting (%s)</translation> + </message> + <message> + <source>Invalid -onion address or hostname: '%s'</source> + <translation>Invalid -onion address or hostname: '%s'</translation> + </message> + <message> + <source>Invalid -proxy address or hostname: '%s'</source> + <translation>Invalid -proxy address or hostname: '%s'</translation> + </message> + <message> + <source>Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)</source> + <translation>Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)</translation> + </message> + <message> + <source>Invalid netmask specified in -whitelist: '%s'</source> + <translation>Invalid netmask specified in -whitelist: '%s'</translation> + </message> + <message> + <source>Need to specify a port with -whitebind: '%s'</source> + <translation>Need to specify a port with -whitebind: '%s'</translation> + </message> + <message> + <source>No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>.</source> + <translation>No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>.</translation> + </message> + <message> + <source>Prune mode is incompatible with -blockfilterindex.</source> + <translation>Prune mode is incompatible with -blockfilterindex.</translation> + </message> + <message> + <source>Reducing -maxconnections from %d to %d, because of system limitations.</source> + <translation>Reducing -maxconnections from %d to %d, because of system limitations.</translation> + </message> + <message> + <source>Section [%s] is not recognized.</source> + <translation>Section [%s] is not recognized.</translation> + </message> + <message> <source>Signing transaction failed</source> <translation>La transacción de firma falló</translation> </message> <message> + <source>Specified -walletdir "%s" does not exist</source> + <translation>Specified -walletdir "%s" does not exist</translation> + </message> + <message> + <source>Specified -walletdir "%s" is a relative path</source> + <translation>Specified -walletdir "%s" is a relative path</translation> + </message> + <message> + <source>Specified -walletdir "%s" is not a directory</source> + <translation>Specified -walletdir "%s" is not a directory</translation> + </message> + <message> + <source>The specified config file %s does not exist +</source> + <translation>The specified config file %s does not exist +</translation> + </message> + <message> <source>The transaction amount is too small to pay the fee</source> <translation>El monto de la transacción es demasiado pequeño para pagar la tarifa</translation> </message> @@ -1855,18 +3937,58 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>La transacción es demasiado grande</translation> </message> <message> + <source>Unable to bind to %s on this computer (bind returned error %s)</source> + <translation>Unable to bind to %s on this computer (bind returned error %s)</translation> + </message> + <message> + <source>Unable to create the PID file '%s': %s</source> + <translation>Unable to create the PID file '%s': %s</translation> + </message> + <message> <source>Unable to generate initial keys</source> <translation>Incapaz de generar claves iniciales</translation> </message> <message> + <source>Unknown -blockfilterindex value %s.</source> + <translation>Unknown -blockfilterindex value %s.</translation> + </message> + <message> <source>Verifying wallet(s)...</source> <translation>Verificando la(s) cartera(s)...</translation> </message> <message> + <source>Warning: unknown new rules activated (versionbit %i)</source> + <translation>Warning: unknown new rules activated (versionbit %i)</translation> + </message> + <message> + <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source> + <translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation> + </message> + <message> <source>This is the transaction fee you may pay when fee estimates are not available.</source> <translation>Esta es la tarifa de transacción que puede pagar cuando no se dispone de estimaciones de tarifas.</translation> </message> <message> + <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source> + <translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation> + </message> + <message> + <source>%s is set very high!</source> + <translation>%s is set very high!</translation> + </message> + <message> + <source>Error loading wallet %s. Duplicate -wallet filename specified.</source> + <translation>Error loading wallet %s. Duplicate -wallet filename specified.</translation> + </message> + <message> + <source>Starting network threads...</source> + <translation>Starting network threads...</translation> + </message> + <message> + <source>The wallet will avoid paying less than the minimum relay fee.</source> + <translation>The wallet will avoid paying less than the minimum relay fee.</translation> + </message> + <message> <source>This is the minimum transaction fee you pay on every transaction.</source> <translation>Esta es la tarifa de transacción mínima que se paga en cada transacción.</translation> </message> @@ -1879,14 +4001,34 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Los montos de las transacciones no deben ser negativos</translation> </message> <message> + <source>Transaction has too long of a mempool chain</source> + <translation>Transaction has too long of a mempool chain</translation> + </message> + <message> <source>Transaction must have at least one recipient</source> <translation>La transacción debe tener al menos un destinatario</translation> </message> <message> + <source>Unknown network specified in -onlynet: '%s'</source> + <translation>Unknown network specified in -onlynet: '%s'</translation> + </message> + <message> <source>Insufficient funds</source> <translation>Fondos insuficientes</translation> </message> <message> + <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source> + <translation>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</translation> + </message> + <message> + <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source> + <translation>Warning: Private keys detected in wallet {%s} with disabled private keys</translation> + </message> + <message> + <source>Cannot write to data directory '%s'; check permissions.</source> + <translation>Cannot write to data directory '%s'; check permissions.</translation> + </message> + <message> <source>Loading block index...</source> <translation>Cargando indice de bloques... </translation> </message> @@ -1895,6 +4037,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI) <translation>Cargando billetera...</translation> </message> <message> + <source>Cannot downgrade wallet</source> + <translation>Cannot downgrade wallet</translation> + </message> + <message> + <source>Rescanning...</source> + <translation>Rescanning...</translation> + </message> + <message> <source>Done loading</source> <translation>Carga completa</translation> </message> diff --git a/src/qt/locale/bitcoin_es_VE.ts b/src/qt/locale/bitcoin_es_VE.ts index c68c72fa4f..a216f0f8e0 100644 --- a/src/qt/locale/bitcoin_es_VE.ts +++ b/src/qt/locale/bitcoin_es_VE.ts @@ -132,6 +132,10 @@ <translation>Repita la nueva contraseña</translation> </message> <message> + <source>Show passphrase</source> + <translation>Mostrar la frase de contraseña</translation> + </message> + <message> <source>Encrypt wallet</source> <translation>Cifrar monedero</translation> </message> @@ -172,6 +176,14 @@ <translation>Monedero cifrado</translation> </message> <message> + <source>Wallet to be encrypted</source> + <translation>Billetera a ser cifrada</translation> + </message> + <message> + <source>Your wallet is now encrypted. </source> + <translation>Su billetera está ahora cifrada</translation> + </message> + <message> <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source> <translation>IMPORTANTE: Algunas copias de seguridad que hayas hecho de tu archivo de billetera deberían ser reemplazadas con la billetera encriptada generada recientemente. Por razones de seguridad, las copias de seguridad previas del archivo de billetera sin cifrar serán inútiles tan pronto uses la nueva billetera encriptada.</translation> </message> @@ -274,6 +286,18 @@ <translation>Abrir URI...</translation> </message> <message> + <source>Create Wallet...</source> + <translation>Crear Billetera...</translation> + </message> + <message> + <source>Create a new wallet</source> + <translation>Crear una nueva billetera</translation> + </message> + <message> + <source>Network activity disabled.</source> + <translation>Actividad de red deshabilitada.</translation> + </message> + <message> <source>Reindexing blocks on disk...</source> <translation>Reindexando bloques en disco...</translation> </message> @@ -386,6 +410,10 @@ <translation>Cerrar monedero</translation> </message> <message> + <source>default wallet</source> + <translation>billetera por defecto</translation> + </message> + <message> <source>No wallets available</source> <translation>Monederos no disponibles</translation> </message> @@ -695,6 +723,10 @@ </context> <context> <name>OpenWalletActivity</name> + <message> + <source>default wallet</source> + <translation>billetera por defecto</translation> + </message> </context> <context> <name>OptionsDialog</name> @@ -1448,14 +1480,22 @@ </context> <context> <name>WalletFrame</name> - </context> + <message> + <source>Create a new wallet</source> + <translation>Crear una nueva billetera</translation> + </message> +</context> <context> <name>WalletModel</name> <message> <source>Send Coins</source> <translation>Enviar monedas</translation> </message> - </context> + <message> + <source>default wallet</source> + <translation>billetera por defecto</translation> + </message> +</context> <context> <name>WalletView</name> <message> @@ -1471,6 +1511,10 @@ <translation>Error</translation> </message> <message> + <source>Backup Wallet</source> + <translation>Billetera de Respaldo</translation> + </message> + <message> <source>Backup Failed</source> <translation>Copia de seguridad fallida</translation> </message> @@ -1486,7 +1530,11 @@ <source>The wallet data was successfully saved to %1.</source> <translation>Los datos de la billetera fueron guardados exitosamente al %1</translation> </message> - </context> + <message> + <source>Cancel</source> + <translation>Cancelar</translation> + </message> +</context> <context> <name>bitcoin-core</name> <message> diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts index e33c63f50e..95d987015d 100644 --- a/src/qt/locale/bitcoin_fa.ts +++ b/src/qt/locale/bitcoin_fa.ts @@ -7,7 +7,7 @@ </message> <message> <source>Create a new address</source> - <translation>ساخت یک آدرس جدید</translation> + <translation>ایجاد یک آدرس جدید</translation> </message> <message> <source>&New</source> @@ -515,6 +515,14 @@ <translation>کیف پول را ببندید</translation> </message> <message> + <source>Close All Wallets...</source> + <translation>همهی کیف پولها را ببند...</translation> + </message> + <message> + <source>Close all wallets</source> + <translation>همهی کیف پولها را ببند</translation> + </message> + <message> <source>default wallet</source> <translation>کیف پول پیشفرض</translation> </message> @@ -622,6 +630,10 @@ <source>Wallet is <b>encrypted</b> and currently <b>locked</b></source> <translation>wallet رمزگذاری شد و در حال حاضر قفل است</translation> </message> + <message> + <source>Original message:</source> + <translation>پیام اصلی:</translation> + </message> </context> <context> <name>CoinControlDialog</name> @@ -1021,6 +1033,10 @@ <context> <name>OpenWalletActivity</name> <message> + <source>Open wallet failed</source> + <translation>بازکردن کیف پول به مشکل خورده است</translation> + </message> + <message> <source>Open wallet warning</source> <translation>هشدار باز کردن کیف پول</translation> </message> @@ -1085,6 +1101,10 @@ <translation>حرفهای</translation> </message> <message> + <source>Enable coin &control features</source> + <translation>فعال کردن قابلیت سکه و کنترل</translation> + </message> + <message> <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source> <translation>باز کردن خودکار درگاه شبکهٔ بیتکوین روی روترها. تنها زمانی کار میکند که روتر از پروتکل UPnP پشتیبانی کند و این پروتکل فعال باشد.</translation> </message> @@ -1291,6 +1311,26 @@ <translation>تگفتگو</translation> </message> <message> + <source>Copy to Clipboard</source> + <translation>کپی کردن</translation> + </message> + <message> + <source>Save...</source> + <translation>ذخیره...</translation> + </message> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Unknown error processing transaction.</source> + <translation>مشکل نامشخصی در پردازش عملیات رخ داده.</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>ذخیره اطلاعات عملیات</translation> + </message> + <message> <source>Total Amount</source> <translation>میزان کل</translation> </message> @@ -1298,7 +1338,19 @@ <source>or</source> <translation>یا</translation> </message> - </context> + <message> + <source>Transaction still needs signature(s).</source> + <translation>عملیات هنوز به امضا(ها) نیاز دارد.</translation> + </message> + <message> + <source>(But this wallet cannot sign transactions.)</source> + <translation>(اما این کیفپول نمیتواند عملیاتها را امضا کند.)</translation> + </message> + <message> + <source>Transaction status is unknown.</source> + <translation>وضعیت عملیات نامشخص است.</translation> + </message> +</context> <context> <name>PaymentServer</name> <message> @@ -1598,6 +1650,10 @@ <translation>پنجره گره</translation> </message> <message> + <source>Current block height</source> + <translation>ارتفاع فعلی بلوک</translation> + </message> + <message> <source>Decrease font size</source> <translation>کاهش دادن اندازه فونت</translation> </message> @@ -1784,6 +1840,14 @@ <context> <name>ReceiveRequestDialog</name> <message> + <source>Request payment to ...</source> + <translation>درخواست واریز به ...</translation> + </message> + <message> + <source>Address:</source> + <translation>آدرسها:</translation> + </message> + <message> <source>Amount:</source> <translation>میزان وجه:</translation> </message> @@ -1958,6 +2022,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>گرد و غبار یا داست:</translation> </message> <message> + <source>Hide transaction fee settings</source> + <translation>تنظیمات مخفی کردن کارمزد عملیات</translation> + </message> + <message> <source>Confirmation time target:</source> <translation>هدف زمانی تایید شدن:</translation> </message> @@ -2022,6 +2090,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>آیا برای ارسال کردن یا فرستادن مطمئن هستید؟</translation> </message> <message> + <source>Save Transaction Data</source> + <translation>ذخیره اطلاعات عملیات</translation> + </message> + <message> <source>or</source> <translation>یا</translation> </message> @@ -2322,6 +2394,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>باز تا %1</translation> </message> <message> + <source>abandoned</source> + <translation>رها شده</translation> + </message> + <message> <source>%1/unconfirmed</source> <translation>%1/تأیید نشده</translation> </message> @@ -2472,6 +2548,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>تایید نشده</translation> </message> <message> + <source>Abandoned</source> + <translation>رهاشده</translation> + </message> + <message> <source>Confirmed (%1 confirmations)</source> <translation>تأیید شده (%1 تأییدیه)</translation> </message> @@ -2692,6 +2772,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <source>Are you sure you wish to close the wallet <i>%1</i>?</source> <translation>آیا برای بستن کیف پول مطمئن هستید<i> %1 </i> ؟</translation> </message> + <message> + <source>Close all wallets</source> + <translation>همهی کیف پولها را ببند</translation> + </message> </context> <context> <name>WalletFrame</name> diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts index 656374b71d..6d5d9c9e2e 100644 --- a/src/qt/locale/bitcoin_fi.ts +++ b/src/qt/locale/bitcoin_fi.ts @@ -70,6 +70,12 @@ <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. +Signing is only possible with addresses of the type 'legacy'.</source> + <translation>Nämä ovat Bitcoin-osoitteesi maksujen vastaanottoa varten. Käytä painiketta "Luo uusi vastaanotto-osoite" vastaanottovälilehdessä luodaksesi uusia osoitteita. +Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translation> + </message> + <message> <source>&Copy Address</source> <translation>&Kopioi osoite</translation> </message> @@ -478,6 +484,22 @@ <translation>Rahansiirtohistoria on ajan tasalla</translation> </message> <message> + <source>&Load PSBT from file...</source> + <translation>&Lataa PSBT (osittain allekirjoitettu bitcoin-siirto) tiedostosta...</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction</source> + <translation>Lataa osittain allekirjoitettu bitcoin-siirtotapahtuma</translation> + </message> + <message> + <source>Load PSBT from clipboard...</source> + <translation>Lataa PSBT (osittain allekirjoitettu bitcoin-siirto) leikepöydältä...</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction from clipboard</source> + <translation>Lataa osittain allekirjoitettu bitcoin-siirtotapahtuma leikepöydältä</translation> + </message> + <message> <source>Node window</source> <translation>Solmu ikkuna</translation> </message> @@ -514,10 +536,26 @@ <translation>Sulje lompakko</translation> </message> <message> + <source>Close All Wallets...</source> + <translation>Sulje kaikki lompakot...</translation> + </message> + <message> + <source>Close all wallets</source> + <translation>Sulje kaikki lompakot</translation> + </message> + <message> <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source> <translation>Näytä %1 ohjeet saadaksesi listan mahdollisista Bitcoinin komentorivivalinnoista</translation> </message> <message> + <source>&Mask values</source> + <translation>&Naamioi arvot</translation> + </message> + <message> + <source>Mask the values in the Overview tab</source> + <translation>Naamioi arvot Yhteenveto-välilehdessä</translation> + </message> + <message> <source>default wallet</source> <translation>oletuslompakko</translation> </message> @@ -625,7 +663,15 @@ <source>Wallet is <b>encrypted</b> and currently <b>locked</b></source> <translation>Lompakko on <b>salattu</b> ja tällä hetkellä <b>lukittuna</b></translation> </message> - </context> + <message> + <source>Original message:</source> + <translation>Alkuperäinen viesti:</translation> + </message> + <message> + <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source> + <translation>Peruuttamaton virhe on tapahtunut. %1 ei voi enää jatkaa turvallisesti ja sammutetaan.</translation> + </message> +</context> <context> <name>CoinControlDialog</name> <message> @@ -827,6 +873,14 @@ <translation>Luo tyhjä lompakko</translation> </message> <message> + <source>Use descriptors for scriptPubKey management</source> + <translation>Käytä kuvaajia sciptPubKeyn hallinnointiin</translation> + </message> + <message> + <source>Descriptor Wallet</source> + <translation>Kuvaajalompakko</translation> + </message> + <message> <source>Create</source> <translation>Luo</translation> </message> @@ -1303,6 +1357,14 @@ <translation>Näytetäänkö kolikkokontrollin ominaisuuksia vai ei</translation> </message> <message> + <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source> + <translation>Yhdistä Bitcoin-verkkoon erillisen SOCKS5-välityspalvelimen kautta Torin onion-palveluja varten.</translation> + </message> + <message> + <source>Use separate SOCKS&5 proxy to reach peers via Tor onion services:</source> + <translation>Käytä erillistä SOCKS&5-välityspalvelinta tavoittaaksesi vertaisia Torin onion-palvelujen kautta:</translation> + </message> + <message> <source>&Third party transaction URLs</source> <translation>&Kolmannen osapuolen rahansiirto URL:t</translation> </message> @@ -1437,7 +1499,11 @@ <source>Current total balance in watch-only addresses</source> <translation>Nykyinen tase seurattavassa osoitetteissa</translation> </message> - </context> + <message> + <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</source> + <translation>Yksityisyysmoodi aktivoitu Yhteenveto-välilehdestä. Paljastaaksesi arvot raksi pois Asetukset->Naamioi arvot.</translation> + </message> +</context> <context> <name>PSBTOperationsDialog</name> <message> @@ -1445,6 +1511,86 @@ <translation>Dialogi</translation> </message> <message> + <source>Sign Tx</source> + <translation>Allekirjoita Tx</translation> + </message> + <message> + <source>Broadcast Tx</source> + <translation>Lähetä Tx</translation> + </message> + <message> + <source>Copy to Clipboard</source> + <translation>Kopioi leikepöydälle</translation> + </message> + <message> + <source>Save...</source> + <translation>Tallenna...</translation> + </message> + <message> + <source>Close</source> + <translation>Sulje</translation> + </message> + <message> + <source>Failed to load transaction: %1</source> + <translation>Siirtoa ei voitu ladata: %1</translation> + </message> + <message> + <source>Failed to sign transaction: %1</source> + <translation>Siirtoa ei voitu allekirjoittaa: %1</translation> + </message> + <message> + <source>Could not sign any more inputs.</source> + <translation>Syötteitä ei voitu enää allekirjoittaa.</translation> + </message> + <message> + <source>Signed %1 inputs, but more signatures are still required.</source> + <translation>%1 syötettä allekirjoitettiin, mutta lisää allekirjoituksia tarvitaan.</translation> + </message> + <message> + <source>Signed transaction successfully. Transaction is ready to broadcast.</source> + <translation>Siirto allekirjoitettiin onnistuneesti. Siirto on valmis lähetettäväksi.</translation> + </message> + <message> + <source>Unknown error processing transaction.</source> + <translation>Siirron käsittelyssä tapahtui tuntematon virhe.</translation> + </message> + <message> + <source>Transaction broadcast successfully! Transaction ID: %1</source> + <translation>Siirto lähetettiin onnistuneesti! Siirtotunniste: %1</translation> + </message> + <message> + <source>Transaction broadcast failed: %1</source> + <translation>Siirron lähetys epäonnstui: %1</translation> + </message> + <message> + <source>PSBT copied to clipboard.</source> + <translation>PSBT (osittain allekirjoitettu bitcoin-siirto) kopioitiin leikepöydälle.</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>Tallenna siirtotiedot</translation> + </message> + <message> + <source>Partially Signed Transaction (Binary) (*.psbt)</source> + <translation>Osittain tallennettu siirto (binääri) (*.psbt)</translation> + </message> + <message> + <source>PSBT saved to disk.</source> + <translation>PSBT (osittain tallennettu bitcoin-siirto) tallennettiin levylle.</translation> + </message> + <message> + <source> * Sends %1 to %2</source> + <translation>*Lähettää %1'n kohteeseen %2</translation> + </message> + <message> + <source>Unable to calculate transaction fee or total transaction amount.</source> + <translation>Siirtokuluja tai siirron lopullista määrää ei voitu laskea.</translation> + </message> + <message> + <source>Pays transaction fee: </source> + <translation>Maksaa siirtokulut:</translation> + </message> + <message> <source>Total Amount</source> <translation>Yhteensä</translation> </message> @@ -1452,7 +1598,35 @@ <source>or</source> <translation>tai</translation> </message> - </context> + <message> + <source>Transaction has %1 unsigned inputs.</source> + <translation>Siirrossa on %1 allekirjoittamatonta syötettä.</translation> + </message> + <message> + <source>Transaction is missing some information about inputs.</source> + <translation>Siirto kaipaa tietoa syötteistä.</translation> + </message> + <message> + <source>Transaction still needs signature(s).</source> + <translation>Siirto tarvitsee vielä allekirjoituksia.</translation> + </message> + <message> + <source>(But this wallet cannot sign transactions.)</source> + <translation>(Mutta tämä lompakko ei voi allekirjoittaa siirtoja.)</translation> + </message> + <message> + <source>(But this wallet does not have the right keys.)</source> + <translation>(Mutta tällä lompakolla ei ole oikeita avaimia.)</translation> + </message> + <message> + <source>Transaction is fully signed and ready for broadcast.</source> + <translation>Siirto on täysin allekirjoitettu ja valmis lähetettäväksi.</translation> + </message> + <message> + <source>Transaction status is unknown.</source> + <translation>Siirron tila on tuntematon.</translation> + </message> +</context> <context> <name>PaymentServer</name> <message> @@ -1618,6 +1792,10 @@ <translation>Virhe: %1</translation> </message> <message> + <source>Error initializing settings: %1</source> + <translation>Virhe alustaessa asetuksia: %1</translation> + </message> + <message> <source>%1 didn't yet exit safely...</source> <translation>%1 ei vielä sulkeutunut turvallisesti...</translation> </message> @@ -1796,6 +1974,10 @@ <translation>Solmun näkymä</translation> </message> <message> + <source>Current block height</source> + <translation>Lohkon nykyinen korkeus</translation> + </message> + <message> <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source> <translation>Avaa %1 -debug-loki tämänhetkisestä data-hakemistosta. Tämä voi viedä muutaman sekunnin suurille lokitiedostoille.</translation> </message> @@ -1808,6 +1990,10 @@ <translation>Suurenna fontin kokoa</translation> </message> <message> + <source>Permissions</source> + <translation>Luvat</translation> + </message> + <message> <source>Services</source> <translation>Palvelut</translation> </message> @@ -2062,10 +2248,22 @@ <source>Could not unlock wallet.</source> <translation>Lompakkoa ei voitu avata.</translation> </message> - </context> + <message> + <source>Could not generate new %1 address</source> + <translation>Uutta %1-osoitetta ei voitu luoda</translation> + </message> +</context> <context> <name>ReceiveRequestDialog</name> <message> + <source>Request payment to ...</source> + <translation>Pyydä maksua osoitteeseen...</translation> + </message> + <message> + <source>Address:</source> + <translation>Osoite:</translation> + </message> + <message> <source>Amount:</source> <translation>Määrä:</translation> </message> @@ -2344,6 +2542,22 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Oletko varma, että haluat lähettää?</translation> </message> <message> + <source>Create Unsigned</source> + <translation>Luo allekirjoittamaton</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>Tallenna siirtotiedot</translation> + </message> + <message> + <source>Partially Signed Transaction (Binary) (*.psbt)</source> + <translation>Osittain tallennettu siirtotapahtuma (binääri) (*.psbt)</translation> + </message> + <message> + <source>PSBT saved</source> + <translation>PSBT tallennettu</translation> + </message> + <message> <source>or</source> <translation>tai</translation> </message> @@ -2352,6 +2566,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Voit korottaa palkkiota myöhemmin (osoittaa Replace-By-Fee:tä, BIP-125).</translation> </message> <message> + <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can save or copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source> + <translation>Ole hyvä ja tarkista siirtoehdotuksesi. Tämä luo osittain allekirjoitetun Bitcoin-siirron (PBST), jonka voit tallentaa tai kopioida ja sitten allekirjoittaa esim. verkosta irrannaisella %1-lompakolla tai PBST-yhteensopivalla laitteistolompakolla.</translation> + </message> + <message> <source>Please, review your transaction.</source> <translation>Tarkistathan siirtosi.</translation> </message> @@ -3161,10 +3379,26 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source> <translation>Lompakon sulkeminen liian pitkäksi aikaa saattaa johtaa tarpeeseen synkronoida koko ketju uudelleen, mikäli karsinta on käytössä.</translation> </message> - </context> + <message> + <source>Close all wallets</source> + <translation>Sulje kaikki lompakot</translation> + </message> + <message> + <source>Are you sure you wish to close all wallets?</source> + <translation>Haluatko varmasti sulkea kaikki lompakot?</translation> + </message> +</context> <context> <name>WalletFrame</name> <message> + <source>No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR -</source> + <translation>Lompakkoa ei ladattu. +Siirry osioon Tiedosto > Avaa lompakko ladataksesi lompakon. +- TAI -</translation> + </message> + <message> <source>Create a new wallet</source> <translation>Luo uusi lompakko</translation> </message> @@ -3243,6 +3477,26 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Virhe</translation> </message> <message> + <source>Unable to decode PSBT from clipboard (invalid base64)</source> + <translation>PBST-ää ei voitu tulkita leikepöydältä (kelpaamaton base64)</translation> + </message> + <message> + <source>Load Transaction Data</source> + <translation>Lataa siirtotiedot</translation> + </message> + <message> + <source>Partially Signed Transaction (*.psbt)</source> + <translation>Osittain allekirjoitettu siirto (*.pbst)</translation> + </message> + <message> + <source>PSBT file must be smaller than 100 MiB</source> + <translation>PBST-tiedoston tulee olla pienempi kuin 100 mebitavua</translation> + </message> + <message> + <source>Unable to decode PSBT</source> + <translation>PSBT-ää ei voitu tulkita</translation> + </message> + <message> <source>Backup Wallet</source> <translation>Varmuuskopioi lompakko</translation> </message> @@ -3310,6 +3564,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Virhe luettaessa %s! Avaimet luetttiin oikein, mutta rahansiirtotiedot tai osoitekirjan sisältö saattavat olla puutteellisia tai vääriä.</translation> </message> <message> + <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source> + <translation>Useampi onion bind -osoite on tarjottu. Automaattisesti luotua Torin onion-palvelua varten käytetään %s.</translation> + </message> + <message> <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> <translation>Tarkistathan että tietokoneesi päivämäärä ja kellonaika ovat oikeassa! Jos kellosi on väärässä, %s ei toimi oikein.</translation> </message> @@ -3318,6 +3576,14 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Ole hyvä ja avusta, jos %s on mielestäsi hyödyllinen. Vieraile %s saadaksesi lisää tietoa ohjelmistosta.</translation> </message> <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase: Lausekkeen valmistelu sqlite-lompakkokaavioversion %s noutamista varten epäonnistui</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source> + <translation>SQLiteDatabase: Lausekkeen valmistelu sovellustunnisteen %s noutamista varten epäonnistui</translation> + </message> + <message> <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> <translation>Lohkotietokanta sisältää lohkon, joka vaikuttaa olevan tulevaisuudesta. Tämä saattaa johtua tietokoneesi virheellisesti asetetuista aika-asetuksista. Rakenna lohkotietokanta uudelleen vain jos olet varma, että tietokoneesi päivämäärä ja aika ovat oikein.</translation> </message> @@ -3422,6 +3688,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Lompakkoa ei voitu tarkastaa alustuksen yhteydessä.</translation> </message> <message> + <source>Failed to verify database</source> + <translation>Tietokannan todennus epäonnistui</translation> + </message> + <message> <source>Importing...</source> <translation>Tuodaan...</translation> </message> @@ -3446,6 +3716,30 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Virheellinen määrä -fallbackfee=<amount>: '%s'</translation> </message> <message> + <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source> + <translation>SQLiteDatabase: Lausekkeen suorittaminen tietokannan %s todentamista varten epäonnistui</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase: sqlite-lompakkokaavioversion %s nouto epäonnistui</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch the application id: %s</source> + <translation>SQLiteDatabase: Sovellustunnisteen %s nouto epäonnistui</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source> + <translation>SQLiteDatabase: Lausekkeen valmistelu tietokannan %s todentamista varten epäonnistui</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>SQLiteDatabase: Tietokantatodennusvirheen %s luku epäonnistui</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>SQLiteDatabase: Odottamaton sovellustunniste. %u odotettu, %u saatu</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation>Määrättyä lohkohakemistoa "%s" ei ole olemassa.</translation> </message> @@ -3530,6 +3824,14 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Virhe: Saapuvien yhteyksien kuuntelu epäonnistui (kuuntelu palautti virheen %s)</translation> </message> <message> + <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source> + <translation>%s on vioittunut. Yritä käyttää lompakkotyökalua bitcoin-wallet pelastaaksesi sen tai palauttaa varmuuskopio.</translation> + </message> + <message> + <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source> + <translation>Muuta kuin HD-jaettua lompakkoa ei voi päivittää ilman päivitystä tukemaan esijaettua avainvarastoa. Käytä versiota 169900 tai älä kaytä määritettyä versiota.</translation> + </message> + <message> <source>Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source> <translation>Virheellinen summa -maxtxfee =: '%s' (täytyy olla vähintään %s minrelay-kulu, jotta estetään jumiutuneet siirtotapahtumat)</translation> </message> @@ -3538,10 +3840,34 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Siirtomäärä on liian pieni lähetettäväksi kulun vähentämisen jälkeen.</translation> </message> <message> + <source>This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet</source> + <translation>Tämä virhe voi tapahtua, jos tämä lompakko ei sammutettu siististi ja ladattiin viimeksi uudempaa Berkeley DB -versiota käyttäneellä ohjelmalla. Tässä tapauksessa käytä sitä ohjelmaa, joka viimeksi latasi tämän lompakon.</translation> + </message> + <message> + <source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source> + <translation>Tämä on maksimimäärä, jonka maksat siirtokuluina (normaalien kulujen lisäksi) pistääksesi osittaiskulutuksen välttämisen tavallisen kolikonvalinnan edelle.</translation> + </message> + <message> + <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source> + <translation>Siirtoon tarvitaan vaihto-osoite, muttemme voi luoda sitä. Ole hyvä ja kutsu ensin keypoolrefill.</translation> + </message> + <message> <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source> <translation>Palataksesi karsimattomaan tilaan joudut uudelleenrakentamaan tietokannan -reindex -valinnalla. Tämä lataa koko lohkoketjun uudestaan.</translation> </message> <message> + <source>A fatal internal error occurred, see debug.log for details</source> + <translation>Kriittinen sisäinen virhe kohdattiin, katso debug.log lisätietoja varten</translation> + </message> + <message> + <source>Cannot set -peerblockfilters without -blockfilterindex.</source> + <translation>-peerblockfiltersiä ei voida asettaa ilman -blockfilterindexiä.</translation> + </message> + <message> + <source>Disk space is too low!</source> + <translation>Liian vähän levytilaa!</translation> + </message> + <message> <source>Error reading from database, shutting down.</source> <translation>Virheitä tietokantaa luettaessa, ohjelma pysäytetään.</translation> </message> @@ -3554,6 +3880,14 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Virhe: levytila vähissä kohteessa %s</translation> </message> <message> + <source>Error: Keypool ran out, please call keypoolrefill first</source> + <translation>Virhe: Avainallas tyhjentyi, ole hyvä ja kutsu keypoolrefill ensin</translation> + </message> + <message> + <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source> + <translation>Kulutaso (%s) on alempi, kuin minimikulutasoasetus (%s)</translation> + </message> + <message> <source>Invalid -onion address or hostname: '%s'</source> <translation>Virheellinen -onion osoite tai isäntänimi: '%s'</translation> </message> @@ -3574,6 +3908,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t <translation>Pitää määritellä portti argumentilla -whitebind: '%s'</translation> </message> <message> + <source>No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>.</source> + <translation>Välityspalvelinta ei ole määritetty. Käytä -proxy=<ip> tai -proxy=<ip:port>.</translation> + </message> + <message> <source>Prune mode is incompatible with -blockfilterindex.</source> <translation>Karsintatila ei ole yhteensopiva -blockfilterindex valinnan kanssa</translation> </message> diff --git a/src/qt/locale/bitcoin_fil.ts b/src/qt/locale/bitcoin_fil.ts index bc84d0bc4a..1051db437b 100644 --- a/src/qt/locale/bitcoin_fil.ts +++ b/src/qt/locale/bitcoin_fil.ts @@ -132,6 +132,10 @@ <translation>Ulitin ang bagong passphrase</translation> </message> <message> + <source>Show passphrase</source> + <translation>Ipakita ang Passphrase</translation> + </message> + <message> <source>Encrypt wallet</source> <translation>I-encrypt ang walet.</translation> </message> @@ -172,6 +176,30 @@ <translation>Naka-encrypt ang walet.</translation> </message> <message> + <source>Enter the new passphrase for the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>.</source> + <translation>Ipasok ang bagong passphrase para sa wallet. (1)Mangyaring gumamit ng isang passphrase na(2) sampu o higit pang mga random na character(2), o (3)walo o higit pang mga salita(3).</translation> + </message> + <message> + <source>Enter the old passphrase and new passphrase for the wallet.</source> + <translation>Ipasok ang lumang passphrase at bagong passphrase para sa pitaka.</translation> + </message> + <message> + <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source> + <translation>Tandaan na ang pag-encrypt ng iyong pitaka ay hindi maaaring ganap na maprotektahan ang iyong mga bitcoin mula sa pagnanakaw ng malware na nahahawa sa iyong computer.</translation> + </message> + <message> + <source>Wallet to be encrypted</source> + <translation>Ang naka-encrypt na wallet</translation> + </message> + <message> + <source>Your wallet is about to be encrypted. </source> + <translation>Malapit na ma-encrypt ang iyong pitaka.</translation> + </message> + <message> + <source>Your wallet is now encrypted. </source> + <translation>Ang iyong wallet ay naka-encrypt na ngayon.</translation> + </message> + <message> <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source> <translation>MAHALAGA: Anumang nakaraang mga backup na ginawa mo sa iyong walet file ay dapat mapalitan ng bagong-buong, naka-encrypt na walet file. Para sa mga kadahilanang pangseguridad, ang mga nakaraang pag-backup ng hindi naka-encrypt na walet file ay mapagwawalang-silbi sa sandaling simulan mong gamitin ang bagong naka-encrypt na walet.</translation> </message> @@ -294,6 +322,14 @@ <translation>Buksan ang URI...</translation> </message> <message> + <source>Create Wallet...</source> + <translation>Gumawa ng Pitaka</translation> + </message> + <message> + <source>Create a new wallet</source> + <translation>Gumawa ng Bagong Pitaka</translation> + </message> + <message> <source>Wallet:</source> <translation>Walet:</translation> </message> @@ -434,6 +470,10 @@ <translation>Napapanahon</translation> </message> <message> + <source>Node window</source> + <translation>Bintana ng Node</translation> + </message> + <message> <source>&Sending addresses</source> <translation>Mga address para sa pagpapadala</translation> </message> @@ -719,10 +759,34 @@ </context> <context> <name>CreateWalletActivity</name> - </context> + <message> + <source>Create wallet failed</source> + <translation>Nabigo ang Pag likha ng Pitaka</translation> + </message> + <message> + <source>Create wallet warning</source> + <translation>Gumawa ng Babala ng Pitaka</translation> + </message> +</context> <context> <name>CreateWalletDialog</name> <message> + <source>Create Wallet</source> + <translation>Gumawa ng Pitaka</translation> + </message> + <message> + <source>Wallet Name</source> + <translation>Pangalan ng Pitaka</translation> + </message> + <message> + <source>Disable Private Keys</source> + <translation>Huwag paganahin ang Privbadong susi</translation> + </message> + <message> + <source>Make Blank Wallet</source> + <translation>Gumawa ng Blankong Pitaka</translation> + </message> + <message> <source>Create</source> <translation>Gumawa</translation> </message> @@ -934,6 +998,10 @@ <translation>Itago</translation> </message> <message> + <source>Esc</source> + <translation>Esc</translation> + </message> + <message> <source>Unknown. Syncing Headers (%1, %2%)...</source> <translation>Hindi alam. S-in-i-sync ang mga Header (%1, %2%)...</translation> </message> @@ -948,6 +1016,14 @@ <context> <name>OpenWalletActivity</name> <message> + <source>Open wallet failed</source> + <translation>Nabigo ang bukas na pitaka</translation> + </message> + <message> + <source>Open wallet warning</source> + <translation>Buksan ang babala sa pitaka</translation> + </message> + <message> <source>default wallet</source> <translation>walet na default</translation> </message> @@ -1485,6 +1561,10 @@ <translation>Kamalian sa pag-e-encode ng URI sa QR Code.</translation> </message> <message> + <source>QR code support not available.</source> + <translation>Hindi magagamit ang suporta ng QR code.</translation> + </message> + <message> <source>Save QR Code</source> <translation>I-save ang QR Code</translation> </message> @@ -1616,10 +1696,23 @@ <translation>Mga block na na-sync</translation> </message> <message> + <source>The mapped Autonomous System used for diversifying peer selection.</source> + <translation>Ginamit ang na-map na Autonomous System para sa pag-iba-iba ng pagpipilian ng kapwa.</translation> + </message> + <message> + <source>Mapped AS</source> + <translation>Mapa sa AS +</translation> + </message> + <message> <source>User Agent</source> <translation>Ahente ng User</translation> </message> <message> + <source>Node window</source> + <translation>Bintana ng Node</translation> + </message> + <message> <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source> <translation>Buksan ang %1 debug log file mula sa kasalukuyang directoryo ng datos. Maaari itong tumagal ng ilang segundo para sa mga malalaking log file.</translation> </message> @@ -1819,6 +1912,18 @@ <translation>Opsyonal na halaga upang humiling. Iwanan itong walang laman o zero upang hindi humiling ng tiyak na halaga.</translation> </message> <message> + <source>An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</source> + <translation>Isang opsyonal na label upang maiugnay sa bagong address ng pagtanggap (ginamit mo upang makilala ang isang invoice). Nakalakip din ito sa kahilingan sa pagbabayad.</translation> + </message> + <message> + <source>An optional message that is attached to the payment request and may be displayed to the sender.</source> + <translation>Isang opsyonal na mensahe na naka-attach sa kahilingan sa pagbabayad at maaaring ipakita sa nagpadala.</translation> + </message> + <message> + <source>&Create new receiving address</source> + <translation>& Lumikha ng bagong address sa pagtanggap</translation> + </message> + <message> <source>Clear all fields of the form.</source> <translation>Burahin ang laman ng lahat ng patlang ng form.</translation> </message> @@ -2056,6 +2161,10 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng <translation>Dust:</translation> </message> <message> + <source>Hide transaction fee settings</source> + <translation>Itago ang mga Setting ng bayad sa Transaksyon</translation> + </message> + <message> <source>When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> <translation>Kapag mas kaunti ang dami ng transaksyon kaysa sa puwang sa mga blocks, ang mga minero pati na rin ang mga relaying node ay maaaring magpatupad ng minimum na bayad. Ang pagbabayad lamang ng minimum na bayad na ito ay maayos, ngunit malaman na maaari itong magresulta sa hindi kailanmang nagkukumpirmang transaksyon sa sandaling magkaroon ng higit na pangangailangan para sa mga transaksyon ng bitcoin kaysa sa kayang i-proseso ng network.</translation> </message> @@ -2124,10 +2233,18 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng <translation>%1 (%2 mga block)</translation> </message> <message> + <source>Cr&eate Unsigned</source> + <translation>Lumikha ng Unsigned</translation> + </message> + <message> <source>%1 to %2</source> <translation>%1 sa %2</translation> </message> <message> + <source>Do you want to draft this transaction?</source> + <translation>Nais mo bang i-draft ang transaksyong ito?</translation> + </message> + <message> <source>Are you sure you want to send?</source> <translation>Sigurado ka bang nais mong magpadala?</translation> </message> @@ -2156,10 +2273,26 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng <translation>Kabuuang Halaga</translation> </message> <message> + <source>To review recipient list click "Show Details..."</source> + <translation>Upang suriin ang listahan ng tatanggap i-click ang "Ipakita ang Mga Detalye ..."</translation> + </message> + <message> <source>Confirm send coins</source> <translation>Kumpirmahin magpadala ng coins</translation> </message> <message> + <source>Confirm transaction proposal</source> + <translation>Kumpirmahin ang panukala sa transaksyon</translation> + </message> + <message> + <source>Send</source> + <translation>Ipadala</translation> + </message> + <message> + <source>Watch-only balance:</source> + <translation>Balanse lamang sa panonood:</translation> + </message> + <message> <source>The recipient address is not valid. Please recheck.</source> <translation>Ang address ng tatanggap ay hindi wasto. Mangyaring suriin muli.</translation> </message> @@ -2413,6 +2546,10 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng <translation>Kinansela ang pag-unlock ng walet.</translation> </message> <message> + <source>No error</source> + <translation>Walang Kamalian</translation> + </message> + <message> <source>Private key for the entered address is not available.</source> <translation>Hindi magagamit ang private key para sa pinasok na address.</translation> </message> @@ -2916,7 +3053,11 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng </context> <context> <name>WalletFrame</name> - </context> + <message> + <source>Create a new wallet</source> + <translation>Gumawa ng Bagong Pitaka</translation> + </message> +</context> <context> <name>WalletModel</name> <message> @@ -2952,6 +3093,14 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng <translation>Kumpirmahin ang fee bump</translation> </message> <message> + <source>Can't draft transaction.</source> + <translation>Hindi ma-draft ang transaksyon</translation> + </message> + <message> + <source>PSBT copied</source> + <translation>Kinopya ang PSBT</translation> + </message> + <message> <source>Can't sign transaction.</source> <translation>Hindi mapirmahan ang transaksyon.</translation> </message> diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts index 3af091b991..aa30c6a0e7 100644 --- a/src/qt/locale/bitcoin_fr.ts +++ b/src/qt/locale/bitcoin_fr.ts @@ -15,7 +15,7 @@ </message> <message> <source>Copy the currently selected address to the system clipboard</source> - <translation>Copier l’adresse sélectionnée actuellement dans le presse-papiers</translation> + <translation>Copier dans le presse-papiers l’adresse sélectionnée actuellement</translation> </message> <message> <source>&Copy</source> @@ -31,7 +31,7 @@ </message> <message> <source>Enter address or label to search</source> - <translation>Saisir une adresse ou une étiquette à rechercher</translation> + <translation>Saisissez une adresse ou une étiquette à rechercher</translation> </message> <message> <source>Export the data in the current tab to a file</source> @@ -127,7 +127,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>Enter passphrase</source> - <translation>Saisir la phrase de passe</translation> + <translation>Saisissez la phrase de passe</translation> </message> <message> <source>New passphrase</source> @@ -187,7 +187,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>Enter the old passphrase and new passphrase for the wallet.</source> - <translation>Saisir l’ancienne puis la nouvelle phrase de passe du porte-monnaie.</translation> + <translation>Saisissez l’ancienne puis la nouvelle phrase de passe du porte-monnaie.</translation> </message> <message> <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source> @@ -341,7 +341,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>Click to disable network activity.</source> - <translation>Cliquer pour désactiver l’activité réseau.</translation> + <translation>Cliquez pour désactiver l’activité réseau.</translation> </message> <message> <source>Network activity disabled.</source> @@ -349,7 +349,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>Click to enable network activity again.</source> - <translation>Cliquer pour réactiver l’activité réseau.</translation> + <translation>Cliquez pour réactiver l’activité réseau.</translation> </message> <message> <source>Syncing Headers (%1%)...</source> @@ -505,7 +505,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>Open node debugging and diagnostic console</source> - <translation>Ouvrir une console de débogage de noeuds et de diagnostic</translation> + <translation>Ouvrir une console de débogage de nœuds et de diagnostic</translation> </message> <message> <source>&Sending addresses</source> @@ -521,7 +521,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>Open Wallet</source> - <translation>Ouvrir le porte-monnaie</translation> + <translation>Ouvrir un porte-monnaie</translation> </message> <message> <source>Open a wallet</source> @@ -553,7 +553,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>Mask the values in the Overview tab</source> - <translation>Dissimuler les montants sur l'onglet de vue d'ensemble</translation> + <translation>Dissimuler les montants dans l’onglet Vue d’ensemble</translation> </message> <message> <source>default wallet</source> @@ -669,7 +669,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source> - <translation>Une erreur fatale est survenue. %1 ne peut plus continuer de façon sûre et va s'arrêter.</translation> + <translation>Une erreur fatale est survenue. %1 ne peut plus continuer de façon sûre et va s’arrêter.</translation> </message> </context> <context> @@ -1705,7 +1705,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>Enter a Bitcoin address (e.g. %1)</source> - <translation>Saisir une adresse Bitcoin (p. ex. %1)</translation> + <translation>Saisissez une adresse Bitcoin (p. ex. %1)</translation> </message> <message> <source>%1 d</source> @@ -2178,7 +2178,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source> - <translation>Un montant facultatif à demander. Ne rien saisir ou un zéro pour ne pas demander de montant précis.</translation> + <translation>Un montant facultatif à demander. Ne saisissez rien ou un zéro pour ne pas demander de montant précis.</translation> </message> <message> <source>An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</source> @@ -2222,11 +2222,11 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr </message> <message> <source>Remove the selected entries from the list</source> - <translation>Retirer les entrées sélectionnées de la liste</translation> + <translation>Supprimer les entrées sélectionnées de la liste</translation> </message> <message> <source>Remove</source> - <translation>Retirer</translation> + <translation>Supprimer</translation> </message> <message> <source>Copy URI</source> @@ -2411,7 +2411,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par </message> <message> <source>per kilobyte</source> - <translation>par kilo-octet</translation> + <translation>Par kilo-octet</translation> </message> <message> <source>Hide</source> @@ -2467,7 +2467,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par </message> <message> <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source> - <translation>Avec Remplacer-par-des-frais (BIP-125), vous pouvez augmenter les frais de transaction après qu’elle est envoyée. Sans cela, des frais plus élevés peuvent être recommandés pour compenser le risque accru de retard transactionnel.</translation> + <translation>Avec Remplacer-par-des-frais (BIP-125), vous pouvez augmenter les frais d’une transaction après qu’elle est envoyée. Sans cela, des frais plus élevés peuvent être recommandés pour compenser le risque accru de retard transactionnel.</translation> </message> <message> <source>Clear &All</source> @@ -2702,7 +2702,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par </message> <message> <source>Remove this entry</source> - <translation>Retirer cette entrée</translation> + <translation>Supprimer cette entrée</translation> </message> <message> <source>The amount to send in the selected unit</source> @@ -2710,7 +2710,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par </message> <message> <source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source> - <translation>Les frais seront déduits du montant envoyé. Le destinataire recevra moins de bitcoins que le montant saisi dans le champ de montant. Si plusieurs destinataires sont sélectionnés, les frais seront partagés également..</translation> + <translation>Les frais seront déduits du montant envoyé. Le destinataire recevra moins de bitcoins que le montant saisi dans le champ de montant. Si plusieurs destinataires sont sélectionnés, les frais seront partagés également.</translation> </message> <message> <source>S&ubtract fee from amount</source> @@ -2734,7 +2734,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par </message> <message> <source>Enter a label for this address to add it to the list of used addresses</source> - <translation>Saisir une étiquette pour cette adresse afin de l’ajouter à la liste d’adresses utilisées</translation> + <translation>Saisissez une étiquette pour cette adresse afin de l’ajouter à la liste d’adresses utilisées</translation> </message> <message> <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source> @@ -2764,7 +2764,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par <name>SignVerifyMessageDialog</name> <message> <source>Signatures - Sign / Verify a Message</source> - <translation>Signatures - Signer / vérifier un message</translation> + <translation>Signatures – Signer/vérifier un message</translation> </message> <message> <source>&Sign Message</source> @@ -2796,7 +2796,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par </message> <message> <source>Enter the message you want to sign here</source> - <translation>Saisir ici le message que vous désirez signer</translation> + <translation>Saisissez ici le message que vous désirez signer</translation> </message> <message> <source>Signature</source> @@ -2828,7 +2828,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par </message> <message> <source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source> - <translation>Saisir ci-dessous l’adresse du destinataire, le message (s’assurer de copier fidèlement les retours à la ligne, les espaces, les tabulations, etc.) et la signature pour vérifier le message. Faire attention à ne pas déduire davantage de la signature que ce qui est contenu dans le message signé même, pour éviter d’être trompé par une attaque d’homme du milieu. Prendre en compte que cela ne fait que prouver que le signataire reçoit l’adresse et ne peut pas prouver la provenance d’une transaction.</translation> + <translation>Saisissez ci-dessous l’adresse du destinataire, le message (assurez-vous de copier fidèlement les retours à la ligne, les espaces, les tabulations, etc.) et la signature pour vérifier le message. Faites attention à ne pas déduire davantage de la signature que ce qui est contenu dans le message signé même, pour éviter d’être trompé par une attaque de l’intercepteur. Notez que cela ne fait que prouver que le signataire reçoit avec l’adresse et ne peut pas prouver la provenance d’une transaction.</translation> </message> <message> <source>The Bitcoin address the message was signed with</source> @@ -3259,7 +3259,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par </message> <message> <source>Enter address, transaction id, or label to search</source> - <translation>Saisir l’adresse, l’ID de transaction ou l’étiquette à chercher</translation> + <translation>Saisissez l’adresse, l’ID de transaction ou l’étiquette à chercher</translation> </message> <message> <source>Min amount</source> @@ -3370,7 +3370,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par <name>UnitDisplayStatusBarControl</name> <message> <source>Unit to show amounts in. Click to select another unit.</source> - <translation>Unité d’affichage des montants. Cliquer pour choisir une autre unité.</translation> + <translation>Unité d’affichage des montants. Cliquez pour choisir une autre unité.</translation> </message> </context> <context> @@ -3537,7 +3537,7 @@ Accédez à Fichier > Ouvrir un porte-monnaie pour en charger un. <name>bitcoin-core</name> <message> <source>Distributed under the MIT software license, see the accompanying file %s or %s</source> - <translation>Distribué sous la licence MIT d’utilisation d’un logiciel. Consulter le fichier joint %s ou %s</translation> + <translation>Distribué sous la licence MIT d’utilisation d’un logiciel, consultez le fichier joint %s ou %s</translation> </message> <message> <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source> @@ -3557,7 +3557,7 @@ Accédez à Fichier > Ouvrir un porte-monnaie pour en charger un. </message> <message> <source>The %s developers</source> - <translation>Les développeurs de %s</translation> + <translation>Les développeurs de %s</translation> </message> <message> <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source> @@ -3572,16 +3572,32 @@ Accédez à Fichier > Ouvrir un porte-monnaie pour en charger un. <translation>Erreur de lecture de %s. Toutes les clés ont été lues correctement, mais les données de la transaction ou les entrées du carnet d’adresses sont peut-être manquantes ou incorrectes.</translation> </message> <message> + <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source> + <translation>Plus d’une adresse onion de liaison est indiquée. %s sera utilisée pour le service onion de Tor créé automatiquement.</translation> + </message> + <message> <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> <translation>Veuillez vérifier que l’heure et la date de votre ordinateur sont justes. Si votre horloge n’est pas à l’heure, %s ne fonctionnera pas correctement.</translation> </message> <message> <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source> - <translation>Si vous trouvez %s utile, vous pouvez y contribuer. Vous trouverez plus de renseignements au sujet du logiciel sur %s.</translation> + <translation>Si vous trouvez %s utile, veuillez y contribuer. Pour de plus de précisions sur le logiciel, rendez-vous sur %s.</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase : échec de préparation de l’instruction pour récupérer la version du schéma de porte-monnaie sqlite : %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source> + <translation>SQLiteDatabase : échec de préparation de l’instruction pour récupérer l’ID de l’application : %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source> + <translation>SQLiteDatabase : la version %d du schéma de porte-monnaie sqlite est inconnue. Seule la version %d est prise en charge</translation> </message> <message> <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> - <translation>La base de données de blocs contient un bloc qui semble provenir du futur. Cela pourrait être causé par la date et l’heure erronées de votre ordinateur. Ne reconstruisez la base de données de blocs que si vous êtes certain que la date et l’heure de votre ordinateur sont justes.</translation> + <translation>La base de données de blocs comprend un bloc qui semble provenir du futur. Cela pourrait être causé par la date et l’heure erronées de votre ordinateur. Ne reconstruisez la base de données de blocs que si vous êtes certain que la date et l’heure de votre ordinateur sont justes.</translation> </message> <message> <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source> @@ -3684,6 +3700,10 @@ Accédez à Fichier > Ouvrir un porte-monnaie pour en charger un. <translation>Échec de réanalyse du porte-monnaie lors de l’initialisation</translation> </message> <message> + <source>Failed to verify database</source> + <translation>Échec de vérification de la base de données</translation> + </message> + <message> <source>Importing...</source> <translation>Importation…</translation> </message> @@ -3712,6 +3732,30 @@ Accédez à Fichier > Ouvrir un porte-monnaie pour en charger un. <translation>Le montant est invalide pour -fallbackfee=<amount> : « %s »</translation> </message> <message> + <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source> + <translation>SQLiteDatabase : échec d’exécution de l’instruction pour vérifier la base de données : %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase : échec de récupération de la version du schéma de porte-monnaie sqlite : %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch the application id: %s</source> + <translation>SQLiteDatabase : échec de récupération de l’ID de l’application : %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source> + <translation>SQLiteDatabase : échec de préparation de l’instruction pour vérifier la base de données : %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>SQLiteDatabase : échec de lecture de l’erreur de vérification de la base de données : %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>SQLiteDatabase : l’ID de l’application est inattendu. %u était attendu, %u été retourné</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation>Le répertoire des blocs indiqué « %s » n’existe pas.</translation> </message> @@ -3781,7 +3825,7 @@ Accédez à Fichier > Ouvrir un porte-monnaie pour en charger un. </message> <message> <source>User Agent comment (%s) contains unsafe characters.</source> - <translation>Le commentaire d’agent utilisateur (%s) contient des caractères dangereux.</translation> + <translation>Le commentaire de l’agent utilisateur (%s) comporte des caractères dangereux.</translation> </message> <message> <source>Verifying blocks...</source> @@ -3853,7 +3897,7 @@ Accédez à Fichier > Ouvrir un porte-monnaie pour en charger un. </message> <message> <source>Error: Keypool ran out, please call keypoolrefill first</source> - <translation>Erreur : La réserve de clés est épuisée, veuillez d'abord appeler « keypoolrefill »</translation> + <translation>Erreur : La réserve de clés est épuisée, veuillez d’abord appeler « keypoolrefill »</translation> </message> <message> <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source> diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts index 813f444dde..bd64fdd179 100644 --- a/src/qt/locale/bitcoin_he.ts +++ b/src/qt/locale/bitcoin_he.ts @@ -15,7 +15,7 @@ </message> <message> <source>Copy the currently selected address to the system clipboard</source> - <translation>העתקת הכתובת המסומנת ללוח הגזירים של המערכת</translation> + <translation>העתקת את הכתובת המסומנת ללוח</translation> </message> <message> <source>&Copy</source> diff --git a/src/qt/locale/bitcoin_hi.ts b/src/qt/locale/bitcoin_hi.ts index 98a60098b5..086a106c3d 100644 --- a/src/qt/locale/bitcoin_hi.ts +++ b/src/qt/locale/bitcoin_hi.ts @@ -3,7 +3,7 @@ <name>AddressBookPage</name> <message> <source>Right-click to edit address or label</source> - <translation>एड्रेस या लेबल को बदलने के लिए राइट-क्लिक करें </translation> + <translation>पता व नामपत्र बदलने के लिए दायीं कुंजी दबाइए </translation> </message> <message> <source>Create a new address</source> @@ -319,6 +319,10 @@ <translation>तिजोरी</translation> </message> <message> + <source>Send coins to a Bitcoin address</source> + <translation>इस पते पर बिटकौइन भेजें</translation> + </message> + <message> <source>Change the passphrase used for wallet encryption</source> <translation>पहचान शब्द/अक्षर जो वॉलेट एनक्रिपशन के लिए इस्तेमाल किया है उसे बदलिए!</translation> </message> @@ -359,6 +363,22 @@ <translation>नवीनतम</translation> </message> <message> + <source>Open a wallet</source> + <translation>बटुआ खोलें</translation> + </message> + <message> + <source>Close Wallet...</source> + <translation>बटुआ बंद करें...</translation> + </message> + <message> + <source>Close wallet</source> + <translation>बटुआ बंद करें</translation> + </message> + <message> + <source>Close All Wallets...</source> + <translation>सारे बटुएँ बंद करें...</translation> + </message> + <message> <source>Sent transaction</source> <translation>भेजी ट्रांजक्शन</translation> </message> @@ -378,6 +398,10 @@ <context> <name>CoinControlDialog</name> <message> + <source>Quantity:</source> + <translation>मात्रा :</translation> + </message> + <message> <source>Amount:</source> <translation>राशि :</translation> </message> @@ -394,6 +418,14 @@ <translation>पक्का</translation> </message> <message> + <source>yes</source> + <translation>हाँ</translation> + </message> + <message> + <source>no</source> + <translation>नहीं</translation> + </message> + <message> <source>(no label)</source> <translation>(कोई परचा नहीं )</translation> </message> @@ -571,6 +603,10 @@ <translation>सिक्के भेजें|</translation> </message> <message> + <source>Quantity:</source> + <translation>मात्रा :</translation> + </message> + <message> <source>Amount:</source> <translation>राशि :</translation> </message> @@ -724,6 +760,10 @@ </context> <context> <name>WalletController</name> + <message> + <source>Close wallet</source> + <translation>बटुआ बंद करें</translation> + </message> </context> <context> <name>WalletFrame</name> diff --git a/src/qt/locale/bitcoin_id.ts b/src/qt/locale/bitcoin_id.ts index 1dcb97dee7..51aafc98b8 100644 --- a/src/qt/locale/bitcoin_id.ts +++ b/src/qt/locale/bitcoin_id.ts @@ -1776,6 +1776,14 @@ <translation>Block Yang Telah Sinkron</translation> </message> <message> + <source>The mapped Autonomous System used for diversifying peer selection.</source> + <translation>Sistem Otonom yang dipetakan digunakan untuk mendiversifikasi pilihan peer</translation> + </message> + <message> + <source>Mapped AS</source> + <translation>AS yang Dipetakan</translation> + </message> + <message> <source>User Agent</source> <translation>Agen Pengguna @@ -1985,6 +1993,10 @@ <translation>Label fakultatif untuk menghubungkan dengan alamat penerima baru (anda menggunakannya untuk mengindetifikasi faktur). Itu juga dilampirkan pada permintaan pembayaran.</translation> </message> <message> + <source>An optional message that is attached to the payment request and may be displayed to the sender.</source> + <translation>Pesan opsional yang dilampirkan di permintaan pembayaran dan dapat ditampilkan ke pengirim.</translation> + </message> + <message> <source>&Create new receiving address</source> <translation>&Create alamat penerima baru</translation> </message> diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts index 8a464ace5c..80131e5b42 100644 --- a/src/qt/locale/bitcoin_it.ts +++ b/src/qt/locale/bitcoin_it.ts @@ -3,7 +3,7 @@ <name>AddressBookPage</name> <message> <source>Right-click to edit address or label</source> - <translation>Fai clic con il tasto destro del mouse per modificare l'indirizzo o l'etichetta</translation> + <translation>Fai clic con il tasto destro del mouse per modificare l'indirizzo oppure l'etichetta</translation> </message> <message> <source>Create a new address</source> @@ -15,7 +15,7 @@ </message> <message> <source>Copy the currently selected address to the system clipboard</source> - <translation>Copia negli appunti l'indirizzo attualmente selezionato</translation> + <translation>Copia negli appunti del sistema l'indirizzo attualmente selezionato</translation> </message> <message> <source>&Copy</source> @@ -89,11 +89,11 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation> </message> <message> <source>Export Address List</source> - <translation>Esporta elenco indirizzi</translation> + <translation>Esporta elenco degli indirizzi</translation> </message> <message> <source>Comma separated file (*.csv)</source> - <translation>Testo CSV (*.csv)</translation> + <translation>File diviso da virgole (*.csv)</translation> </message> <message> <source>Exporting Failed</source> @@ -171,7 +171,7 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation> </message> <message> <source>Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>!</source> - <translation>Attenzione: Se si cifra il portamonete e si perde la passphrase <b>TUTTI I PROPRI BITCOIN ANDRANNO PERSI</b>!</translation> + <translation>Attenzione: Se si cifra il portafoglio e si perde la passphrase <b>TUTTI I PROPRI BITCOIN ANDRANNO PERSI</b>!</translation> </message> <message> <source>Are you sure you wish to encrypt your wallet?</source> @@ -548,6 +548,14 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation> <translation>Mostra il messaggio di aiuto di %1 per ottenere una lista di opzioni di comando per Bitcoin</translation> </message> <message> + <source>&Mask values</source> + <translation>&Valori della maschera</translation> + </message> + <message> + <source>Mask the values in the Overview tab</source> + <translation>Maschera i valori nella sezione "Panoramica"</translation> + </message> + <message> <source>default wallet</source> <translation>Portafoglio predefinito:</translation> </message> @@ -869,6 +877,10 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation> <translation>Usa descriptors per gestione scriptPubKey</translation> </message> <message> + <source>Descriptor Wallet</source> + <translation>Descrizione del Portafoglio</translation> + </message> + <message> <source>Create</source> <translation>Crea</translation> </message> @@ -1488,7 +1500,11 @@ Per specificare più URL separarli con una barra verticale "|".</translation> <source>Current total balance in watch-only addresses</source> <translation>Saldo corrente totale negli indirizzi di sola lettura</translation> </message> - </context> + <message> + <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</source> + <translation>Modalità privacy attivata per la scheda "Panoramica". Per smascherare i valori, deseleziona Impostazioni-> Valori maschera.</translation> + </message> +</context> <context> <name>PSBTOperationsDialog</name> <message> @@ -3557,6 +3573,10 @@ Vai su File > Apri Portafoglio per caricare un portafoglio. <translation>Errore lettura %s! Tutte le chiavi sono state lette correttamente, ma i dati delle transazioni o della rubrica potrebbero essere mancanti o non corretti.</translation> </message> <message> + <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source> + <translation>Viene fornito più di un indirizzo di associazione onion. L'utilizzo di %s per il servizio Tor onion viene creato automaticamente.</translation> + </message> + <message> <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> <translation>Per favore controllate che la data del computer e l'ora siano corrette! Se il vostro orologio è sbagliato %s non funzionerà correttamente.</translation> </message> @@ -3669,6 +3689,10 @@ Vai su File > Apri Portafoglio per caricare un portafoglio. <translation>Impossibile ripetere la scansione del portafoglio durante l'inizializzazione</translation> </message> <message> + <source>Failed to verify database</source> + <translation>Errore nella verifica del database</translation> + </message> + <message> <source>Importing...</source> <translation>Importazione...</translation> </message> @@ -3697,6 +3721,22 @@ Vai su File > Apri Portafoglio per caricare un portafoglio. <translation>Importo non valido per -fallbackfee=<amount>: '%s'</translation> </message> <message> + <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source> + <translation>SQLiteDatabase: Errore nell'eseguire l'operazione di verifica del database: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source> + <translation>SQLiteDatabase: Errore nel verificare il database: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>SQLiteDatabase: Errore nella lettura della verifica del database: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>SQLiteDatabase: Application id non riconosciuto. Mi aspetto un %u, arriva un %u</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation>La cartella specificata "%s" non esiste.</translation> </message> @@ -3781,6 +3821,14 @@ Vai su File > Apri Portafoglio per caricare un portafoglio. <translation>Errore: attesa per connessioni in arrivo fallita (errore riportato %s)</translation> </message> <message> + <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source> + <translation>%s corrotto. Prova a usare la funzione del portafoglio bitcoin-wallet per salvare o recuperare il backup</translation> + </message> + <message> + <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source> + <translation>Impossibile aggiornare un portafoglio diviso non HD senza aggiornamento per supportare il keypool pre-split. Si prega di utilizzare -upgradewallet = 169900 o -upgradewallet senza specificare la versione.</translation> + </message> + <message> <source>Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source> <translation>Importo non valido per -maxtxfee=<amount>: '%s' (deve essere almeno pari alla commissione 'minrelay fee' di %s per prevenire transazioni bloccate)</translation> </message> diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts index 5590483f24..ccbc135c16 100644 --- a/src/qt/locale/bitcoin_ja.ts +++ b/src/qt/locale/bitcoin_ja.ts @@ -479,6 +479,14 @@ <translation>ブロックは最新</translation> </message> <message> + <source>Load PSBT from clipboard...</source> + <translation>PSBTをクリップボードから読み込み</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction from clipboard</source> + <translation>部分的に署名されたビットコインのトランザクションをクリップボードから読み込み</translation> + </message> + <message> <source>Node window</source> <translation>ノードウィンドウ</translation> </message> @@ -515,6 +523,14 @@ <translation>ウォレットを閉じる</translation> </message> <message> + <source>Close All Wallets...</source> + <translation>全てのウォレットを閉じる</translation> + </message> + <message> + <source>Close all wallets</source> + <translation>全てのウォレットを閉じる</translation> + </message> + <message> <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source> <translation>%1 のヘルプ メッセージを表示し、使用可能な Bitcoin のコマンドラインオプション一覧を見る。</translation> </message> @@ -626,6 +642,10 @@ <source>Wallet is <b>encrypted</b> and currently <b>locked</b></source> <translation>ウォレットは<b>暗号化済み</b>・<b>ロック状態</b></translation> </message> + <message> + <source>Original message:</source> + <translation>オリジナルメッセージ:</translation> + </message> </context> <context> <name>CoinControlDialog</name> @@ -1442,6 +1462,34 @@ <context> <name>PSBTOperationsDialog</name> <message> + <source>Dialog</source> + <translation>ダイアログ</translation> + </message> + <message> + <source>Copy to Clipboard</source> + <translation>クリップボードにコピー</translation> + </message> + <message> + <source>Save...</source> + <translation>保存</translation> + </message> + <message> + <source>Close</source> + <translation>閉じる</translation> + </message> + <message> + <source>Signed transaction successfully. Transaction is ready to broadcast.</source> + <translation>トランザクションへの署名が成功しました。トランザクションのブロードキャストの準備ができています。</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>トランザクションデータの保存</translation> + </message> + <message> + <source>PSBT saved to disk.</source> + <translation>PSBTはディスクに保存されました。</translation> + </message> + <message> <source>Total Amount</source> <translation>合計</translation> </message> @@ -2063,6 +2111,10 @@ <context> <name>ReceiveRequestDialog</name> <message> + <source>Address:</source> + <translation>アドレス:</translation> + </message> + <message> <source>Amount:</source> <translation>金額:</translation> </message> @@ -2345,6 +2397,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>送金してもよろしいですか?</translation> </message> <message> + <source>Save Transaction Data</source> + <translation>トランザクションデータの保存</translation> + </message> + <message> <source>or</source> <translation>または</translation> </message> @@ -3166,7 +3222,15 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source> <translation>ブロックファイル剪定が有効の場合、長期間ウォレットを起動しないと全チェーンを再度同期させる必要があるかもしれません。</translation> </message> - </context> + <message> + <source>Close all wallets</source> + <translation>全てのウォレットを閉じる</translation> + </message> + <message> + <source>Are you sure you wish to close all wallets?</source> + <translation>本当に全てのウォレットを閉じますか。</translation> + </message> +</context> <context> <name>WalletFrame</name> <message> @@ -3551,6 +3615,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>非剪定モードに戻るためには -reindex オプションを指定してデータベースを再構築する必要があります。 ブロックチェーン全体の再ダウンロードが必要となります。</translation> </message> <message> + <source>Disk space is too low!</source> + <translation>ディスク容量不足!</translation> + </message> + <message> <source>Error reading from database, shutting down.</source> <translation>データベースの読み込みエラー。シャットダウンします。</translation> </message> diff --git a/src/qt/locale/bitcoin_ms.ts b/src/qt/locale/bitcoin_ms.ts index ee729a3f9e..4d51ebba02 100644 --- a/src/qt/locale/bitcoin_ms.ts +++ b/src/qt/locale/bitcoin_ms.ts @@ -134,6 +134,10 @@ Alihkan fail data ke dalam tab semasa</translation> <translation>Ulangi frasa laluan baru</translation> </message> <message> + <source>Show passphrase</source> + <translation>Show passphrase</translation> + </message> + <message> <source>Encrypt wallet</source> <translation>Dompet encrypt</translation> </message> @@ -174,6 +178,30 @@ Alihkan fail data ke dalam tab semasa</translation> <translation>Dompet dienkripsi</translation> </message> <message> + <source>Enter the new passphrase for the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>.</source> + <translation>Enter the new passphrase for the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>.</translation> + </message> + <message> + <source>Enter the old passphrase and new passphrase for the wallet.</source> + <translation>Enter the old passphrase and new passphrase for the wallet.</translation> + </message> + <message> + <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source> + <translation>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</translation> + </message> + <message> + <source>Wallet to be encrypted</source> + <translation>Wallet to be encrypted</translation> + </message> + <message> + <source>Your wallet is about to be encrypted. </source> + <translation>Your wallet is about to be encrypted. </translation> + </message> + <message> + <source>Your wallet is now encrypted. </source> + <translation>Your wallet is now encrypted. </translation> + </message> + <message> <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source> <translation>PENTING: Apa-apa sandaran yang anda buat sebelum ini untuk fail dompet anda hendaklah digantikan dengan fail dompet enkripsi yang dijana baru. Untuk sebab-sebab keselamatan , sandaran fail dompet yang belum dibuat enkripsi sebelum ini akan menjadi tidak berguna secepat anda mula guna dompet enkripsi baru.</translation> </message> @@ -296,6 +324,14 @@ Alihkan fail data ke dalam tab semasa</translation> <translation>Buka &URI...</translation> </message> <message> + <source>Create Wallet...</source> + <translation>Create Wallet...</translation> + </message> + <message> + <source>Create a new wallet</source> + <translation>Create a new wallet</translation> + </message> + <message> <source>Wallet:</source> <translation>dompet</translation> </message> @@ -320,6 +356,10 @@ Alihkan fail data ke dalam tab semasa</translation> <translation>Reindexi blok pada cakera...</translation> </message> <message> + <source>Proxy is <b>enabled</b>: %1</source> + <translation>Proxy is <b>enabled</b>: %1</translation> + </message> + <message> <source>Send coins to a Bitcoin address</source> <translation>Menghantar koin kepada alamat Bitcoin</translation> </message> @@ -391,6 +431,34 @@ Alihkan fail data ke dalam tab semasa</translation> </translation> </message> <message> + <source>Show the list of used receiving addresses and labels</source> + <translation>Show the list of used receiving addresses and labels</translation> + </message> + <message> + <source>&Command-line options</source> + <translation>&Command-line options</translation> + </message> + <message> + <source>Indexing blocks on disk...</source> + <translation>Indexing blocks on disk...</translation> + </message> + <message> + <source>Processing blocks on disk...</source> + <translation>Processing blocks on disk...</translation> + </message> + <message> + <source>%1 behind</source> + <translation>%1 behind</translation> + </message> + <message> + <source>Last received block was generated %1 ago.</source> + <translation>Last received block was generated %1 ago.</translation> + </message> + <message> + <source>Transactions after this will not yet be visible.</source> + <translation>Transactions after this will not yet be visible.</translation> + </message> + <message> <source>Error</source> <translation>Ralat</translation> </message> @@ -407,10 +475,34 @@ Alihkan fail data ke dalam tab semasa</translation> <translation>Terkini</translation> </message> <message> + <source>Node window</source> + <translation>Node window</translation> + </message> + <message> + <source>Open node debugging and diagnostic console</source> + <translation>Open node debugging and diagnostic console</translation> + </message> + <message> + <source>&Sending addresses</source> + <translation>&Sending addresses</translation> + </message> + <message> + <source>&Receiving addresses</source> + <translation>&Receiving addresses</translation> + </message> + <message> + <source>Open a bitcoin: URI</source> + <translation>Open a bitcoin: URI</translation> + </message> + <message> <source>Open Wallet</source> <translation>Buka Wallet</translation> </message> <message> + <source>Open a wallet</source> + <translation>Open a wallet</translation> + </message> + <message> <source>Close Wallet...</source> <translation>Tutup Wallet...</translation> </message> @@ -419,28 +511,324 @@ Alihkan fail data ke dalam tab semasa</translation> <translation>Tutup Wallet</translation> </message> <message> + <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source> + <translation>Show the %1 help message to get a list with possible Bitcoin command-line options</translation> + </message> + <message> <source>default wallet</source> <translation>dompet lalai </translation> </message> + <message> + <source>No wallets available</source> + <translation>No wallets available</translation> + </message> + <message> + <source>&Window</source> + <translation>&Window</translation> + </message> + <message> + <source>Minimize</source> + <translation>Minimize</translation> + </message> + <message> + <source>Zoom</source> + <translation>Zoom</translation> + </message> + <message> + <source>Main Window</source> + <translation>Main Window</translation> + </message> + <message> + <source>%1 client</source> + <translation>%1 client</translation> + </message> + <message> + <source>Connecting to peers...</source> + <translation>Connecting to peers...</translation> + </message> + <message> + <source>Catching up...</source> + <translation>Catching up...</translation> + </message> + <message> + <source>Error: %1</source> + <translation>Error: %1</translation> + </message> + <message> + <source>Warning: %1</source> + <translation>Warning: %1</translation> + </message> + <message> + <source>Date: %1 +</source> + <translation>Date: %1 +</translation> + </message> + <message> + <source>Amount: %1 +</source> + <translation>Amount: %1 +</translation> + </message> + <message> + <source>Wallet: %1 +</source> + <translation>Wallet: %1 +</translation> + </message> + <message> + <source>Type: %1 +</source> + <translation>Type: %1 +</translation> + </message> + <message> + <source>Label: %1 +</source> + <translation>Label: %1 +</translation> + </message> + <message> + <source>Address: %1 +</source> + <translation>Address: %1 +</translation> + </message> + <message> + <source>Sent transaction</source> + <translation>Sent transaction</translation> + </message> + <message> + <source>Incoming transaction</source> + <translation>Incoming transaction</translation> + </message> + <message> + <source>HD key generation is <b>enabled</b></source> + <translation>HD key generation is <b>enabled</b></translation> + </message> + <message> + <source>HD key generation is <b>disabled</b></source> + <translation>HD key generation is <b>disabled</b></translation> + </message> + <message> + <source>Private key <b>disabled</b></source> + <translation>Private key <b>disabled</b></translation> + </message> + <message> + <source>Wallet is <b>encrypted</b> and currently <b>unlocked</b></source> + <translation>Wallet is <b>encrypted</b> and currently <b>unlocked</b></translation> + </message> + <message> + <source>Wallet is <b>encrypted</b> and currently <b>locked</b></source> + <translation>Wallet is <b>encrypted</b> and currently <b>locked</b></translation> + </message> </context> <context> <name>CoinControlDialog</name> <message> + <source>Coin Selection</source> + <translation>Coin Selection</translation> + </message> + <message> + <source>Quantity:</source> + <translation>Quantity:</translation> + </message> + <message> + <source>Bytes:</source> + <translation>Bytes:</translation> + </message> + <message> + <source>Amount:</source> + <translation>Amount:</translation> + </message> + <message> + <source>Fee:</source> + <translation>Fee:</translation> + </message> + <message> + <source>Dust:</source> + <translation>Dust:</translation> + </message> + <message> + <source>After Fee:</source> + <translation>After Fee:</translation> + </message> + <message> + <source>Change:</source> + <translation>Change:</translation> + </message> + <message> + <source>(un)select all</source> + <translation>(un)select all</translation> + </message> + <message> + <source>Tree mode</source> + <translation>Tree mode</translation> + </message> + <message> + <source>List mode</source> + <translation>List mode</translation> + </message> + <message> <source>Amount</source> <translation>Amount</translation> </message> <message> + <source>Received with label</source> + <translation>Received with label</translation> + </message> + <message> + <source>Received with address</source> + <translation>Received with address</translation> + </message> + <message> + <source>Date</source> + <translation>Date</translation> + </message> + <message> + <source>Confirmations</source> + <translation>Confirmations</translation> + </message> + <message> + <source>Confirmed</source> + <translation>Confirmed</translation> + </message> + <message> + <source>Copy address</source> + <translation>Copy address</translation> + </message> + <message> + <source>Copy label</source> + <translation>Copy label</translation> + </message> + <message> + <source>Copy amount</source> + <translation>Copy amount</translation> + </message> + <message> + <source>Copy transaction ID</source> + <translation>Copy transaction ID</translation> + </message> + <message> + <source>Lock unspent</source> + <translation>Lock unspent</translation> + </message> + <message> + <source>Unlock unspent</source> + <translation>Unlock unspent</translation> + </message> + <message> + <source>Copy quantity</source> + <translation>Copy quantity</translation> + </message> + <message> + <source>Copy fee</source> + <translation>Copy fee</translation> + </message> + <message> + <source>Copy after fee</source> + <translation>Copy after fee</translation> + </message> + <message> + <source>Copy bytes</source> + <translation>Copy bytes</translation> + </message> + <message> + <source>Copy dust</source> + <translation>Copy dust</translation> + </message> + <message> + <source>Copy change</source> + <translation>Copy change</translation> + </message> + <message> + <source>(%1 locked)</source> + <translation>(%1 locked)</translation> + </message> + <message> + <source>yes</source> + <translation>yes</translation> + </message> + <message> + <source>no</source> + <translation>no</translation> + </message> + <message> + <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source> + <translation>This label turns red if any recipient receives an amount smaller than the current dust threshold.</translation> + </message> + <message> + <source>Can vary +/- %1 satoshi(s) per input.</source> + <translation>Can vary +/- %1 satoshi(s) per input.</translation> + </message> + <message> <source>(no label)</source> <translation>(tiada label)</translation> </message> - </context> + <message> + <source>change from %1 (%2)</source> + <translation>change from %1 (%2)</translation> + </message> + <message> + <source>(change)</source> + <translation>(change)</translation> + </message> +</context> <context> <name>CreateWalletActivity</name> - </context> + <message> + <source>Creating Wallet <b>%1</b>...</source> + <translation>Creating Wallet <b>%1</b>...</translation> + </message> + <message> + <source>Create wallet failed</source> + <translation>Create wallet failed</translation> + </message> + <message> + <source>Create wallet warning</source> + <translation>Create wallet warning</translation> + </message> +</context> <context> <name>CreateWalletDialog</name> - </context> + <message> + <source>Create Wallet</source> + <translation>Create Wallet</translation> + </message> + <message> + <source>Wallet Name</source> + <translation>Wallet Name</translation> + </message> + <message> + <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source> + <translation>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</translation> + </message> + <message> + <source>Encrypt Wallet</source> + <translation>Encrypt Wallet</translation> + </message> + <message> + <source>Disable private keys for this wallet. Wallets with private keys disabled will have no private keys and cannot have an HD seed or imported private keys. This is ideal for watch-only wallets.</source> + <translation>Disable private keys for this wallet. Wallets with private keys disabled will have no private keys and cannot have an HD seed or imported private keys. This is ideal for watch-only wallets.</translation> + </message> + <message> + <source>Disable Private Keys</source> + <translation>Disable Private Keys</translation> + </message> + <message> + <source>Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time.</source> + <translation>Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time.</translation> + </message> + <message> + <source>Make Blank Wallet</source> + <translation>Make Blank Wallet</translation> + </message> + <message> + <source>Create</source> + <translation>Create</translation> + </message> +</context> <context> <name>EditAddressDialog</name> <message> @@ -448,36 +836,244 @@ Alihkan fail data ke dalam tab semasa</translation> <translation>Alamat</translation> </message> <message> + <source>&Label</source> + <translation>&Label</translation> + </message> + <message> + <source>The label associated with this address list entry</source> + <translation>The label associated with this address list entry</translation> + </message> + <message> + <source>The address associated with this address list entry. This can only be modified for sending addresses.</source> + <translation>The address associated with this address list entry. This can only be modified for sending addresses.</translation> + </message> + <message> <source>&Address</source> <translation>Alamat</translation> </message> - </context> + <message> + <source>New sending address</source> + <translation>New sending address</translation> + </message> + <message> + <source>Edit receiving address</source> + <translation>Edit receiving address</translation> + </message> + <message> + <source>Edit sending address</source> + <translation>Edit sending address</translation> + </message> + <message> + <source>The entered address "%1" is not a valid Bitcoin address.</source> + <translation>The entered address "%1" is not a valid Bitcoin address.</translation> + </message> + <message> + <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source> + <translation>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</translation> + </message> + <message> + <source>The entered address "%1" is already in the address book with label "%2".</source> + <translation>The entered address "%1" is already in the address book with label "%2".</translation> + </message> + <message> + <source>Could not unlock wallet.</source> + <translation>Could not unlock wallet.</translation> + </message> + <message> + <source>New key generation failed.</source> + <translation>New key generation failed.</translation> + </message> +</context> <context> <name>FreespaceChecker</name> - </context> + <message> + <source>A new data directory will be created.</source> + <translation>A new data directory will be created.</translation> + </message> + <message> + <source>name</source> + <translation>name</translation> + </message> + <message> + <source>Directory already exists. Add %1 if you intend to create a new directory here.</source> + <translation>Directory already exists. Add %1 if you intend to create a new directory here.</translation> + </message> + <message> + <source>Path already exists, and is not a directory.</source> + <translation>Path already exists, and is not a directory.</translation> + </message> + <message> + <source>Cannot create data directory here.</source> + <translation>Cannot create data directory here.</translation> + </message> +</context> <context> <name>HelpMessageDialog</name> - </context> + <message> + <source>version</source> + <translation>version</translation> + </message> + <message> + <source>About %1</source> + <translation>About %1</translation> + </message> + <message> + <source>Command-line options</source> + <translation>Command-line options</translation> + </message> +</context> <context> <name>Intro</name> <message> + <source>Welcome</source> + <translation>Welcome</translation> + </message> + <message> + <source>Welcome to %1.</source> + <translation>Welcome to %1.</translation> + </message> + <message> + <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source> + <translation>As this is the first time the program is launched, you can choose where %1 will store its data.</translation> + </message> + <message> + <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source> + <translation>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</translation> + </message> + <message> + <source>Reverting this setting requires re-downloading the entire blockchain. It is faster to download the full chain first and prune it later. Disables some advanced features.</source> + <translation>Reverting this setting requires re-downloading the entire blockchain. It is faster to download the full chain first and prune it later. Disables some advanced features.</translation> + </message> + <message> + <source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source> + <translation>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</translation> + </message> + <message> + <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source> + <translation>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</translation> + </message> + <message> + <source>Use the default data directory</source> + <translation>Use the default data directory</translation> + </message> + <message> + <source>Use a custom data directory:</source> + <translation>Use a custom data directory:</translation> + </message> + <message> <source>Bitcoin</source> <translation>Bitcoin</translation> </message> <message> + <source>Discard blocks after verification, except most recent %1 GB (prune)</source> + <translation>Discard blocks after verification, except most recent %1 GB (prune)</translation> + </message> + <message> + <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source> + <translation>At least %1 GB of data will be stored in this directory, and it will grow over time.</translation> + </message> + <message> + <source>Approximately %1 GB of data will be stored in this directory.</source> + <translation>Approximately %1 GB of data will be stored in this directory.</translation> + </message> + <message> + <source>%1 will download and store a copy of the Bitcoin block chain.</source> + <translation>%1 will download and store a copy of the Bitcoin block chain.</translation> + </message> + <message> + <source>The wallet will also be stored in this directory.</source> + <translation>The wallet will also be stored in this directory.</translation> + </message> + <message> + <source>Error: Specified data directory "%1" cannot be created.</source> + <translation>Error: Specified data directory "%1" cannot be created.</translation> + </message> + <message> <source>Error</source> <translation>Ralat</translation> </message> </context> <context> <name>ModalOverlay</name> - </context> + <message> + <source>Form</source> + <translation>Form</translation> + </message> + <message> + <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source> + <translation>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</translation> + </message> + <message> + <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source> + <translation>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</translation> + </message> + <message> + <source>Number of blocks left</source> + <translation>Number of blocks left</translation> + </message> + <message> + <source>Unknown...</source> + <translation>Unknown...</translation> + </message> + <message> + <source>Last block time</source> + <translation>Last block time</translation> + </message> + <message> + <source>Progress</source> + <translation>Progress</translation> + </message> + <message> + <source>Progress increase per hour</source> + <translation>Progress increase per hour</translation> + </message> + <message> + <source>calculating...</source> + <translation>calculating...</translation> + </message> + <message> + <source>Estimated time left until synced</source> + <translation>Estimated time left until synced</translation> + </message> + <message> + <source>Hide</source> + <translation>Hide</translation> + </message> + <message> + <source>Esc</source> + <translation>Esc</translation> + </message> + <message> + <source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source> + <translation>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</translation> + </message> + <message> + <source>Unknown. Syncing Headers (%1, %2%)...</source> + <translation>Unknown. Syncing Headers (%1, %2%)...</translation> + </message> +</context> <context> <name>OpenURIDialog</name> - </context> + <message> + <source>Open bitcoin URI</source> + <translation>Open bitcoin URI</translation> + </message> + <message> + <source>URI:</source> + <translation>URI:</translation> + </message> +</context> <context> <name>OpenWalletActivity</name> <message> + <source>Open wallet failed</source> + <translation>Open wallet failed</translation> + </message> + <message> + <source>Open wallet warning</source> + <translation>Open wallet warning</translation> + </message> + <message> <source>default wallet</source> <translation>dompet lalai </translation> @@ -490,111 +1086,1971 @@ Alihkan fail data ke dalam tab semasa</translation> <context> <name>OptionsDialog</name> <message> + <source>Options</source> + <translation>Options</translation> + </message> + <message> + <source>&Main</source> + <translation>&Main</translation> + </message> + <message> + <source>Automatically start %1 after logging in to the system.</source> + <translation>Automatically start %1 after logging in to the system.</translation> + </message> + <message> + <source>&Start %1 on system login</source> + <translation>&Start %1 on system login</translation> + </message> + <message> + <source>Size of &database cache</source> + <translation>Size of &database cache</translation> + </message> + <message> + <source>Number of script &verification threads</source> + <translation>Number of script &verification threads</translation> + </message> + <message> + <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> + <translation>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</translation> + </message> + <message> + <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source> + <translation>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</translation> + </message> + <message> + <source>Hide the icon from the system tray.</source> + <translation>Hide the icon from the system tray.</translation> + </message> + <message> + <source>&Hide tray icon</source> + <translation>&Hide tray icon</translation> + </message> + <message> + <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source> + <translation>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</translation> + </message> + <message> + <source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source> + <translation>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</translation> + </message> + <message> + <source>Open the %1 configuration file from the working directory.</source> + <translation>Open the %1 configuration file from the working directory.</translation> + </message> + <message> + <source>Open Configuration File</source> + <translation>Open Configuration File</translation> + </message> + <message> + <source>Reset all client options to default.</source> + <translation>Reset all client options to default.</translation> + </message> + <message> + <source>&Reset Options</source> + <translation>&Reset Options</translation> + </message> + <message> + <source>&Network</source> + <translation>&Network</translation> + </message> + <message> + <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source> + <translation>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</translation> + </message> + <message> + <source>Prune &block storage to</source> + <translation>Prune &block storage to</translation> + </message> + <message> + <source>GB</source> + <translation>GB</translation> + </message> + <message> + <source>Reverting this setting requires re-downloading the entire blockchain.</source> + <translation>Reverting this setting requires re-downloading the entire blockchain.</translation> + </message> + <message> + <source>MiB</source> + <translation>MiB</translation> + </message> + <message> + <source>(0 = auto, <0 = leave that many cores free)</source> + <translation>(0 = auto, <0 = leave that many cores free)</translation> + </message> + <message> + <source>W&allet</source> + <translation>W&allet</translation> + </message> + <message> + <source>Expert</source> + <translation>Expert</translation> + </message> + <message> + <source>Enable coin &control features</source> + <translation>Enable coin &control features</translation> + </message> + <message> + <source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source> + <translation>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</translation> + </message> + <message> + <source>&Spend unconfirmed change</source> + <translation>&Spend unconfirmed change</translation> + </message> + <message> + <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source> + <translation>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</translation> + </message> + <message> + <source>Map port using &UPnP</source> + <translation>Map port using &UPnP</translation> + </message> + <message> + <source>Accept connections from outside.</source> + <translation>Accept connections from outside.</translation> + </message> + <message> + <source>Allow incomin&g connections</source> + <translation>Allow incomin&g connections</translation> + </message> + <message> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation>Connect to the Bitcoin network through a SOCKS5 proxy.</translation> + </message> + <message> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation>&Connect through SOCKS5 proxy (default proxy):</translation> + </message> + <message> + <source>Proxy &IP:</source> + <translation>Proxy &IP:</translation> + </message> + <message> + <source>&Port:</source> + <translation>&Port:</translation> + </message> + <message> + <source>Port of the proxy (e.g. 9050)</source> + <translation>Port of the proxy (e.g. 9050)</translation> + </message> + <message> + <source>Used for reaching peers via:</source> + <translation>Used for reaching peers via:</translation> + </message> + <message> + <source>IPv4</source> + <translation>IPv4</translation> + </message> + <message> + <source>IPv6</source> + <translation>IPv6</translation> + </message> + <message> + <source>Tor</source> + <translation>Tor</translation> + </message> + <message> + <source>&Window</source> + <translation>&Window</translation> + </message> + <message> + <source>Show only a tray icon after minimizing the window.</source> + <translation>Show only a tray icon after minimizing the window.</translation> + </message> + <message> + <source>&Minimize to the tray instead of the taskbar</source> + <translation>&Minimize to the tray instead of the taskbar</translation> + </message> + <message> + <source>M&inimize on close</source> + <translation>M&inimize on close</translation> + </message> + <message> + <source>&Display</source> + <translation>&Display</translation> + </message> + <message> + <source>User Interface &language:</source> + <translation>User Interface &language:</translation> + </message> + <message> + <source>The user interface language can be set here. This setting will take effect after restarting %1.</source> + <translation>The user interface language can be set here. This setting will take effect after restarting %1.</translation> + </message> + <message> + <source>&Unit to show amounts in:</source> + <translation>&Unit to show amounts in:</translation> + </message> + <message> + <source>Choose the default subdivision unit to show in the interface and when sending coins.</source> + <translation>Choose the default subdivision unit to show in the interface and when sending coins.</translation> + </message> + <message> + <source>Whether to show coin control features or not.</source> + <translation>Whether to show coin control features or not.</translation> + </message> + <message> + <source>&Third party transaction URLs</source> + <translation>&Third party transaction URLs</translation> + </message> + <message> + <source>Options set in this dialog are overridden by the command line or in the configuration file:</source> + <translation>Options set in this dialog are overridden by the command line or in the configuration file:</translation> + </message> + <message> + <source>&OK</source> + <translation>&OK</translation> + </message> + <message> + <source>&Cancel</source> + <translation>&Cancel</translation> + </message> + <message> + <source>default</source> + <translation>default</translation> + </message> + <message> + <source>none</source> + <translation>none</translation> + </message> + <message> + <source>Confirm options reset</source> + <translation>Confirm options reset</translation> + </message> + <message> + <source>Client restart required to activate changes.</source> + <translation>Client restart required to activate changes.</translation> + </message> + <message> + <source>Client will be shut down. Do you want to proceed?</source> + <translation>Client will be shut down. Do you want to proceed?</translation> + </message> + <message> + <source>Configuration options</source> + <translation>Configuration options</translation> + </message> + <message> + <source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source> + <translation>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</translation> + </message> + <message> <source>Error</source> <translation>Ralat</translation> </message> - </context> + <message> + <source>The configuration file could not be opened.</source> + <translation>The configuration file could not be opened.</translation> + </message> + <message> + <source>This change would require a client restart.</source> + <translation>This change would require a client restart.</translation> + </message> + <message> + <source>The supplied proxy address is invalid.</source> + <translation>The supplied proxy address is invalid.</translation> + </message> +</context> <context> <name>OverviewPage</name> + <message> + <source>Form</source> + <translation>Form</translation> + </message> + <message> + <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source> + <translation>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</translation> + </message> + <message> + <source>Watch-only:</source> + <translation>Watch-only:</translation> + </message> + <message> + <source>Available:</source> + <translation>Available:</translation> + </message> + <message> + <source>Your current spendable balance</source> + <translation>Your current spendable balance</translation> + </message> + <message> + <source>Pending:</source> + <translation>Pending:</translation> + </message> + <message> + <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source> + <translation>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</translation> + </message> + <message> + <source>Immature:</source> + <translation>Immature:</translation> + </message> + <message> + <source>Mined balance that has not yet matured</source> + <translation>Mined balance that has not yet matured</translation> + </message> + <message> + <source>Balances</source> + <translation>Balances</translation> + </message> + <message> + <source>Total:</source> + <translation>Total:</translation> + </message> + <message> + <source>Your current total balance</source> + <translation>Your current total balance</translation> + </message> + <message> + <source>Your current balance in watch-only addresses</source> + <translation>Your current balance in watch-only addresses</translation> + </message> + <message> + <source>Spendable:</source> + <translation>Spendable:</translation> + </message> + <message> + <source>Recent transactions</source> + <translation>Recent transactions</translation> + </message> + <message> + <source>Unconfirmed transactions to watch-only addresses</source> + <translation>Unconfirmed transactions to watch-only addresses</translation> + </message> + <message> + <source>Mined balance in watch-only addresses that has not yet matured</source> + <translation>Mined balance in watch-only addresses that has not yet matured</translation> + </message> + <message> + <source>Current total balance in watch-only addresses</source> + <translation>Current total balance in watch-only addresses</translation> + </message> </context> <context> <name>PSBTOperationsDialog</name> + <message> + <source>Total Amount</source> + <translation>Total Amount</translation> + </message> + <message> + <source>or</source> + <translation>or</translation> + </message> </context> <context> <name>PaymentServer</name> - </context> + <message> + <source>Payment request error</source> + <translation>Payment request error</translation> + </message> + <message> + <source>Cannot start bitcoin: click-to-pay handler</source> + <translation>Cannot start bitcoin: click-to-pay handler</translation> + </message> + <message> + <source>URI handling</source> + <translation>URI handling</translation> + </message> + <message> + <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source> + <translation>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</translation> + </message> + <message> + <source>Cannot process payment request because BIP70 is not supported.</source> + <translation>Cannot process payment request because BIP70 is not supported.</translation> + </message> + <message> + <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source> + <translation>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</translation> + </message> + <message> + <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source> + <translation>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</translation> + </message> + <message> + <source>Invalid payment address %1</source> + <translation>Invalid payment address %1</translation> + </message> + <message> + <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source> + <translation>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation> + </message> + <message> + <source>Payment request file handling</source> + <translation>Payment request file handling</translation> + </message> +</context> <context> <name>PeerTableModel</name> - </context> + <message> + <source>User Agent</source> + <translation>User Agent</translation> + </message> + <message> + <source>Node/Service</source> + <translation>Node/Service</translation> + </message> + <message> + <source>NodeId</source> + <translation>NodeId</translation> + </message> + <message> + <source>Ping</source> + <translation>Ping</translation> + </message> + <message> + <source>Sent</source> + <translation>Sent</translation> + </message> + <message> + <source>Received</source> + <translation>Received</translation> + </message> +</context> <context> <name>QObject</name> <message> <source>Amount</source> <translation>Amount</translation> </message> - </context> + <message> + <source>Enter a Bitcoin address (e.g. %1)</source> + <translation>Enter a Bitcoin address (e.g. %1)</translation> + </message> + <message> + <source>%1 d</source> + <translation>%1 d</translation> + </message> + <message> + <source>%1 h</source> + <translation>%1 h</translation> + </message> + <message> + <source>%1 m</source> + <translation>%1 m</translation> + </message> + <message> + <source>%1 s</source> + <translation>%1 s</translation> + </message> + <message> + <source>None</source> + <translation>None</translation> + </message> + <message> + <source>N/A</source> + <translation>N/A</translation> + </message> + <message> + <source>%1 ms</source> + <translation>%1 ms</translation> + </message> + <message> + <source>%1 and %2</source> + <translation>%1 and %2</translation> + </message> + <message> + <source>%1 B</source> + <translation>%1 B</translation> + </message> + <message> + <source>%1 KB</source> + <translation>%1 KB</translation> + </message> + <message> + <source>%1 MB</source> + <translation>%1 MB</translation> + </message> + <message> + <source>%1 GB</source> + <translation>%1 GB</translation> + </message> + <message> + <source>Error: Specified data directory "%1" does not exist.</source> + <translation>Error: Specified data directory "%1" does not exist.</translation> + </message> + <message> + <source>Error: Cannot parse configuration file: %1.</source> + <translation>Error: Cannot parse configuration file: %1.</translation> + </message> + <message> + <source>Error: %1</source> + <translation>Error: %1</translation> + </message> + <message> + <source>%1 didn't yet exit safely...</source> + <translation>%1 didn't yet exit safely...</translation> + </message> + <message> + <source>unknown</source> + <translation>unknown</translation> + </message> +</context> <context> <name>QRImageWidget</name> - </context> + <message> + <source>&Save Image...</source> + <translation>&Save Image...</translation> + </message> + <message> + <source>&Copy Image</source> + <translation>&Copy Image</translation> + </message> + <message> + <source>Resulting URI too long, try to reduce the text for label / message.</source> + <translation>Resulting URI too long, try to reduce the text for label / message.</translation> + </message> + <message> + <source>Error encoding URI into QR Code.</source> + <translation>Error encoding URI into QR Code.</translation> + </message> + <message> + <source>QR code support not available.</source> + <translation>QR code support not available.</translation> + </message> + <message> + <source>Save QR Code</source> + <translation>Save QR Code</translation> + </message> + <message> + <source>PNG Image (*.png)</source> + <translation>PNG Image (*.png)</translation> + </message> +</context> <context> <name>RPCConsole</name> - </context> + <message> + <source>N/A</source> + <translation>N/A</translation> + </message> + <message> + <source>Client version</source> + <translation>Client version</translation> + </message> + <message> + <source>&Information</source> + <translation>&Information</translation> + </message> + <message> + <source>General</source> + <translation>General</translation> + </message> + <message> + <source>Using BerkeleyDB version</source> + <translation>Using BerkeleyDB version</translation> + </message> + <message> + <source>Datadir</source> + <translation>Datadir</translation> + </message> + <message> + <source>To specify a non-default location of the data directory use the '%1' option.</source> + <translation>To specify a non-default location of the data directory use the '%1' option.</translation> + </message> + <message> + <source>Blocksdir</source> + <translation>Blocksdir</translation> + </message> + <message> + <source>To specify a non-default location of the blocks directory use the '%1' option.</source> + <translation>To specify a non-default location of the blocks directory use the '%1' option.</translation> + </message> + <message> + <source>Startup time</source> + <translation>Startup time</translation> + </message> + <message> + <source>Network</source> + <translation>Network</translation> + </message> + <message> + <source>Name</source> + <translation>Name</translation> + </message> + <message> + <source>Number of connections</source> + <translation>Number of connections</translation> + </message> + <message> + <source>Block chain</source> + <translation>Block chain</translation> + </message> + <message> + <source>Memory Pool</source> + <translation>Memory Pool</translation> + </message> + <message> + <source>Current number of transactions</source> + <translation>Current number of transactions</translation> + </message> + <message> + <source>Memory usage</source> + <translation>Memory usage</translation> + </message> + <message> + <source>Wallet: </source> + <translation>Wallet: </translation> + </message> + <message> + <source>(none)</source> + <translation>(none)</translation> + </message> + <message> + <source>&Reset</source> + <translation>&Reset</translation> + </message> + <message> + <source>Received</source> + <translation>Received</translation> + </message> + <message> + <source>Sent</source> + <translation>Sent</translation> + </message> + <message> + <source>&Peers</source> + <translation>&Peers</translation> + </message> + <message> + <source>Banned peers</source> + <translation>Banned peers</translation> + </message> + <message> + <source>Select a peer to view detailed information.</source> + <translation>Select a peer to view detailed information.</translation> + </message> + <message> + <source>Direction</source> + <translation>Direction</translation> + </message> + <message> + <source>Version</source> + <translation>Version</translation> + </message> + <message> + <source>Starting Block</source> + <translation>Starting Block</translation> + </message> + <message> + <source>Synced Headers</source> + <translation>Synced Headers</translation> + </message> + <message> + <source>Synced Blocks</source> + <translation>Synced Blocks</translation> + </message> + <message> + <source>The mapped Autonomous System used for diversifying peer selection.</source> + <translation>The mapped Autonomous System used for diversifying peer selection.</translation> + </message> + <message> + <source>Mapped AS</source> + <translation>Mapped AS</translation> + </message> + <message> + <source>User Agent</source> + <translation>User Agent</translation> + </message> + <message> + <source>Node window</source> + <translation>Node window</translation> + </message> + <message> + <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source> + <translation>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</translation> + </message> + <message> + <source>Decrease font size</source> + <translation>Decrease font size</translation> + </message> + <message> + <source>Increase font size</source> + <translation>Increase font size</translation> + </message> + <message> + <source>Services</source> + <translation>Services</translation> + </message> + <message> + <source>Connection Time</source> + <translation>Connection Time</translation> + </message> + <message> + <source>Last Send</source> + <translation>Last Send</translation> + </message> + <message> + <source>Last Receive</source> + <translation>Last Receive</translation> + </message> + <message> + <source>Ping Time</source> + <translation>Ping Time</translation> + </message> + <message> + <source>The duration of a currently outstanding ping.</source> + <translation>The duration of a currently outstanding ping.</translation> + </message> + <message> + <source>Ping Wait</source> + <translation>Ping Wait</translation> + </message> + <message> + <source>Min Ping</source> + <translation>Min Ping</translation> + </message> + <message> + <source>Time Offset</source> + <translation>Time Offset</translation> + </message> + <message> + <source>Last block time</source> + <translation>Last block time</translation> + </message> + <message> + <source>&Open</source> + <translation>&Open</translation> + </message> + <message> + <source>&Console</source> + <translation>&Console</translation> + </message> + <message> + <source>&Network Traffic</source> + <translation>&Network Traffic</translation> + </message> + <message> + <source>Totals</source> + <translation>Totals</translation> + </message> + <message> + <source>In:</source> + <translation>In:</translation> + </message> + <message> + <source>Out:</source> + <translation>Out:</translation> + </message> + <message> + <source>Debug log file</source> + <translation>Debug log file</translation> + </message> + <message> + <source>Clear console</source> + <translation>Clear console</translation> + </message> + <message> + <source>1 &hour</source> + <translation>1 &hour</translation> + </message> + <message> + <source>1 &day</source> + <translation>1 &day</translation> + </message> + <message> + <source>1 &week</source> + <translation>1 &week</translation> + </message> + <message> + <source>1 &year</source> + <translation>1 &year</translation> + </message> + <message> + <source>&Disconnect</source> + <translation>&Disconnect</translation> + </message> + <message> + <source>Ban for</source> + <translation>Ban for</translation> + </message> + <message> + <source>&Unban</source> + <translation>&Unban</translation> + </message> + <message> + <source>Welcome to the %1 RPC console.</source> + <translation>Welcome to the %1 RPC console.</translation> + </message> + <message> + <source>Use up and down arrows to navigate history, and %1 to clear screen.</source> + <translation>Use up and down arrows to navigate history, and %1 to clear screen.</translation> + </message> + <message> + <source>Type %1 for an overview of available commands.</source> + <translation>Type %1 for an overview of available commands.</translation> + </message> + <message> + <source>For more information on using this console type %1.</source> + <translation>For more information on using this console type %1.</translation> + </message> + <message> + <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source> + <translation>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</translation> + </message> + <message> + <source>Network activity disabled</source> + <translation>Network activity disabled</translation> + </message> + <message> + <source>Executing command without any wallet</source> + <translation>Executing command without any wallet</translation> + </message> + <message> + <source>Executing command using "%1" wallet</source> + <translation>Executing command using "%1" wallet</translation> + </message> + <message> + <source>(node id: %1)</source> + <translation>(node id: %1)</translation> + </message> + <message> + <source>via %1</source> + <translation>via %1</translation> + </message> + <message> + <source>never</source> + <translation>never</translation> + </message> + <message> + <source>Inbound</source> + <translation>Inbound</translation> + </message> + <message> + <source>Outbound</source> + <translation>Outbound</translation> + </message> + <message> + <source>Unknown</source> + <translation>Unknown</translation> + </message> +</context> <context> <name>ReceiveCoinsDialog</name> + <message> + <source>&Amount:</source> + <translation>&Amount:</translation> + </message> + <message> + <source>&Label:</source> + <translation>&Label:</translation> + </message> + <message> + <source>&Message:</source> + <translation>&Message:</translation> + </message> + <message> + <source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source> + <translation>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</translation> + </message> + <message> + <source>An optional label to associate with the new receiving address.</source> + <translation>An optional label to associate with the new receiving address.</translation> + </message> + <message> + <source>Use this form to request payments. All fields are <b>optional</b>.</source> + <translation>Use this form to request payments. All fields are <b>optional</b>.</translation> + </message> + <message> + <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source> + <translation>An optional amount to request. Leave this empty or zero to not request a specific amount.</translation> + </message> + <message> + <source>An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</source> + <translation>An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</translation> + </message> + <message> + <source>An optional message that is attached to the payment request and may be displayed to the sender.</source> + <translation>An optional message that is attached to the payment request and may be displayed to the sender.</translation> + </message> + <message> + <source>&Create new receiving address</source> + <translation>&Create new receiving address</translation> + </message> + <message> + <source>Clear all fields of the form.</source> + <translation>Clear all fields of the form.</translation> + </message> + <message> + <source>Clear</source> + <translation>Clear</translation> + </message> + <message> + <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source> + <translation>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</translation> + </message> + <message> + <source>Generate native segwit (Bech32) address</source> + <translation>Generate native segwit (Bech32) address</translation> + </message> + <message> + <source>Requested payments history</source> + <translation>Requested payments history</translation> + </message> + <message> + <source>Show the selected request (does the same as double clicking an entry)</source> + <translation>Show the selected request (does the same as double clicking an entry)</translation> + </message> + <message> + <source>Show</source> + <translation>Show</translation> + </message> + <message> + <source>Remove the selected entries from the list</source> + <translation>Remove the selected entries from the list</translation> + </message> + <message> + <source>Remove</source> + <translation>Remove</translation> + </message> + <message> + <source>Copy URI</source> + <translation>Copy URI</translation> + </message> + <message> + <source>Copy label</source> + <translation>Copy label</translation> + </message> + <message> + <source>Copy message</source> + <translation>Copy message</translation> + </message> + <message> + <source>Copy amount</source> + <translation>Copy amount</translation> + </message> + <message> + <source>Could not unlock wallet.</source> + <translation>Could not unlock wallet.</translation> + </message> </context> <context> <name>ReceiveRequestDialog</name> <message> + <source>Amount:</source> + <translation>Amount:</translation> + </message> + <message> + <source>Message:</source> + <translation>Message:</translation> + </message> + <message> <source>Wallet:</source> <translation>dompet</translation> </message> <message> + <source>Copy &URI</source> + <translation>Copy &URI</translation> + </message> + <message> <source>Copy &Address</source> <translation>&Salin Alamat</translation> </message> - </context> + <message> + <source>&Save Image...</source> + <translation>&Save Image...</translation> + </message> + <message> + <source>Request payment to %1</source> + <translation>Request payment to %1</translation> + </message> + <message> + <source>Payment information</source> + <translation>Payment information</translation> + </message> +</context> <context> <name>RecentRequestsTableModel</name> <message> + <source>Date</source> + <translation>Date</translation> + </message> + <message> <source>Label</source> <translation>Label</translation> </message> <message> + <source>Message</source> + <translation>Message</translation> + </message> + <message> <source>(no label)</source> <translation>(tiada label)</translation> </message> - </context> + <message> + <source>(no message)</source> + <translation>(no message)</translation> + </message> + <message> + <source>(no amount requested)</source> + <translation>(no amount requested)</translation> + </message> + <message> + <source>Requested</source> + <translation>Requested</translation> + </message> +</context> <context> <name>SendCoinsDialog</name> <message> + <source>Send Coins</source> + <translation>Send Coins</translation> + </message> + <message> + <source>Coin Control Features</source> + <translation>Coin Control Features</translation> + </message> + <message> + <source>Inputs...</source> + <translation>Inputs...</translation> + </message> + <message> + <source>automatically selected</source> + <translation>automatically selected</translation> + </message> + <message> + <source>Insufficient funds!</source> + <translation>Insufficient funds!</translation> + </message> + <message> + <source>Quantity:</source> + <translation>Quantity:</translation> + </message> + <message> + <source>Bytes:</source> + <translation>Bytes:</translation> + </message> + <message> + <source>Amount:</source> + <translation>Amount:</translation> + </message> + <message> + <source>Fee:</source> + <translation>Fee:</translation> + </message> + <message> + <source>After Fee:</source> + <translation>After Fee:</translation> + </message> + <message> + <source>Change:</source> + <translation>Change:</translation> + </message> + <message> + <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source> + <translation>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</translation> + </message> + <message> + <source>Custom change address</source> + <translation>Custom change address</translation> + </message> + <message> + <source>Transaction Fee:</source> + <translation>Transaction Fee:</translation> + </message> + <message> + <source>Choose...</source> + <translation>Choose...</translation> + </message> + <message> + <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source> + <translation>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</translation> + </message> + <message> + <source>Warning: Fee estimation is currently not possible.</source> + <translation>Warning: Fee estimation is currently not possible.</translation> + </message> + <message> + <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size. + +Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source> + <translation>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size. + +Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</translation> + </message> + <message> + <source>per kilobyte</source> + <translation>per kilobyte</translation> + </message> + <message> + <source>Hide</source> + <translation>Hide</translation> + </message> + <message> + <source>Recommended:</source> + <translation>Recommended:</translation> + </message> + <message> + <source>Custom:</source> + <translation>Custom:</translation> + </message> + <message> + <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source> + <translation>(Smart fee not initialized yet. This usually takes a few blocks...)</translation> + </message> + <message> + <source>Send to multiple recipients at once</source> + <translation>Send to multiple recipients at once</translation> + </message> + <message> + <source>Add &Recipient</source> + <translation>Add &Recipient</translation> + </message> + <message> + <source>Clear all fields of the form.</source> + <translation>Clear all fields of the form.</translation> + </message> + <message> + <source>Dust:</source> + <translation>Dust:</translation> + </message> + <message> + <source>Hide transaction fee settings</source> + <translation>Hide transaction fee settings</translation> + </message> + <message> + <source>When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> + <translation>When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</translation> + </message> + <message> + <source>A too low fee might result in a never confirming transaction (read the tooltip)</source> + <translation>A too low fee might result in a never confirming transaction (read the tooltip)</translation> + </message> + <message> + <source>Confirmation time target:</source> + <translation>Confirmation time target:</translation> + </message> + <message> + <source>Enable Replace-By-Fee</source> + <translation>Enable Replace-By-Fee</translation> + </message> + <message> + <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source> + <translation>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</translation> + </message> + <message> + <source>Clear &All</source> + <translation>Clear &All</translation> + </message> + <message> <source>Balance:</source> <translation>Baki</translation> </message> <message> + <source>Confirm the send action</source> + <translation>Confirm the send action</translation> + </message> + <message> + <source>S&end</source> + <translation>S&end</translation> + </message> + <message> + <source>Copy quantity</source> + <translation>Copy quantity</translation> + </message> + <message> + <source>Copy amount</source> + <translation>Copy amount</translation> + </message> + <message> + <source>Copy fee</source> + <translation>Copy fee</translation> + </message> + <message> + <source>Copy after fee</source> + <translation>Copy after fee</translation> + </message> + <message> + <source>Copy bytes</source> + <translation>Copy bytes</translation> + </message> + <message> + <source>Copy dust</source> + <translation>Copy dust</translation> + </message> + <message> + <source>Copy change</source> + <translation>Copy change</translation> + </message> + <message> + <source>%1 (%2 blocks)</source> + <translation>%1 (%2 blocks)</translation> + </message> + <message> + <source>Cr&eate Unsigned</source> + <translation>Cr&eate Unsigned</translation> + </message> + <message> + <source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source> + <translation>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation> + </message> + <message> + <source> from wallet '%1'</source> + <translation> from wallet '%1'</translation> + </message> + <message> + <source>%1 to '%2'</source> + <translation>%1 to '%2'</translation> + </message> + <message> + <source>%1 to %2</source> + <translation>%1 to %2</translation> + </message> + <message> + <source>Do you want to draft this transaction?</source> + <translation>Do you want to draft this transaction?</translation> + </message> + <message> + <source>Are you sure you want to send?</source> + <translation>Are you sure you want to send?</translation> + </message> + <message> + <source>or</source> + <translation>or</translation> + </message> + <message> + <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source> + <translation>You can increase the fee later (signals Replace-By-Fee, BIP-125).</translation> + </message> + <message> + <source>Please, review your transaction.</source> + <translation>Please, review your transaction.</translation> + </message> + <message> + <source>Transaction fee</source> + <translation>Transaction fee</translation> + </message> + <message> + <source>Not signalling Replace-By-Fee, BIP-125.</source> + <translation>Not signalling Replace-By-Fee, BIP-125.</translation> + </message> + <message> + <source>Total Amount</source> + <translation>Total Amount</translation> + </message> + <message> + <source>To review recipient list click "Show Details..."</source> + <translation>To review recipient list click "Show Details..."</translation> + </message> + <message> + <source>Confirm send coins</source> + <translation>Confirm send coins</translation> + </message> + <message> + <source>Confirm transaction proposal</source> + <translation>Confirm transaction proposal</translation> + </message> + <message> + <source>Send</source> + <translation>Send</translation> + </message> + <message> + <source>Watch-only balance:</source> + <translation>Watch-only balance:</translation> + </message> + <message> + <source>The recipient address is not valid. Please recheck.</source> + <translation>The recipient address is not valid. Please recheck.</translation> + </message> + <message> + <source>The amount to pay must be larger than 0.</source> + <translation>The amount to pay must be larger than 0.</translation> + </message> + <message> + <source>The amount exceeds your balance.</source> + <translation>The amount exceeds your balance.</translation> + </message> + <message> + <source>The total exceeds your balance when the %1 transaction fee is included.</source> + <translation>The total exceeds your balance when the %1 transaction fee is included.</translation> + </message> + <message> + <source>Duplicate address found: addresses should only be used once each.</source> + <translation>Duplicate address found: addresses should only be used once each.</translation> + </message> + <message> + <source>Transaction creation failed!</source> + <translation>Transaction creation failed!</translation> + </message> + <message> + <source>A fee higher than %1 is considered an absurdly high fee.</source> + <translation>A fee higher than %1 is considered an absurdly high fee.</translation> + </message> + <message> + <source>Payment request expired.</source> + <translation>Payment request expired.</translation> + </message> + <message> + <source>Warning: Invalid Bitcoin address</source> + <translation>Warning: Invalid Bitcoin address</translation> + </message> + <message> + <source>Warning: Unknown change address</source> + <translation>Warning: Unknown change address</translation> + </message> + <message> + <source>Confirm custom change address</source> + <translation>Confirm custom change address</translation> + </message> + <message> + <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source> + <translation>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</translation> + </message> + <message> <source>(no label)</source> <translation>(tiada label)</translation> </message> </context> <context> <name>SendCoinsEntry</name> - </context> + <message> + <source>A&mount:</source> + <translation>A&mount:</translation> + </message> + <message> + <source>Pay &To:</source> + <translation>Pay &To:</translation> + </message> + <message> + <source>&Label:</source> + <translation>&Label:</translation> + </message> + <message> + <source>Choose previously used address</source> + <translation>Choose previously used address</translation> + </message> + <message> + <source>The Bitcoin address to send the payment to</source> + <translation>The Bitcoin address to send the payment to</translation> + </message> + <message> + <source>Alt+A</source> + <translation>Alt+A</translation> + </message> + <message> + <source>Paste address from clipboard</source> + <translation>Paste address from clipboard</translation> + </message> + <message> + <source>Alt+P</source> + <translation>Alt+P</translation> + </message> + <message> + <source>Remove this entry</source> + <translation>Remove this entry</translation> + </message> + <message> + <source>The amount to send in the selected unit</source> + <translation>The amount to send in the selected unit</translation> + </message> + <message> + <source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source> + <translation>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</translation> + </message> + <message> + <source>S&ubtract fee from amount</source> + <translation>S&ubtract fee from amount</translation> + </message> + <message> + <source>Use available balance</source> + <translation>Use available balance</translation> + </message> + <message> + <source>Message:</source> + <translation>Message:</translation> + </message> + <message> + <source>This is an unauthenticated payment request.</source> + <translation>This is an unauthenticated payment request.</translation> + </message> + <message> + <source>This is an authenticated payment request.</source> + <translation>This is an authenticated payment request.</translation> + </message> + <message> + <source>Enter a label for this address to add it to the list of used addresses</source> + <translation>Enter a label for this address to add it to the list of used addresses</translation> + </message> + <message> + <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source> + <translation>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</translation> + </message> + <message> + <source>Pay To:</source> + <translation>Pay To:</translation> + </message> + <message> + <source>Memo:</source> + <translation>Memo:</translation> + </message> +</context> <context> <name>ShutdownWindow</name> - </context> + <message> + <source>%1 is shutting down...</source> + <translation>%1 is shutting down...</translation> + </message> + <message> + <source>Do not shut down the computer until this window disappears.</source> + <translation>Do not shut down the computer until this window disappears.</translation> + </message> +</context> <context> <name>SignVerifyMessageDialog</name> - </context> + <message> + <source>Signatures - Sign / Verify a Message</source> + <translation>Signatures - Sign / Verify a Message</translation> + </message> + <message> + <source>&Sign Message</source> + <translation>&Sign Message</translation> + </message> + <message> + <source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source> + <translation>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</translation> + </message> + <message> + <source>The Bitcoin address to sign the message with</source> + <translation>The Bitcoin address to sign the message with</translation> + </message> + <message> + <source>Choose previously used address</source> + <translation>Choose previously used address</translation> + </message> + <message> + <source>Alt+A</source> + <translation>Alt+A</translation> + </message> + <message> + <source>Paste address from clipboard</source> + <translation>Paste address from clipboard</translation> + </message> + <message> + <source>Alt+P</source> + <translation>Alt+P</translation> + </message> + <message> + <source>Enter the message you want to sign here</source> + <translation>Enter the message you want to sign here</translation> + </message> + <message> + <source>Signature</source> + <translation>Signature</translation> + </message> + <message> + <source>Copy the current signature to the system clipboard</source> + <translation>Copy the current signature to the system clipboard</translation> + </message> + <message> + <source>Sign the message to prove you own this Bitcoin address</source> + <translation>Sign the message to prove you own this Bitcoin address</translation> + </message> + <message> + <source>Sign &Message</source> + <translation>Sign &Message</translation> + </message> + <message> + <source>Reset all sign message fields</source> + <translation>Reset all sign message fields</translation> + </message> + <message> + <source>Clear &All</source> + <translation>Clear &All</translation> + </message> + <message> + <source>&Verify Message</source> + <translation>&Verify Message</translation> + </message> + <message> + <source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source> + <translation>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</translation> + </message> + <message> + <source>The Bitcoin address the message was signed with</source> + <translation>The Bitcoin address the message was signed with</translation> + </message> + <message> + <source>The signed message to verify</source> + <translation>The signed message to verify</translation> + </message> + <message> + <source>The signature given when the message was signed</source> + <translation>The signature given when the message was signed</translation> + </message> + <message> + <source>Verify the message to ensure it was signed with the specified Bitcoin address</source> + <translation>Verify the message to ensure it was signed with the specified Bitcoin address</translation> + </message> + <message> + <source>Verify &Message</source> + <translation>Verify &Message</translation> + </message> + <message> + <source>Reset all verify message fields</source> + <translation>Reset all verify message fields</translation> + </message> + <message> + <source>Click "Sign Message" to generate signature</source> + <translation>Click "Sign Message" to generate signature</translation> + </message> + <message> + <source>The entered address is invalid.</source> + <translation>The entered address is invalid.</translation> + </message> + <message> + <source>Please check the address and try again.</source> + <translation>Please check the address and try again.</translation> + </message> + <message> + <source>The entered address does not refer to a key.</source> + <translation>The entered address does not refer to a key.</translation> + </message> + <message> + <source>Wallet unlock was cancelled.</source> + <translation>Wallet unlock was cancelled.</translation> + </message> + <message> + <source>No error</source> + <translation>No error</translation> + </message> + <message> + <source>Private key for the entered address is not available.</source> + <translation>Private key for the entered address is not available.</translation> + </message> + <message> + <source>Message signing failed.</source> + <translation>Message signing failed.</translation> + </message> + <message> + <source>Message signed.</source> + <translation>Message signed.</translation> + </message> + <message> + <source>The signature could not be decoded.</source> + <translation>The signature could not be decoded.</translation> + </message> + <message> + <source>Please check the signature and try again.</source> + <translation>Please check the signature and try again.</translation> + </message> + <message> + <source>The signature did not match the message digest.</source> + <translation>The signature did not match the message digest.</translation> + </message> + <message> + <source>Message verification failed.</source> + <translation>Message verification failed.</translation> + </message> + <message> + <source>Message verified.</source> + <translation>Message verified.</translation> + </message> +</context> <context> <name>TrafficGraphWidget</name> - </context> + <message> + <source>KB/s</source> + <translation>KB/s</translation> + </message> +</context> <context> <name>TransactionDesc</name> <message> + <source>Open until %1</source> + <translation>Open until %1</translation> + </message> + <message> + <source>conflicted with a transaction with %1 confirmations</source> + <translation>conflicted with a transaction with %1 confirmations</translation> + </message> + <message> + <source>0/unconfirmed, %1</source> + <translation>0/unconfirmed, %1</translation> + </message> + <message> + <source>in memory pool</source> + <translation>in memory pool</translation> + </message> + <message> + <source>not in memory pool</source> + <translation>not in memory pool</translation> + </message> + <message> + <source>abandoned</source> + <translation>abandoned</translation> + </message> + <message> + <source>%1/unconfirmed</source> + <translation>%1/unconfirmed</translation> + </message> + <message> + <source>%1 confirmations</source> + <translation>%1 confirmations</translation> + </message> + <message> + <source>Status</source> + <translation>Status</translation> + </message> + <message> + <source>Date</source> + <translation>Date</translation> + </message> + <message> + <source>Source</source> + <translation>Source</translation> + </message> + <message> + <source>Generated</source> + <translation>Generated</translation> + </message> + <message> + <source>From</source> + <translation>From</translation> + </message> + <message> + <source>unknown</source> + <translation>unknown</translation> + </message> + <message> + <source>To</source> + <translation>To</translation> + </message> + <message> + <source>own address</source> + <translation>own address</translation> + </message> + <message> + <source>watch-only</source> + <translation>watch-only</translation> + </message> + <message> + <source>label</source> + <translation>label</translation> + </message> + <message> + <source>Credit</source> + <translation>Credit</translation> + </message> + <message> + <source>not accepted</source> + <translation>not accepted</translation> + </message> + <message> + <source>Debit</source> + <translation>Debit</translation> + </message> + <message> + <source>Total debit</source> + <translation>Total debit</translation> + </message> + <message> + <source>Total credit</source> + <translation>Total credit</translation> + </message> + <message> + <source>Transaction fee</source> + <translation>Transaction fee</translation> + </message> + <message> + <source>Net amount</source> + <translation>Net amount</translation> + </message> + <message> + <source>Message</source> + <translation>Message</translation> + </message> + <message> + <source>Comment</source> + <translation>Comment</translation> + </message> + <message> + <source>Transaction ID</source> + <translation>Transaction ID</translation> + </message> + <message> + <source>Transaction total size</source> + <translation>Transaction total size</translation> + </message> + <message> + <source>Transaction virtual size</source> + <translation>Transaction virtual size</translation> + </message> + <message> + <source>Output index</source> + <translation>Output index</translation> + </message> + <message> + <source> (Certificate was not verified)</source> + <translation> (Certificate was not verified)</translation> + </message> + <message> + <source>Merchant</source> + <translation>Merchant</translation> + </message> + <message> + <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source> + <translation>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</translation> + </message> + <message> + <source>Debug information</source> + <translation>Debug information</translation> + </message> + <message> + <source>Transaction</source> + <translation>Transaction</translation> + </message> + <message> + <source>Inputs</source> + <translation>Inputs</translation> + </message> + <message> <source>Amount</source> <translation>Amount</translation> </message> - </context> + <message> + <source>true</source> + <translation>true</translation> + </message> + <message> + <source>false</source> + <translation>false</translation> + </message> +</context> <context> <name>TransactionDescDialog</name> - </context> + <message> + <source>This pane shows a detailed description of the transaction</source> + <translation>This pane shows a detailed description of the transaction</translation> + </message> + <message> + <source>Details for %1</source> + <translation>Details for %1</translation> + </message> +</context> <context> <name>TransactionTableModel</name> <message> + <source>Date</source> + <translation>Date</translation> + </message> + <message> + <source>Type</source> + <translation>Type</translation> + </message> + <message> <source>Label</source> <translation>Label</translation> </message> <message> + <source>Open until %1</source> + <translation>Open until %1</translation> + </message> + <message> + <source>Unconfirmed</source> + <translation>Unconfirmed</translation> + </message> + <message> + <source>Abandoned</source> + <translation>Abandoned</translation> + </message> + <message> + <source>Confirming (%1 of %2 recommended confirmations)</source> + <translation>Confirming (%1 of %2 recommended confirmations)</translation> + </message> + <message> + <source>Confirmed (%1 confirmations)</source> + <translation>Confirmed (%1 confirmations)</translation> + </message> + <message> + <source>Conflicted</source> + <translation>Conflicted</translation> + </message> + <message> + <source>Immature (%1 confirmations, will be available after %2)</source> + <translation>Immature (%1 confirmations, will be available after %2)</translation> + </message> + <message> + <source>Generated but not accepted</source> + <translation>Generated but not accepted</translation> + </message> + <message> + <source>Received with</source> + <translation>Received with</translation> + </message> + <message> + <source>Received from</source> + <translation>Received from</translation> + </message> + <message> + <source>Sent to</source> + <translation>Sent to</translation> + </message> + <message> + <source>Payment to yourself</source> + <translation>Payment to yourself</translation> + </message> + <message> + <source>Mined</source> + <translation>Mined</translation> + </message> + <message> + <source>watch-only</source> + <translation>watch-only</translation> + </message> + <message> + <source>(n/a)</source> + <translation>(n/a)</translation> + </message> + <message> <source>(no label)</source> <translation>(tiada label)</translation> </message> - </context> + <message> + <source>Transaction status. Hover over this field to show number of confirmations.</source> + <translation>Transaction status. Hover over this field to show number of confirmations.</translation> + </message> + <message> + <source>Date and time that the transaction was received.</source> + <translation>Date and time that the transaction was received.</translation> + </message> + <message> + <source>Type of transaction.</source> + <translation>Type of transaction.</translation> + </message> + <message> + <source>Whether or not a watch-only address is involved in this transaction.</source> + <translation>Whether or not a watch-only address is involved in this transaction.</translation> + </message> + <message> + <source>User-defined intent/purpose of the transaction.</source> + <translation>User-defined intent/purpose of the transaction.</translation> + </message> + <message> + <source>Amount removed from or added to balance.</source> + <translation>Amount removed from or added to balance.</translation> + </message> +</context> <context> <name>TransactionView</name> <message> + <source>All</source> + <translation>All</translation> + </message> + <message> + <source>Today</source> + <translation>Today</translation> + </message> + <message> + <source>This week</source> + <translation>This week</translation> + </message> + <message> + <source>This month</source> + <translation>This month</translation> + </message> + <message> + <source>Last month</source> + <translation>Last month</translation> + </message> + <message> + <source>This year</source> + <translation>This year</translation> + </message> + <message> + <source>Range...</source> + <translation>Range...</translation> + </message> + <message> + <source>Received with</source> + <translation>Received with</translation> + </message> + <message> + <source>Sent to</source> + <translation>Sent to</translation> + </message> + <message> + <source>To yourself</source> + <translation>To yourself</translation> + </message> + <message> + <source>Mined</source> + <translation>Mined</translation> + </message> + <message> + <source>Other</source> + <translation>Other</translation> + </message> + <message> + <source>Enter address, transaction id, or label to search</source> + <translation>Enter address, transaction id, or label to search</translation> + </message> + <message> + <source>Min amount</source> + <translation>Min amount</translation> + </message> + <message> + <source>Abandon transaction</source> + <translation>Abandon transaction</translation> + </message> + <message> + <source>Increase transaction fee</source> + <translation>Increase transaction fee</translation> + </message> + <message> + <source>Copy address</source> + <translation>Copy address</translation> + </message> + <message> + <source>Copy label</source> + <translation>Copy label</translation> + </message> + <message> + <source>Copy amount</source> + <translation>Copy amount</translation> + </message> + <message> + <source>Copy transaction ID</source> + <translation>Copy transaction ID</translation> + </message> + <message> + <source>Copy raw transaction</source> + <translation>Copy raw transaction</translation> + </message> + <message> + <source>Copy full transaction details</source> + <translation>Copy full transaction details</translation> + </message> + <message> + <source>Edit label</source> + <translation>Edit label</translation> + </message> + <message> + <source>Show transaction details</source> + <translation>Show transaction details</translation> + </message> + <message> + <source>Export Transaction History</source> + <translation>Export Transaction History</translation> + </message> + <message> <source>Comma separated file (*.csv)</source> <translation>Fail dibahagi oleh koma(*.csv)</translation> </message> <message> + <source>Confirmed</source> + <translation>Confirmed</translation> + </message> + <message> + <source>Watch-only</source> + <translation>Watch-only</translation> + </message> + <message> + <source>Date</source> + <translation>Date</translation> + </message> + <message> + <source>Type</source> + <translation>Type</translation> + </message> + <message> <source>Label</source> <translation>Label</translation> </message> @@ -603,26 +3059,118 @@ Alihkan fail data ke dalam tab semasa</translation> <translation>Alamat</translation> </message> <message> + <source>ID</source> + <translation>ID</translation> + </message> + <message> <source>Exporting Failed</source> <translation>Mengeksport Gagal</translation> </message> - </context> + <message> + <source>There was an error trying to save the transaction history to %1.</source> + <translation>There was an error trying to save the transaction history to %1.</translation> + </message> + <message> + <source>Exporting Successful</source> + <translation>Exporting Successful</translation> + </message> + <message> + <source>The transaction history was successfully saved to %1.</source> + <translation>The transaction history was successfully saved to %1.</translation> + </message> + <message> + <source>Range:</source> + <translation>Range:</translation> + </message> + <message> + <source>to</source> + <translation>to</translation> + </message> +</context> <context> <name>UnitDisplayStatusBarControl</name> - </context> + <message> + <source>Unit to show amounts in. Click to select another unit.</source> + <translation>Unit to show amounts in. Click to select another unit.</translation> + </message> +</context> <context> <name>WalletController</name> <message> <source>Close wallet</source> <translation>Tutup Wallet</translation> </message> + <message> + <source>Are you sure you wish to close the wallet <i>%1</i>?</source> + <translation>Are you sure you wish to close the wallet <i>%1</i>?</translation> + </message> + <message> + <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source> + <translation>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</translation> + </message> </context> <context> <name>WalletFrame</name> - </context> + <message> + <source>Create a new wallet</source> + <translation>Create a new wallet</translation> + </message> +</context> <context> <name>WalletModel</name> <message> + <source>Send Coins</source> + <translation>Send Coins</translation> + </message> + <message> + <source>Fee bump error</source> + <translation>Fee bump error</translation> + </message> + <message> + <source>Increasing transaction fee failed</source> + <translation>Increasing transaction fee failed</translation> + </message> + <message> + <source>Do you want to increase the fee?</source> + <translation>Do you want to increase the fee?</translation> + </message> + <message> + <source>Do you want to draft a transaction with fee increase?</source> + <translation>Do you want to draft a transaction with fee increase?</translation> + </message> + <message> + <source>Current fee:</source> + <translation>Current fee:</translation> + </message> + <message> + <source>Increase:</source> + <translation>Increase:</translation> + </message> + <message> + <source>New fee:</source> + <translation>New fee:</translation> + </message> + <message> + <source>Confirm fee bump</source> + <translation>Confirm fee bump</translation> + </message> + <message> + <source>Can't draft transaction.</source> + <translation>Can't draft transaction.</translation> + </message> + <message> + <source>PSBT copied</source> + <translation>PSBT copied</translation> + </message> + <message> + <source>Can't sign transaction.</source> + <translation>Can't sign transaction.</translation> + </message> + <message> + <source>Could not commit transaction</source> + <translation>Could not commit transaction</translation> + </message> + <message> <source>default wallet</source> <translation>dompet lalai </translation> @@ -643,14 +3191,500 @@ Alihkan fail data ke dalam tab semasa</translation> <source>Error</source> <translation>Ralat</translation> </message> - </context> + <message> + <source>Backup Wallet</source> + <translation>Backup Wallet</translation> + </message> + <message> + <source>Wallet Data (*.dat)</source> + <translation>Wallet Data (*.dat)</translation> + </message> + <message> + <source>Backup Failed</source> + <translation>Backup Failed</translation> + </message> + <message> + <source>There was an error trying to save the wallet data to %1.</source> + <translation>There was an error trying to save the wallet data to %1.</translation> + </message> + <message> + <source>Backup Successful</source> + <translation>Backup Successful</translation> + </message> + <message> + <source>The wallet data was successfully saved to %1.</source> + <translation>The wallet data was successfully saved to %1.</translation> + </message> + <message> + <source>Cancel</source> + <translation>Cancel</translation> + </message> +</context> <context> <name>bitcoin-core</name> <message> + <source>Distributed under the MIT software license, see the accompanying file %s or %s</source> + <translation>Distributed under the MIT software license, see the accompanying file %s or %s</translation> + </message> + <message> + <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source> + <translation>Prune configured below the minimum of %d MiB. Please use a higher number.</translation> + </message> + <message> + <source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source> + <translation>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</translation> + </message> + <message> + <source>Pruning blockstore...</source> + <translation>Pruning blockstore...</translation> + </message> + <message> + <source>Unable to start HTTP server. See debug log for details.</source> + <translation>Unable to start HTTP server. See debug log for details.</translation> + </message> + <message> + <source>The %s developers</source> + <translation>The %s developers</translation> + </message> + <message> + <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source> + <translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation> + </message> + <message> + <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source> + <translation>Cannot provide specific connections and have addrman find outgoing connections at the same.</translation> + </message> + <message> + <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source> + <translation>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</translation> + </message> + <message> + <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> + <translation>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</translation> + </message> + <message> + <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source> + <translation>Please contribute if you find %s useful. Visit %s for further information about the software.</translation> + </message> + <message> + <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> + <translation>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</translation> + </message> + <message> + <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source> + <translation>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</translation> + </message> + <message> + <source>This is the transaction fee you may discard if change is smaller than dust at this level</source> + <translation>This is the transaction fee you may discard if change is smaller than dust at this level</translation> + </message> + <message> + <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source> + <translation>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</translation> + </message> + <message> + <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source> + <translation>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</translation> + </message> + <message> + <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source> + <translation>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</translation> + </message> + <message> + <source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source> + <translation>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation> + </message> + <message> + <source>-maxmempool must be at least %d MB</source> + <translation>-maxmempool must be at least %d MB</translation> + </message> + <message> + <source>Cannot resolve -%s address: '%s'</source> + <translation>Cannot resolve -%s address: '%s'</translation> + </message> + <message> + <source>Change index out of range</source> + <translation>Change index out of range</translation> + </message> + <message> + <source>Config setting for %s only applied on %s network when in [%s] section.</source> + <translation>Config setting for %s only applied on %s network when in [%s] section.</translation> + </message> + <message> + <source>Copyright (C) %i-%i</source> + <translation>Copyright (C) %i-%i</translation> + </message> + <message> + <source>Corrupted block database detected</source> + <translation>Corrupted block database detected</translation> + </message> + <message> + <source>Could not find asmap file %s</source> + <translation>Could not find asmap file %s</translation> + </message> + <message> + <source>Could not parse asmap file %s</source> + <translation>Could not parse asmap file %s</translation> + </message> + <message> + <source>Do you want to rebuild the block database now?</source> + <translation>Do you want to rebuild the block database now?</translation> + </message> + <message> + <source>Error initializing block database</source> + <translation>Error initializing block database</translation> + </message> + <message> + <source>Error initializing wallet database environment %s!</source> + <translation>Error initializing wallet database environment %s!</translation> + </message> + <message> + <source>Error loading %s</source> + <translation>Error loading %s</translation> + </message> + <message> + <source>Error loading %s: Private keys can only be disabled during creation</source> + <translation>Error loading %s: Private keys can only be disabled during creation</translation> + </message> + <message> + <source>Error loading %s: Wallet corrupted</source> + <translation>Error loading %s: Wallet corrupted</translation> + </message> + <message> + <source>Error loading %s: Wallet requires newer version of %s</source> + <translation>Error loading %s: Wallet requires newer version of %s</translation> + </message> + <message> + <source>Error loading block database</source> + <translation>Error loading block database</translation> + </message> + <message> + <source>Error opening block database</source> + <translation>Error opening block database</translation> + </message> + <message> + <source>Failed to listen on any port. Use -listen=0 if you want this.</source> + <translation>Failed to listen on any port. Use -listen=0 if you want this.</translation> + </message> + <message> + <source>Failed to rescan the wallet during initialization</source> + <translation>Failed to rescan the wallet during initialization</translation> + </message> + <message> + <source>Importing...</source> + <translation>Importing...</translation> + </message> + <message> + <source>Incorrect or no genesis block found. Wrong datadir for network?</source> + <translation>Incorrect or no genesis block found. Wrong datadir for network?</translation> + </message> + <message> + <source>Initialization sanity check failed. %s is shutting down.</source> + <translation>Initialization sanity check failed. %s is shutting down.</translation> + </message> + <message> + <source>Invalid P2P permission: '%s'</source> + <translation>Invalid P2P permission: '%s'</translation> + </message> + <message> + <source>Invalid amount for -%s=<amount>: '%s'</source> + <translation>Invalid amount for -%s=<amount>: '%s'</translation> + </message> + <message> + <source>Invalid amount for -discardfee=<amount>: '%s'</source> + <translation>Invalid amount for -discardfee=<amount>: '%s'</translation> + </message> + <message> + <source>Invalid amount for -fallbackfee=<amount>: '%s'</source> + <translation>Invalid amount for -fallbackfee=<amount>: '%s'</translation> + </message> + <message> + <source>Specified blocks directory "%s" does not exist.</source> + <translation>Specified blocks directory "%s" does not exist.</translation> + </message> + <message> + <source>Unknown address type '%s'</source> + <translation>Unknown address type '%s'</translation> + </message> + <message> + <source>Unknown change type '%s'</source> + <translation>Unknown change type '%s'</translation> + </message> + <message> + <source>Upgrading txindex database</source> + <translation>Upgrading txindex database</translation> + </message> + <message> + <source>Loading P2P addresses...</source> + <translation>Loading P2P addresses...</translation> + </message> + <message> + <source>Loading banlist...</source> + <translation>Loading banlist...</translation> + </message> + <message> + <source>Not enough file descriptors available.</source> + <translation>Not enough file descriptors available.</translation> + </message> + <message> + <source>Prune cannot be configured with a negative value.</source> + <translation>Prune cannot be configured with a negative value.</translation> + </message> + <message> + <source>Prune mode is incompatible with -txindex.</source> + <translation>Prune mode is incompatible with -txindex.</translation> + </message> + <message> + <source>Replaying blocks...</source> + <translation>Replaying blocks...</translation> + </message> + <message> + <source>Rewinding blocks...</source> + <translation>Rewinding blocks...</translation> + </message> + <message> + <source>The source code is available from %s.</source> + <translation>The source code is available from %s.</translation> + </message> + <message> + <source>Transaction fee and change calculation failed</source> + <translation>Transaction fee and change calculation failed</translation> + </message> + <message> + <source>Unable to bind to %s on this computer. %s is probably already running.</source> + <translation>Unable to bind to %s on this computer. %s is probably already running.</translation> + </message> + <message> + <source>Unable to generate keys</source> + <translation>Unable to generate keys</translation> + </message> + <message> + <source>Unsupported logging category %s=%s.</source> + <translation>Unsupported logging category %s=%s.</translation> + </message> + <message> + <source>Upgrading UTXO database</source> + <translation>Upgrading UTXO database</translation> + </message> + <message> + <source>User Agent comment (%s) contains unsafe characters.</source> + <translation>User Agent comment (%s) contains unsafe characters.</translation> + </message> + <message> + <source>Verifying blocks...</source> + <translation>Verifying blocks...</translation> + </message> + <message> + <source>Wallet needed to be rewritten: restart %s to complete</source> + <translation>Wallet needed to be rewritten: restart %s to complete</translation> + </message> + <message> + <source>Error: Listening for incoming connections failed (listen returned error %s)</source> + <translation>Error: Listening for incoming connections failed (listen returned error %s)</translation> + </message> + <message> + <source>Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source> + <translation>Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</translation> + </message> + <message> + <source>The transaction amount is too small to send after the fee has been deducted</source> + <translation>The transaction amount is too small to send after the fee has been deducted</translation> + </message> + <message> + <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source> + <translation>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</translation> + </message> + <message> + <source>Error reading from database, shutting down.</source> + <translation>Error reading from database, shutting down.</translation> + </message> + <message> + <source>Error upgrading chainstate database</source> + <translation>Error upgrading chainstate database</translation> + </message> + <message> + <source>Error: Disk space is low for %s</source> + <translation>Error: Disk space is low for %s</translation> + </message> + <message> + <source>Invalid -onion address or hostname: '%s'</source> + <translation>Invalid -onion address or hostname: '%s'</translation> + </message> + <message> + <source>Invalid -proxy address or hostname: '%s'</source> + <translation>Invalid -proxy address or hostname: '%s'</translation> + </message> + <message> + <source>Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)</source> + <translation>Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)</translation> + </message> + <message> + <source>Invalid netmask specified in -whitelist: '%s'</source> + <translation>Invalid netmask specified in -whitelist: '%s'</translation> + </message> + <message> + <source>Need to specify a port with -whitebind: '%s'</source> + <translation>Need to specify a port with -whitebind: '%s'</translation> + </message> + <message> + <source>Prune mode is incompatible with -blockfilterindex.</source> + <translation>Prune mode is incompatible with -blockfilterindex.</translation> + </message> + <message> + <source>Reducing -maxconnections from %d to %d, because of system limitations.</source> + <translation>Reducing -maxconnections from %d to %d, because of system limitations.</translation> + </message> + <message> + <source>Section [%s] is not recognized.</source> + <translation>Section [%s] is not recognized.</translation> + </message> + <message> + <source>Signing transaction failed</source> + <translation>Signing transaction failed</translation> + </message> + <message> + <source>Specified -walletdir "%s" does not exist</source> + <translation>Specified -walletdir "%s" does not exist</translation> + </message> + <message> + <source>Specified -walletdir "%s" is a relative path</source> + <translation>Specified -walletdir "%s" is a relative path</translation> + </message> + <message> + <source>Specified -walletdir "%s" is not a directory</source> + <translation>Specified -walletdir "%s" is not a directory</translation> + </message> + <message> + <source>The specified config file %s does not exist +</source> + <translation>The specified config file %s does not exist +</translation> + </message> + <message> + <source>The transaction amount is too small to pay the fee</source> + <translation>The transaction amount is too small to pay the fee</translation> + </message> + <message> + <source>This is experimental software.</source> + <translation>This is experimental software.</translation> + </message> + <message> + <source>Transaction amount too small</source> + <translation>Transaction amount too small</translation> + </message> + <message> + <source>Transaction too large</source> + <translation>Transaction too large</translation> + </message> + <message> + <source>Unable to bind to %s on this computer (bind returned error %s)</source> + <translation>Unable to bind to %s on this computer (bind returned error %s)</translation> + </message> + <message> + <source>Unable to create the PID file '%s': %s</source> + <translation>Unable to create the PID file '%s': %s</translation> + </message> + <message> + <source>Unable to generate initial keys</source> + <translation>Unable to generate initial keys</translation> + </message> + <message> + <source>Unknown -blockfilterindex value %s.</source> + <translation>Unknown -blockfilterindex value %s.</translation> + </message> + <message> + <source>Verifying wallet(s)...</source> + <translation>Verifying wallet(s)...</translation> + </message> + <message> + <source>Warning: unknown new rules activated (versionbit %i)</source> + <translation>Warning: unknown new rules activated (versionbit %i)</translation> + </message> + <message> + <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source> + <translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation> + </message> + <message> + <source>This is the transaction fee you may pay when fee estimates are not available.</source> + <translation>This is the transaction fee you may pay when fee estimates are not available.</translation> + </message> + <message> + <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source> + <translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation> + </message> + <message> + <source>%s is set very high!</source> + <translation>%s is set very high!</translation> + </message> + <message> + <source>Error loading wallet %s. Duplicate -wallet filename specified.</source> + <translation>Error loading wallet %s. Duplicate -wallet filename specified.</translation> + </message> + <message> + <source>Starting network threads...</source> + <translation>Starting network threads...</translation> + </message> + <message> + <source>The wallet will avoid paying less than the minimum relay fee.</source> + <translation>The wallet will avoid paying less than the minimum relay fee.</translation> + </message> + <message> + <source>This is the minimum transaction fee you pay on every transaction.</source> + <translation>This is the minimum transaction fee you pay on every transaction.</translation> + </message> + <message> + <source>This is the transaction fee you will pay if you send a transaction.</source> + <translation>This is the transaction fee you will pay if you send a transaction.</translation> + </message> + <message> + <source>Transaction amounts must not be negative</source> + <translation>Transaction amounts must not be negative</translation> + </message> + <message> + <source>Transaction has too long of a mempool chain</source> + <translation>Transaction has too long of a mempool chain</translation> + </message> + <message> + <source>Transaction must have at least one recipient</source> + <translation>Transaction must have at least one recipient</translation> + </message> + <message> + <source>Unknown network specified in -onlynet: '%s'</source> + <translation>Unknown network specified in -onlynet: '%s'</translation> + </message> + <message> + <source>Insufficient funds</source> + <translation>Insufficient funds</translation> + </message> + <message> + <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source> + <translation>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</translation> + </message> + <message> + <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source> + <translation>Warning: Private keys detected in wallet {%s} with disabled private keys</translation> + </message> + <message> + <source>Cannot write to data directory '%s'; check permissions.</source> + <translation>Cannot write to data directory '%s'; check permissions.</translation> + </message> + <message> + <source>Loading block index...</source> + <translation>Loading block index...</translation> + </message> + <message> <source>Loading wallet...</source> <translation>Sedang baca wallet...</translation> </message> <message> + <source>Cannot downgrade wallet</source> + <translation>Cannot downgrade wallet</translation> + </message> + <message> + <source>Rescanning...</source> + <translation>Rescanning...</translation> + </message> + <message> <source>Done loading</source> <translation>Baca Selesai</translation> </message> diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts index 6f672821e3..2cb42a0e39 100644 --- a/src/qt/locale/bitcoin_nl.ts +++ b/src/qt/locale/bitcoin_nl.ts @@ -15,7 +15,7 @@ </message> <message> <source>Copy the currently selected address to the system clipboard</source> - <translation>Kopieer het geselecteerde adres naar het klembord</translation> + <translation>Kopieer het momenteel geselecteerde adres naar het systeem klembord</translation> </message> <message> <source>&Copy</source> @@ -47,7 +47,7 @@ </message> <message> <source>Choose the address to send coins to</source> - <translation>Kies het adres om munten naar te versturen</translation> + <translation>Kies het adres om de munten naar te versturen</translation> </message> <message> <source>Choose the address to receive coins with</source> @@ -70,6 +70,12 @@ <translation>Dit zijn uw Bitcoinadressen om betalingen mee te verzenden. Controleer altijd het bedrag en het ontvangstadres voordat u uw bitcoins verzendt.</translation> </message> <message> + <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses. +Signing is only possible with addresses of the type 'legacy'.</source> + <translation>Dit zijn uw Bitcoin adressen voor het ontvangen van betalingen. Gebruik de 'Nieuw ontvangst adres maken' knop in de ontvangst tab om een nieuwe adres te maken. +Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation> + </message> + <message> <source>&Copy Address</source> <translation>&Kopiëer adres</translation> </message> @@ -478,6 +484,22 @@ <translation>Bijgewerkt</translation> </message> <message> + <source>&Load PSBT from file...</source> + <translation>&Laad PSBT van bestand...</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction</source> + <translation>Laad gedeeltelijk ondertekende Bitcoin-transactie</translation> + </message> + <message> + <source>Load PSBT from clipboard...</source> + <translation>Laad PSBT van klembord</translation> + </message> + <message> + <source>Load Partially Signed Bitcoin Transaction from clipboard</source> + <translation>Laad gedeeltelijk ondertekende Bitcoin-transactie vanaf het klembord</translation> + </message> + <message> <source>Node window</source> <translation>Nodevenster</translation> </message> @@ -514,10 +536,26 @@ <translation>Portemonnee Sluiten</translation> </message> <message> + <source>Close All Wallets...</source> + <translation>Sluit Alle Portemonnees...</translation> + </message> + <message> + <source>Close all wallets</source> + <translation>Sluit alle portemonnees</translation> + </message> + <message> <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source> <translation>Toon het %1 hulpbericht om een lijst te krijgen met mogelijke Bitcoin commandoregelopties</translation> </message> <message> + <source>&Mask values</source> + <translation>&Maskeer waarden</translation> + </message> + <message> + <source>Mask the values in the Overview tab</source> + <translation>Maskeer de waarden op het tabblad Overzicht</translation> + </message> + <message> <source>default wallet</source> <translation>standaard portemonnee</translation> </message> @@ -625,7 +663,15 @@ <source>Wallet is <b>encrypted</b> and currently <b>locked</b></source> <translation>Portemonnee is <b>versleuteld</b> en momenteel <b>gesloten</b></translation> </message> - </context> + <message> + <source>Original message:</source> + <translation>Origineel bericht:</translation> + </message> + <message> + <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source> + <translation>Er is een fatale fout opgetreden. %1 kan niet langer veilig doorgaan en wordt afgesloten.</translation> + </message> +</context> <context> <name>CoinControlDialog</name> <message> @@ -828,6 +874,14 @@ Dit is ideaal voor alleen-lezen portommonees.</translation> <translation>Maak een lege portemonnee</translation> </message> <message> + <source>Use descriptors for scriptPubKey management</source> + <translation>Gebruik descriptors voor scriptPubKey-beheer</translation> + </message> + <message> + <source>Descriptor Wallet</source> + <translation>Descriptor Portemonnee</translation> + </message> + <message> <source>Create</source> <translation>Creëer</translation> </message> @@ -1304,6 +1358,14 @@ Dit is ideaal voor alleen-lezen portommonees.</translation> <translation>Munt controle functies weergeven of niet.</translation> </message> <message> + <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source> + <translation>Maak verbinding met het Bitcoin-netwerk via een aparte SOCKS5-proxy voor Tor Onion-services.</translation> + </message> + <message> + <source>Use separate SOCKS&5 proxy to reach peers via Tor onion services:</source> + <translation>Gebruik afzonderlijke SOCKS & 5-proxy om peers te bereiken via Tor Onion-services:</translation> + </message> + <message> <source>&Third party transaction URLs</source> <translation>Transactie-URL's van &derden</translation> </message> @@ -1438,7 +1500,11 @@ Dit is ideaal voor alleen-lezen portommonees.</translation> <source>Current total balance in watch-only addresses</source> <translation>Huidige balans in alleen-bekijkbare adressen.</translation> </message> - </context> + <message> + <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</source> + <translation>Privacymodus geactiveerd voor het tabblad Overzicht. Om de waarden te ontmaskeren, schakelt u Instellingen -> Maskeer waarden uit.</translation> + </message> +</context> <context> <name>PSBTOperationsDialog</name> <message> @@ -1446,6 +1512,38 @@ Dit is ideaal voor alleen-lezen portommonees.</translation> <translation>Dialoog</translation> </message> <message> + <source>Sign Tx</source> + <translation>Signeer Tx</translation> + </message> + <message> + <source>Broadcast Tx</source> + <translation>Zend Tx uit</translation> + </message> + <message> + <source>Copy to Clipboard</source> + <translation>Kopieer naar klembord</translation> + </message> + <message> + <source>Save...</source> + <translation>Opslaan...</translation> + </message> + <message> + <source>Close</source> + <translation>Sluiten</translation> + </message> + <message> + <source>Failed to load transaction: %1</source> + <translation>Laden transactie niet gelukt: %1</translation> + </message> + <message> + <source>Failed to sign transaction: %1</source> + <translation>Tekenen transactie niet gelukt: %1</translation> + </message> + <message> + <source>Could not sign any more inputs.</source> + <translation>Kon geen inputs meer ondertekenen.</translation> + </message> + <message> <source>Total Amount</source> <translation>Totaalbedrag</translation> </message> @@ -3170,6 +3268,10 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10 <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source> <translation>De portemonee te lang gesloten houden kan leiden tot het moeten hersynchroniseren van de hele keten als snoeien aktief is.</translation> </message> + <message> + <source>Close all wallets</source> + <translation>Sluit alle portemonnees</translation> + </message> </context> <context> <name>WalletFrame</name> diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index dbb325decd..1d8d1f89ff 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -3,7 +3,7 @@ <name>AddressBookPage</name> <message> <source>Right-click to edit address or label</source> - <translation>Right-click to edit address or label</translation> + <translation>Kliknij prawym przyciskiem myszy, aby edytować adres lub etykietę</translation> </message> <message> <source>Create a new address</source> @@ -67,13 +67,13 @@ </message> <message> <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source> - <translation>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</translation> + <translation>To są twoje adresy Bitcoin do wysyłania płatności. Zawsze sprawdź kwotę i adres odbiorcy przed wysłaniem monet.</translation> </message> <message> <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses. Signing is only possible with addresses of the type 'legacy'.</source> - <translation>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses. -Signing is only possible with addresses of the type 'legacy'.</translation> + <translation>To są twoje adresy Bitcoin do otrzymywania płatności. Użyj przycisku „Utwórz nowy adres odbiorcy” na karcie odbioru, aby utworzyć nowe adresy. +Podpisywanie jest możliwe tylko z adresami typu „legacy”.</translation> </message> <message> <source>&Copy Address</source> @@ -89,7 +89,7 @@ Signing is only possible with addresses of the type 'legacy'.</translation> </message> <message> <source>Export Address List</source> - <translation>Export Address List</translation> + <translation>Eksportuj listę adresów</translation> </message> <message> <source>Comma separated file (*.csv)</source> @@ -151,7 +151,7 @@ Signing is only possible with addresses of the type 'legacy'.</translation> </message> <message> <source>Unlock wallet</source> - <translation>Unlock wallet</translation> + <translation>Odblokuj portfel</translation> </message> <message> <source>This operation needs your wallet passphrase to decrypt the wallet.</source> @@ -325,7 +325,7 @@ Signing is only possible with addresses of the type 'legacy'.</translation> </message> <message> <source>Open &URI...</source> - <translation>Otwórz URI...</translation> + <translation>Otwórz &URI...</translation> </message> <message> <source>Create Wallet...</source> @@ -488,10 +488,18 @@ Signing is only possible with addresses of the type 'legacy'.</translation> <translation>Wczytaj PSBT z p&liku ..</translation> </message> <message> + <source>Load Partially Signed Bitcoin Transaction</source> + <translation>Załaduj częściowo podpisaną transakcję Bitcoin</translation> + </message> + <message> <source>Load PSBT from clipboard...</source> <translation>Wczytaj PSBT do schowka</translation> </message> <message> + <source>Load Partially Signed Bitcoin Transaction from clipboard</source> + <translation>Załaduj częściowo podpisaną transakcję Bitcoin ze schowka</translation> + </message> + <message> <source>Node window</source> <translation>Okno węzła</translation> </message> @@ -853,6 +861,10 @@ Signing is only possible with addresses of the type 'legacy'.</translation> <translation>Stwórz czysty portfel</translation> </message> <message> + <source>Descriptor Wallet</source> + <translation>Portfel deskryptora</translation> + </message> + <message> <source>Create</source> <translation>Stwórz</translation> </message> @@ -3275,7 +3287,7 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw </message> <message> <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source> - <translation>Zamknięcie portfela na zbyt długo może skutkować konieczność ponownego załadowania całego łańcucha, jeżeli jest włączony pruning.</translation> + <translation>Zamknięcie portfela na zbyt długo może skutkować koniecznością ponownego załadowania całego łańcucha, jeżeli jest włączony pruning.</translation> </message> <message> <source>Close all wallets</source> @@ -3558,6 +3570,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw <translation>Nie udało się ponownie przeskanować portfela podczas inicjalizacji.</translation> </message> <message> + <source>Failed to verify database</source> + <translation>Nie udało się zweryfikować bazy danych</translation> + </message> + <message> <source>Importing...</source> <translation>Importowanie…</translation> </message> @@ -3586,6 +3602,30 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw <translation>Nieprawidłowa kwota dla -fallbackfee=<amount>: '%s'</translation> </message> <message> + <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source> + <translation>SQLiteDatabase: nie powiodło się wykonanie instrukcji weryfikującej bazę danych: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase: nie udało się pobrać wersji schematu portfela sqlite: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch the application id: %s</source> + <translation>SQLiteDatabase: nie udało się pobrać identyfikatora aplikacji: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source> + <translation>SQLiteDatabase: nie udało się przygotować instrukcji do weryfikacji bazy danych: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>SQLiteDatabase: nie udało się odczytać błędu weryfikacji bazy danych: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>SQLiteDatabase: nieoczekiwany identyfikator aplikacji. Oczekiwano %u, otrzymano %u</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation>Podany folder bloków "%s" nie istnieje. </translation> diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts index ca98c94a35..71b4bd2640 100644 --- a/src/qt/locale/bitcoin_pt_BR.ts +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -3570,6 +3570,10 @@ Go to File > Open Wallet to load a wallet. <translation>Erro ao ler arquivo %s! Todas as chaves privadas foram lidas corretamente, mas os dados de transação ou o livro de endereços podem estar faltando ou incorretos.</translation> </message> <message> + <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source> + <translation>Mais de um endereço onion associado é fornecido. Usando %s para automaticamento criar serviço onion Tor.</translation> + </message> + <message> <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> <translation>Por favor verifique se a data e o horário de seu computador estão corretos. Se o relógio de seu computador estiver incorreto, %s não funcionará corretamente.</translation> </message> @@ -3578,6 +3582,18 @@ Go to File > Open Wallet to load a wallet. <translation>Por favor contribua se você entender que %s é útil. Visite %s para mais informações sobre o software.</translation> </message> <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase: Falha ao preparar a confirmação para buscar a versão do programa da carteira sqlite: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source> + <translation>SQLiteDatabase: Falhou em preparar confirmação para buscar a id da aplicação: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source> + <translation>SQLiteDatabase: Desconhecida a versão %d do programa da carteira sqlite. Apenas a versão %d é suportada</translation> + </message> + <message> <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> <translation>O banco de dados de blocos contém um bloco que parece ser do futuro. Isso pode ser devido à data e hora do seu computador estarem configuradas incorretamente. Apenas reconstrua o banco de dados de blocos se você estiver certo de que a data e hora de seu computador estão corretas.</translation> </message> @@ -3682,6 +3698,10 @@ Go to File > Open Wallet to load a wallet. <translation>Falha ao escanear novamente a carteira durante a inicialização</translation> </message> <message> + <source>Failed to verify database</source> + <translation>Falha ao verificar a base de dados</translation> + </message> + <message> <source>Importing...</source> <translation>Importando...</translation> </message> @@ -3710,6 +3730,30 @@ Go to File > Open Wallet to load a wallet. <translation>Quantidade inválida para -fallbackfee=<amount>: '%s'</translation> </message> <message> + <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source> + <translation>SQLiteDatabase: Falhou em executar a confirmação para verificar a base de dados: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase: Falha ao burscar a versão do programa da carteira sqlite: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch the application id: %s</source> + <translation>SQLiteDatabase: Falha ao procurar a id da aplicação: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source> + <translation>SQLiteDatabase: Falhou em preparar confirmação para verificar a base de dados: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>SQLiteDatabase: Falha ao ler o erro de verificação da base de dados: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>SQLiteDatabase: Id da aplicação inesperada. Esperada %u, got %u</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation> Diretório de blocos especificados "%s" não existe.</translation> diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index db4e095ccf..ba327643d6 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -667,7 +667,12 @@ Signing is only possible with addresses of the type 'legacy'.</source> <source>Original message:</source> <translation>Исходное сообщение:</translation> </message> - </context> + <message> + <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source> + <translation>Произошла критическая ошибка. %1 больше не может продолжать безопасную работу и будет закрыт. + </translation> + </message> +</context> <context> <name>CoinControlDialog</name> <message> @@ -869,6 +874,10 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Создать пустой кошелёк</translation> </message> <message> + <source>Use descriptors for scriptPubKey management</source> + <translation>Использовать дескриптор для управления scriptPubKey</translation> + </message> + <message> <source>Descriptor Wallet</source> <translation>Дескриптор кошелька</translation> </message> @@ -1349,6 +1358,14 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Показывать ли опцию управления монетами.</translation> </message> <message> + <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source> + <translation>Подключаться к Биткойн-сети через отдельный прокси SOCKS5 для скрытых сервисов Tor.</translation> + </message> + <message> + <source>Use separate SOCKS&5 proxy to reach peers via Tor onion services:</source> + <translation>Использовать отдельный прокси SOCKS&5 для соединения с узлами через скрытые сервисы Tor:</translation> + </message> + <message> <source>&Third party transaction URLs</source> <translation>&Ссылки на транзакции сторонних сервисов</translation> </message> @@ -1483,7 +1500,11 @@ Signing is only possible with addresses of the type 'legacy'.</source> <source>Current total balance in watch-only addresses</source> <translation>Текущий общий баланс на адресах наблюдения</translation> </message> - </context> + <message> + <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</source> + <translation>Режим приватности включен для вкладки обзора. Чтобы показать данные, отключите настройку Скрыть Значения.</translation> + </message> +</context> <context> <name>PSBTOperationsDialog</name> <message> @@ -1495,6 +1516,10 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Подписать транзакцию</translation> </message> <message> + <source>Broadcast Tx</source> + <translation>Отправить Tx</translation> + </message> + <message> <source>Copy to Clipboard</source> <translation>Скопировать в буфер обмена</translation> </message> @@ -1507,14 +1532,66 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Закрыть</translation> </message> <message> + <source>Failed to load transaction: %1</source> + <translation>Не удалось загрузить транзакцию: %1</translation> + </message> + <message> + <source>Failed to sign transaction: %1</source> + <translation>Не удалось подписать транзакцию: %1</translation> + </message> + <message> + <source>Could not sign any more inputs.</source> + <translation>Не удалось подписать оставшиеся входы.</translation> + </message> + <message> + <source>Signed %1 inputs, but more signatures are still required.</source> + <translation>Подписано %1 входов, но требуется больше подписей.</translation> + </message> + <message> + <source>Signed transaction successfully. Transaction is ready to broadcast.</source> + <translation>Транзакция успешно подписана. Транзакция готова к отправке.</translation> + </message> + <message> + <source>Unknown error processing transaction.</source> + <translation>Неизвестная ошибка во время обработки транзакции.</translation> + </message> + <message> + <source>Transaction broadcast successfully! Transaction ID: %1</source> + <translation>Транзакция успешно отправлена! ID транзакции: %1</translation> + </message> + <message> + <source>Transaction broadcast failed: %1</source> + <translation>Отправка транзакции не удалась: %1</translation> + </message> + <message> <source>PSBT copied to clipboard.</source> <translation>PSBT скопирован в буфер обмена</translation> </message> <message> + <source>Save Transaction Data</source> + <translation>Сохранить данные о транзакции</translation> + </message> + <message> <source>Partially Signed Transaction (Binary) (*.psbt)</source> <translation>Частично Подписанная Транзакция (Бинарный файл) (*.psbt)</translation> </message> <message> + <source>PSBT saved to disk.</source> + <translation>PSBT сохранён на диск.</translation> + </message> + <message> + <source> * Sends %1 to %2</source> + <translation>* Отправляет %1 к %2</translation> + </message> + <message> + <source>Unable to calculate transaction fee or total transaction amount.</source> + <translation>Не удалось сосчитать сумму комиссии или общую сумму транзакции.</translation> + </message> + <message> + <source>Pays transaction fee: </source> + <translation>Платит комиссию:</translation> + </message> + <message> <source>Total Amount</source> <translation>Общая сумма</translation> </message> @@ -1522,7 +1599,35 @@ Signing is only possible with addresses of the type 'legacy'.</source> <source>or</source> <translation>или</translation> </message> - </context> + <message> + <source>Transaction has %1 unsigned inputs.</source> + <translation>Транзакция имеет %1 неподписанных входов.</translation> + </message> + <message> + <source>Transaction is missing some information about inputs.</source> + <translation>Транзакция имеет недостаточно информации о некоторых входах.</translation> + </message> + <message> + <source>Transaction still needs signature(s).</source> + <translation>Транзакция требует по крайней мере одну подпись.</translation> + </message> + <message> + <source>(But this wallet cannot sign transactions.)</source> + <translation>(Но этот кошелёк не может подписывать транзакции.)</translation> + </message> + <message> + <source>(But this wallet does not have the right keys.)</source> + <translation>(Но этот кошелёк не имеет необходимые ключи.)</translation> + </message> + <message> + <source>Transaction is fully signed and ready for broadcast.</source> + <translation>Транзакция полностью подписана, и готова к отправке.</translation> + </message> + <message> + <source>Transaction status is unknown.</source> + <translation>Статус транзакции неизвестен.</translation> + </message> +</context> <context> <name>PaymentServer</name> <message> @@ -1688,6 +1793,10 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Ошибка: %1</translation> </message> <message> + <source>Error initializing settings: %1</source> + <translation>Ошибка инициализации настроек: %1</translation> + </message> + <message> <source>%1 didn't yet exit safely...</source> <translation>%1 ещё не завершился безопасно...</translation> </message> @@ -1882,6 +1991,10 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Увеличить размер шрифта</translation> </message> <message> + <source>Permissions</source> + <translation>Права</translation> + </message> + <message> <source>Services</source> <translation>Сервисы</translation> </message> @@ -2136,10 +2249,22 @@ Signing is only possible with addresses of the type 'legacy'.</source> <source>Could not unlock wallet.</source> <translation>Невозможно разблокировать кошелёк.</translation> </message> - </context> + <message> + <source>Could not generate new %1 address</source> + <translation>Не удалось сгенерировать новый %1 адрес</translation> + </message> +</context> <context> <name>ReceiveRequestDialog</name> <message> + <source>Request payment to ...</source> + <translation>Запросить платёж на ...</translation> + </message> + <message> + <source>Address:</source> + <translation>Адрес:</translation> + </message> + <message> <source>Amount:</source> <translation>Количество:</translation> </message> @@ -2422,10 +2547,22 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Вы действительно хотите выполнить отправку?</translation> </message> <message> + <source>Create Unsigned</source> + <translation>Создать Без Подписи</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>Сохранить данные о транзакции</translation> + </message> + <message> <source>Partially Signed Transaction (Binary) (*.psbt)</source> <translation>Частично Подписанная Транзакция (Бинарный файл) (*.psbt)</translation> </message> <message> + <source>PSBT saved</source> + <translation>PSBT сохранён</translation> + </message> + <message> <source>or</source> <translation>или</translation> </message> @@ -2434,6 +2571,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Вы можете увеличить комиссию позже (Replace-By-Fee, BIP-125).</translation> </message> <message> + <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can save or copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source> + <translation>Пожалуйста, пересмотрите ваше транзакционное предложение. Это создаст Частично Подписанную Биткойн Транзакцию (PSBT), которую можно сохранить или копировать и использовать для подписи, например, с оффлайн %1 кошельком, или PSBT-совместимым аппаратным кошельком.</translation> + </message> + <message> <source>Please, review your transaction.</source> <translation>Пожалуйста, ознакомьтесь с вашей транзакцией.</translation> </message> @@ -3251,10 +3392,22 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <source>Close all wallets</source> <translation>Закрыть все кошельки</translation> </message> - </context> + <message> + <source>Are you sure you wish to close all wallets?</source> + <translation>Вы уверенны, что хотите закрыть все кошельки?</translation> + </message> +</context> <context> <name>WalletFrame</name> <message> + <source>No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR -</source> + <translation>Кошелёк не был загружен. +Откройте вкладку Файл > Открыть Кошелёк чтобы загрузить кошелёк. +- ИЛИ -</translation> + </message> + <message> <source>Create a new wallet</source> <translation>Создать новый кошелёк</translation> </message> @@ -3333,6 +3486,26 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Ошибка</translation> </message> <message> + <source>Unable to decode PSBT from clipboard (invalid base64)</source> + <translation>Не удалось декодировать PSBT из буфера обмена (неверный base64)</translation> + </message> + <message> + <source>Load Transaction Data</source> + <translation>Загрузить данные о транзакции</translation> + </message> + <message> + <source>Partially Signed Transaction (*.psbt)</source> + <translation>Частично Подписанная Транзакция (*.psbt)</translation> + </message> + <message> + <source>PSBT file must be smaller than 100 MiB</source> + <translation>Файл PSBT должен быть меньше 100 мегабит.</translation> + </message> + <message> + <source>Unable to decode PSBT</source> + <translation>Не удалось декодировать PSBT</translation> + </message> + <message> <source>Backup Wallet</source> <translation>Создать резервную копию кошелька</translation> </message> @@ -3400,6 +3573,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Ошибка чтения %s! Все ключи прочитаны верно, но данные транзакций или записи адресной книги могут отсутствовать или быть неправильными.</translation> </message> <message> + <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source> + <translation>Предоставлен более чем один адрес подключения к скрытым сервисам. %s используется для подключения к автоматически созданному сервису Tor.</translation> + </message> + <message> <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> <translation>Пожалуйста, убедитесь в корректности установки времени и даты на вашем компьютере! Если время установлено неверно, %s не будет работать правильно.</translation> </message> @@ -3408,6 +3585,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Пожалуйста, внесите свой вклад, если вы найдете %s полезными. Посетите %s для получения дополнительной информации о программном обеспечении.</translation> </message> <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase: Не удалось приготовить утверждение чтобы загрузить sqlite кошелёк версии: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source> + <translation>SQLiteDatabase: Не удалось приготовить утверждение чтобы загрузить id приложения: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source> + <translation>SQLiteDatabase: Кошелёк sqlite имеет неизвестную версию %d. Поддерживается только версия %d</translation> + </message> + <message> <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> <translation>База данных блоков содержит блок, который появляется из будущего. Это может произойти из-за некорректно установленных даты и времени на вашем компьютере. Остается только перестраивать базу блоков, если вы уверены, что дата и время корректны.</translation> </message> @@ -3512,6 +3701,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Не удалось повторно сканировать кошелёк во время инициализации</translation> </message> <message> + <source>Failed to verify database</source> + <translation>Не удалось проверить базу данных</translation> + </message> + <message> <source>Importing...</source> <translation>Выполняется импорт...</translation> </message> @@ -3540,6 +3733,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Недопустимая сумма для -fallbackfee=<amount>: '%s'</translation> </message> <message> + <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source> + <translation>SQLiteDatabase: Не удалось произвести проверку базы данных: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase: Не удалось загрузить sqlite кошелёк версии: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch the application id: %s</source> + <translation>SQLiteDatabase: Не удалось загрузить id приложения: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source> + <translation>SQLiteDatabase: Не удалось приготовить утверждение для проверки базы данных: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>SQLiteDatabase: Ошибка при проверке базы данных: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>SQLiteDatabase: Неожиданный id приложения. Ожидалось %u, а получено %u</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation>Указанная директория с блоками "%s" не существует.</translation> </message> @@ -3624,6 +3841,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Ошибка: Не удалось начать прослушивание входящих подключений (прослушивание вернуло ошибку %s)</translation> </message> <message> + <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source> + <translation>%s испорчен. Попробуйте восстановить с помощью инструмента bitcoin-wallet, или используйте резервную копию.</translation> + </message> + <message> + <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source> + <translation>Невозможно обновить не разделенный HD кошелёк без обновления для поддержки предварительно разделенного пула ключей. Пожалуйста, используйте версию 169900 или повторите без указания версии.</translation> + </message> + <message> <source>Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source> <translation>Неверное значение для -maxtxfee=<amount>: '%s' (минимальная комиссия трансляции %s для предотвращения зависания транзакций)</translation> </message> @@ -3632,10 +3857,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Сумма транзакции за вычетом комиссии слишком мала</translation> </message> <message> + <source>This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet</source> + <translation>Данная ошибка может произойти в том случае, если этот кошелёк не был правильно закрыт и в последний раз был загружен используя версию с более новой версией Berkley DB. Если это так, воспользуйтесь той программой, в которой этот кошелёк открывался в последний раз.</translation> + </message> + <message> + <source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source> + <translation>Это максимальная транзакция, которую вы заплатите (в добавок к обычной плате) для избежания затрат по причине отбора монет.</translation> + </message> + <message> + <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source> + <translation>Для транзакции требуется адрес сдачи, но сгенерировать его не удалось. Пожалуйста, сначала выполните keypoolrefill.</translation> + </message> + <message> <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source> <translation>Вам необходимо пересобрать базу данных с помощью -reindex, чтобы вернуться к полному режиму. Это приведёт к перезагрузке всей цепи блоков</translation> </message> <message> + <source>A fatal internal error occurred, see debug.log for details</source> + <translation>Ошибка: произошла критическая внутренняя ошибка, для получения деталей см. debug.log</translation> + </message> + <message> + <source>Cannot set -peerblockfilters without -blockfilterindex.</source> + <translation>Не удалось поставить -peerblockfilters без использования -blockfilterindex.</translation> + </message> + <message> + <source>Disk space is too low!</source> + <translation>Мало места на диске!</translation> + </message> + <message> <source>Error reading from database, shutting down.</source> <translation>Ошибка чтения с базы данных, выполняется закрытие.</translation> </message> @@ -3648,6 +3897,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Ошибка: На диске недостаточно места для %s</translation> </message> <message> + <source>Error: Keypool ran out, please call keypoolrefill first</source> + <translation>Пул ключей опустел, пожалуйста сначала выполните keypoolrefill</translation> + </message> + <message> + <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source> + <translation>Количество комисии (%s) меньше чем настроенное минимальное количество комисии (%s).</translation> + </message> + <message> <source>Invalid -onion address or hostname: '%s'</source> <translation>Неверный -onion адрес или имя хоста: '%s'</translation> </message> @@ -3668,6 +3925,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Необходимо указать порт с -whitebind: '%s'</translation> </message> <message> + <source>No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>.</source> + <translation>Не указан прокси сервер. Используйте -proxy=<ip> или -proxy=<ip:port></translation> + </message> + <message> <source>Prune mode is incompatible with -blockfilterindex.</source> <translation>Режим удаления блоков несовместим с -blockfilterindex.</translation> </message> diff --git a/src/qt/locale/bitcoin_sl.ts b/src/qt/locale/bitcoin_sl.ts index f2cd56aab5..1c84983532 100644 --- a/src/qt/locale/bitcoin_sl.ts +++ b/src/qt/locale/bitcoin_sl.ts @@ -3580,6 +3580,18 @@ Za odpiranje denarnice kliknite Datoteka > Odpri denarnico <translation>Prosimo, prispevajte, če se vam zdi %s uporaben. Za dodatne informacije o programski opremi obiščite %s.</translation> </message> <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source> + <translation>Baza SQLite: priprava stavka za poizvedbo verzije sheme SQLite denarnice je spodletela: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source> + <translation>Baza SQLite: priprava stavka za poizvedbo identifikatorja aplikacije je spodletela: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source> + <translation>Baza SQLite: Neznana verzija sheme SQLite denarnice %d. Podprta je le verzija %d.</translation> + </message> + <message> <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> <translation>Baza podatkov blokov vsebuje blok, za katerega se zdi, da je iz prihodnosti. To je lahko posledica napačnega nastavitve datuma in časa vašega računalnika. Znova zgradite bazo podatkov samo, če ste prepričani, da sta datum in čas računalnika pravilna.</translation> </message> @@ -3684,6 +3696,10 @@ Za odpiranje denarnice kliknite Datoteka > Odpri denarnico <translation>Med inicializacijo denarnice ni bilo mogoče preveriti zgodovine (rescan failed).</translation> </message> <message> + <source>Failed to verify database</source> + <translation>Preverba podatkovne baze je spodletela.</translation> + </message> + <message> <source>Importing...</source> <translation>Uvažam ...</translation> </message> @@ -3712,6 +3728,30 @@ Za odpiranje denarnice kliknite Datoteka > Odpri denarnico <translation>Neveljavna količina za -fallbackfee=<amount>: '%s'</translation> </message> <message> + <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source> + <translation>Baza SQLite: Izvršitev stavka za preverbo baze je spodletela: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source> + <translation>Baza SQLite: pridobitev verzije sheme SQLite denarnice je spodletela: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch the application id: %s</source> + <translation>Baza SQLite: pridobitev identifikatorja aplikacije je spodletela: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source> + <translation>Baza SQLite: priprava stavka za preverbo baze je spodletela: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>Baza SQLite: branje napake pri preverjanje baze je spodletelo: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>Baza SQLite: nepričakovan identifikator aplikacije. Pričakovana vrednost je %u, dobljena vrednost je %u.</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation>Vnešena podatkovna mapa za bloke "%s" ne obstaja.</translation> </message> diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts index feece83f0c..4fae82128d 100644 --- a/src/qt/locale/bitcoin_sq.ts +++ b/src/qt/locale/bitcoin_sq.ts @@ -26,10 +26,18 @@ <translation>Fshi adresen e selektuar nga lista</translation> </message> <message> + <source>Enter address or label to search</source> + <translation>Vendos adresën ose etiketën për të kërkuar</translation> + </message> + <message> <source>Export the data in the current tab to a file</source> <translation>Eksporto të dhënat e skedës korrente në një skedar</translation> </message> <message> + <source>&Export</source> + <translation>&Eksporto</translation> + </message> + <message> <source>&Delete</source> <translation>&Fshi</translation> </message> @@ -164,6 +172,18 @@ <translation>Jepe fjalëkalimin e vjetër dhe fjalkalimin e ri për portofolin.</translation> </message> <message> + <source>Wallet to be encrypted</source> + <translation>Portofoli që duhet të enkriptohet</translation> + </message> + <message> + <source>Your wallet is about to be encrypted. </source> + <translation>Portofoli juaj do të enkriptohet</translation> + </message> + <message> + <source>Your wallet is now encrypted. </source> + <translation>Portofoli juaj është i enkriptuar.</translation> + </message> + <message> <source>Wallet encryption failed</source> <translation>Enkriptimi i portofolit dështoi</translation> </message> @@ -218,6 +238,10 @@ <translation>Mbyllni aplikacionin</translation> </message> <message> + <source>Show information about Qt</source> + <translation>Shfaq informacion rreth Qt</translation> + </message> + <message> <source>&Options...</source> <translation>&Opsione</translation> </message> @@ -763,6 +787,10 @@ <context> <name>WalletView</name> <message> + <source>&Export</source> + <translation>&Eksporto</translation> + </message> + <message> <source>Export the data in the current tab to a file</source> <translation>Eksporto të dhënat e skedës korrente në një skedar</translation> </message> diff --git a/src/qt/locale/bitcoin_ta.ts b/src/qt/locale/bitcoin_ta.ts index 9bbd853c9d..d35834ef64 100644 --- a/src/qt/locale/bitcoin_ta.ts +++ b/src/qt/locale/bitcoin_ta.ts @@ -478,6 +478,14 @@ <translation>தேதி வரை</translation> </message> <message> + <source>Node window</source> + <translation>நோட் விண்டோ</translation> + </message> + <message> + <source>Open node debugging and diagnostic console</source> + <translation>திற நோட் பிழைத்திருத்தம் மற்றும் கண்டறியும் பணியகம்</translation> + </message> + <message> <source>&Sending addresses</source> <translation>முகவரிகள் அனுப்புகிறது</translation> </message> @@ -486,6 +494,10 @@ <translation>முகவரிகள் பெறுதல்</translation> </message> <message> + <source>Open a bitcoin: URI</source> + <translation>திற பிட்காயின்: URI</translation> + </message> + <message> <source>Open Wallet</source> <translation>வாலட்டை திற</translation> </message> @@ -1440,6 +1452,10 @@ <translation>'bitcoin: //' சரியான URI அல்ல. அதற்கு பதிலாக 'பிட்கின்:' பயன்படுத்தவும்.</translation> </message> <message> + <source>Cannot process payment request because BIP70 is not supported.</source> + <translation>பரிவர்த்தனை வேண்டுதலை ஏற்க இயலாது ஏனென்றால் BIP70 ஆதரவு தரவில்லை</translation> + </message> + <message> <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source> <translation>பிப்70 இல் உள்ள பரவலான பாதுகாப்பு குறைபாடுகள் காரணமாக, வாலட்டை மாற்றுவதற்கான எந்தவொரு வணிக அறிவுறுத்தல்களும் புறக்கணிக்கப்பட வேண்டும் என்று கடுமையாக பரிந்துரைக்கப்படுகிறது.</translation> </message> @@ -1724,6 +1740,10 @@ <translation>பயனர் முகவர்</translation> </message> <message> + <source>Node window</source> + <translation>நோட் விண்டோ</translation> + </message> + <message> <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source> <translation>தற்போதைய தரவு அடைவில் இருந்து %1 பிழைத்திருத்த பதிவு கோப்பைத் திறக்கவும். இது பெரிய பதிவு கோப்புகளை சில விநாடிகள் எடுக்கலாம்.</translation> </message> @@ -2280,6 +2300,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>அனுப்பும் பிட்காயின்களை உறுதிப்படுத்தவும்</translation> </message> <message> + <source>Confirm transaction proposal</source> + <translation>பரிவர்த்தனை வரைவு உறுதி செய்</translation> + </message> + <message> + <source>Send</source> + <translation>அனுப்புவும்</translation> + </message> + <message> <source>The recipient address is not valid. Please recheck.</source> <translation>பெறுநரின் முகவரி தவறானது. மீண்டும் சரிபார்க்கவும்.</translation> </message> @@ -2521,6 +2549,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>வாலட் திறத்தல் ரத்து செய்யப்பட்டது.</translation> </message> <message> + <source>No error</source> + <translation>தவறு எதுவுமில்லை</translation> + </message> + <message> <source>Private key for the entered address is not available.</source> <translation>உள்ளிட்ட முகவரிக்கான ப்ரைவேட் கீ கிடைக்கவில்லை.</translation> </message> @@ -3048,6 +3080,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>கட்டண ஏற்றத்தை உறுதிப்படுத்தவும்</translation> </message> <message> + <source>Can't draft transaction.</source> + <translation>பரிவர்த்தனை செய்ய இயலாது</translation> + </message> + <message> <source>Can't sign transaction.</source> <translation>பரிவர்த்தனையில் கையொப்பமிட முடியவில்லை.</translation> </message> diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts index ee8608e4f8..e2c28fca7c 100644 --- a/src/qt/locale/bitcoin_tr.ts +++ b/src/qt/locale/bitcoin_tr.ts @@ -50,6 +50,10 @@ <translation>Coin gönderilecek adresi seçiniz</translation> </message> <message> + <source>C&hoose</source> + <translation>S&ç</translation> + </message> + <message> <source>Sending addresses</source> <translation>Gönderici adresler</translation> </message> @@ -134,6 +138,10 @@ Cüzdan kilidini aç.</translation> <translation>Cüzdan kilidini aç</translation> </message> <message> + <source>Decrypt wallet</source> + <translation>cüzdan şifresini çöz</translation> + </message> + <message> <source>Change passphrase</source> <translation>Parola değiştir</translation> </message> @@ -176,10 +184,26 @@ Cüzdan kilidini aç.</translation> </context> <context> <name>BanTableModel</name> - </context> + <message> + <source>IP/Netmask</source> + <translation>İP/Ağ maskesi</translation> + </message> + <message> + <source>Banned Until</source> + <translation>Kadar Yasaklı</translation> + </message> +</context> <context> <name>BitcoinGUI</name> <message> + <source>Sign &message...</source> + <translation>&Mesajı imzala ...</translation> + </message> + <message> + <source>Synchronizing with network...</source> + <translation>Ağ ile senkronize ediliyor...</translation> + </message> + <message> <source>&Overview</source> <translation>Genel durum</translation> </message> @@ -204,10 +228,42 @@ Cüzdan kilidini aç.</translation> <translation>Uygulamayı kapat</translation> </message> <message> + <source>Show information about %1</source> + <translation>%1 hakkındaki bilgileri göster</translation> + </message> + <message> + <source>About &Qt</source> + <translation>&Qt hakkında</translation> + </message> + <message> + <source>Show information about Qt</source> + <translation>Qt hakkındaki bilgileri göster</translation> + </message> + <message> <source>&Options...</source> <translation>Seçenekler</translation> </message> <message> + <source>Modify configuration options for %1</source> + <translation>%1 için yapılandırma seçeneklerini değiştirin</translation> + </message> + <message> + <source>&Encrypt Wallet...</source> + <translation>Cüzdan &Şifrelemek...</translation> + </message> + <message> + <source>&Backup Wallet...</source> + <translation>Cüzdanı &Yedekle</translation> + </message> + <message> + <source>&Change Passphrase...</source> + <translation>Parola &Değiştir...</translation> + </message> + <message> + <source>Open &URI...</source> + <translation>&URI aç...</translation> + </message> + <message> <source>Create Wallet...</source> <translation>Cüzdan oluştur</translation> </message> @@ -220,6 +276,10 @@ Cüzdan kilidini aç.</translation> <translation>Cüzdan</translation> </message> <message> + <source>Click to disable network activity.</source> + <translation>Ağ etkinliğini devre dışı bırakmak için tıklayın.</translation> + </message> + <message> <source>Network activity disabled.</source> <translation>Network aktivitesi devre dışı bırakıldı</translation> </message> @@ -228,6 +288,14 @@ Cüzdan kilidini aç.</translation> <translation>Network activitesini serbest bırakmak için tıklayınız</translation> </message> <message> + <source>Syncing Headers (%1%)...</source> + <translation>Bağlantılar senkronize ediliyor (%1%)...</translation> + </message> + <message> + <source>Reindexing blocks on disk...</source> + <translation>Diskteki blokları yeniden indeksleme ...</translation> + </message> + <message> <source>&Verify message...</source> <translation>Mesajı doğrula</translation> </message> @@ -236,6 +304,10 @@ Cüzdan kilidini aç.</translation> <translation>Gönder</translation> </message> <message> + <source>&Receive</source> + <translation>&Teslim alınan</translation> + </message> + <message> <source>&Show / Hide</source> <translation>Göster / Gizle</translation> </message> @@ -256,6 +328,10 @@ Cüzdan kilidini aç.</translation> <translation>Yardım</translation> </message> <message> + <source>Tabs toolbar</source> + <translation>Araç çubuğu sekmeleri</translation> + </message> + <message> <source>&Command-line options</source> <translation>Komut-satırı seçenekleri</translation> </message> @@ -272,6 +348,10 @@ Cüzdan kilidini aç.</translation> <translation>Bilgi</translation> </message> <message> + <source>Up to date</source> + <translation>Güncel</translation> + </message> + <message> <source>Open Wallet</source> <translation>Cüzdanı aç</translation> </message> diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts index 6675185cb7..87264deea8 100644 --- a/src/qt/locale/bitcoin_uk.ts +++ b/src/qt/locale/bitcoin_uk.ts @@ -488,10 +488,18 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>&Завантажити PSBT з файлу...</translation> </message> <message> + <source>Load Partially Signed Bitcoin Transaction</source> + <translation>Завантажте Частково Підписану Транзакцію Біткойн</translation> + </message> + <message> <source>Load PSBT from clipboard...</source> <translation>Скопіювати PSBT у буфер обміну</translation> </message> <message> + <source>Load Partially Signed Bitcoin Transaction from clipboard</source> + <translation>Завантажте Частково Підписану Біткойн Транзакцію з буфера обміну</translation> + </message> + <message> <source>Node window</source> <translation>Вікно вузлів</translation> </message> @@ -540,6 +548,14 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Показати довідку %1 для отримання переліку можливих параметрів командного рядка.</translation> </message> <message> + <source>&Mask values</source> + <translation>&Значення маски</translation> + </message> + <message> + <source>Mask the values in the Overview tab</source> + <translation>Маскуйте значення на вкладці Огляд</translation> + </message> + <message> <source>default wallet</source> <translation>типовий гаманець</translation> </message> @@ -651,7 +667,11 @@ Signing is only possible with addresses of the type 'legacy'.</source> <source>Original message:</source> <translation>Первинне повідомлення:</translation> </message> - </context> + <message> + <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source> + <translation>Сталася фатальна помилка. %1 більше не може продовжувати безпечно і вийде.</translation> + </message> +</context> <context> <name>CoinControlDialog</name> <message> @@ -853,6 +873,14 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Створити пустий гаманець</translation> </message> <message> + <source>Use descriptors for scriptPubKey management</source> + <translation>Використовуйте дескриптори для управління scriptPubKey</translation> + </message> + <message> + <source>Descriptor Wallet</source> + <translation>Дешифрування гаманця</translation> + </message> + <message> <source>Create</source> <translation>Створити</translation> </message> @@ -1325,6 +1353,14 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Показати або сховати керування входами.</translation> </message> <message> + <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source> + <translation>Підключіться до мережі Біткойн через окремий проксі-сервер SOCKS5 для сервісів Tor.</translation> + </message> + <message> + <source>Use separate SOCKS&5 proxy to reach peers via Tor onion services:</source> + <translation>Використовуйте окремий проксі-сервер SOCKS&5, щоб дістатися до вузлів через послуги Tor:</translation> + </message> + <message> <source>&Third party transaction URLs</source> <translation>&URL-адреси транзакцій сторонніх розробників</translation> </message> @@ -1459,7 +1495,11 @@ Signing is only possible with addresses of the type 'legacy'.</source> <source>Current total balance in watch-only addresses</source> <translation>Поточний сукупний баланс в адресах для спостереження</translation> </message> - </context> + <message> + <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</source> + <translation>Режим конфіденційності активований для вкладки Огляд. Щоб демаскувати значення, зніміть прапорець Параметри-> Маскувати значення.</translation> + </message> +</context> <context> <name>PSBTOperationsDialog</name> <message> @@ -1467,6 +1507,14 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Діалог</translation> </message> <message> + <source>Sign Tx</source> + <translation>Знак Tx</translation> + </message> + <message> + <source>Broadcast Tx</source> + <translation>Трансляція Tx</translation> + </message> + <message> <source>Copy to Clipboard</source> <translation>Копіювати у буфер обміну</translation> </message> @@ -1479,6 +1527,66 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Завершити</translation> </message> <message> + <source>Failed to load transaction: %1</source> + <translation>Не вдалося завантажити транзакцію: %1</translation> + </message> + <message> + <source>Failed to sign transaction: %1</source> + <translation>Не вдалося підписати транзакцію: %1</translation> + </message> + <message> + <source>Could not sign any more inputs.</source> + <translation>Не вдалося підписати більше входів.</translation> + </message> + <message> + <source>Signed %1 inputs, but more signatures are still required.</source> + <translation>Підписано %1 введення, але все одно потрібно більше підписів.</translation> + </message> + <message> + <source>Signed transaction successfully. Transaction is ready to broadcast.</source> + <translation>Угода успішно підписана. Транзакція готова до трансляції.</translation> + </message> + <message> + <source>Unknown error processing transaction.</source> + <translation>Невідома помилка обробки транзакції.</translation> + </message> + <message> + <source>Transaction broadcast successfully! Transaction ID: %1</source> + <translation>Трансакція успішно транслюється! Ідентифікатор транзакції: %1</translation> + </message> + <message> + <source>Transaction broadcast failed: %1</source> + <translation>Помилка трансляції транзакції: %1</translation> + </message> + <message> + <source>PSBT copied to clipboard.</source> + <translation>PSBT скопійовано в буфер обміну.</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>Зберегти дані транзакції</translation> + </message> + <message> + <source>Partially Signed Transaction (Binary) (*.psbt)</source> + <translation>Частково підписана транзакція (Binary) (* .psbt)</translation> + </message> + <message> + <source>PSBT saved to disk.</source> + <translation>PSBT збережено на диск.</translation> + </message> + <message> + <source> * Sends %1 to %2</source> + <translation>* Надсилає від %1 до %2</translation> + </message> + <message> + <source>Unable to calculate transaction fee or total transaction amount.</source> + <translation>Неможливо розрахувати комісію за транзакцію або загальну суму транзакції.</translation> + </message> + <message> + <source>Pays transaction fee: </source> + <translation>Оплачує комісію за транзакцію:</translation> + </message> + <message> <source>Total Amount</source> <translation>Всього</translation> </message> @@ -1486,7 +1594,35 @@ Signing is only possible with addresses of the type 'legacy'.</source> <source>or</source> <translation>або</translation> </message> - </context> + <message> + <source>Transaction has %1 unsigned inputs.</source> + <translation>Транзакція містить %1 непідписаних входів.</translation> + </message> + <message> + <source>Transaction is missing some information about inputs.</source> + <translation>У транзакції бракує певної інформації про вхідні дані.</translation> + </message> + <message> + <source>Transaction still needs signature(s).</source> + <translation>Для транзакції все ще потрібні підпис(и).</translation> + </message> + <message> + <source>(But this wallet cannot sign transactions.)</source> + <translation>(Але цей гаманець не може підписувати транзакції.)</translation> + </message> + <message> + <source>(But this wallet does not have the right keys.)</source> + <translation>(Але цей гаманець не має правильних ключів.)</translation> + </message> + <message> + <source>Transaction is fully signed and ready for broadcast.</source> + <translation>Транзакція повністю підписана і готова до трансляції.</translation> + </message> + <message> + <source>Transaction status is unknown.</source> + <translation>Статус транзакції невідомий.</translation> + </message> +</context> <context> <name>PaymentServer</name> <message> @@ -1652,6 +1788,10 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Помилка: %1</translation> </message> <message> + <source>Error initializing settings: %1</source> + <translation>Помилка ініціалізації налаштувань: %1</translation> + </message> + <message> <source>%1 didn't yet exit safely...</source> <translation>%1 безпечний вихід ще не виконано...</translation> </message> @@ -1830,6 +1970,10 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation>Вікно вузлів</translation> </message> <message> + <source>Current block height</source> + <translation>Поточна висота блоку</translation> + </message> + <message> <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source> <translation>Відкрийте файл журналу налагодження %1 з поточного каталогу даних. Це може зайняти кілька секунд для файлів великого розміру.</translation> </message> @@ -2108,6 +2252,10 @@ Signing is only possible with addresses of the type 'legacy'.</source> <context> <name>ReceiveRequestDialog</name> <message> + <source>Request payment to ...</source> + <translation>Запит на оплату до ...</translation> + </message> + <message> <source>Address:</source> <translation>Адреса:</translation> </message> @@ -2394,6 +2542,22 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Ви впевнені, що хочете відправити?</translation> </message> <message> + <source>Create Unsigned</source> + <translation>Створити без підпису</translation> + </message> + <message> + <source>Save Transaction Data</source> + <translation>Зберегти дані транзакції</translation> + </message> + <message> + <source>Partially Signed Transaction (Binary) (*.psbt)</source> + <translation>Частково підписана транзакція (Binary) (* .psbt)</translation> + </message> + <message> + <source>PSBT saved</source> + <translation>PSBT збережено</translation> + </message> + <message> <source>or</source> <translation>або</translation> </message> @@ -2402,6 +2566,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Ви можете збільшити комісію пізніше (сигналізує Заміна-Через-Комісію, BIP-125).</translation> </message> <message> + <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can save or copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source> + <translation>Перегляньте свою пропозицію щодо транзакції. Це призведе до частково Підписаної Транзакції Біткойна (PSBT), яку ви можете зберегти або скопіювати, а потім підписати, наприклад, офлайн-гаманцем %1 або апаратним гаманецем, сумісний з PSBT.</translation> + </message> + <message> <source>Please, review your transaction.</source> <translation>Будь-ласка, перевірте вашу транзакцію.</translation> </message> @@ -3227,6 +3395,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <context> <name>WalletFrame</name> <message> + <source>No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR -</source> + <translation>Жоден гаманець не завантажений. Перейдіть у меню Файл> Відкрити гаманець, щоб завантажити гаманець. - АБО -</translation> + </message> + <message> <source>Create a new wallet</source> <translation>Створити новий гаманець</translation> </message> @@ -3305,6 +3479,26 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Помилка</translation> </message> <message> + <source>Unable to decode PSBT from clipboard (invalid base64)</source> + <translation>Не вдається декодувати PSBT з буфера обміну (недійсний base64)</translation> + </message> + <message> + <source>Load Transaction Data</source> + <translation>Завантажити дані транзакції</translation> + </message> + <message> + <source>Partially Signed Transaction (*.psbt)</source> + <translation>Частково підписана транзакція (* .psbt)</translation> + </message> + <message> + <source>PSBT file must be smaller than 100 MiB</source> + <translation>Файл PSBT повинен бути менше 100 Мб</translation> + </message> + <message> + <source>Unable to decode PSBT</source> + <translation>Не вдається декодувати PSBT</translation> + </message> + <message> <source>Backup Wallet</source> <translation>Зробити резервне копіювання гаманця</translation> </message> @@ -3372,6 +3566,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Помилка читання %s! Всі ключі зчитано правильно, але записи в адресній книзі, або дані транзакцій можуть бути відсутніми чи невірними.</translation> </message> <message> + <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source> + <translation>Надано більше однієї адреси прив'язки служби Tor. Використання %s для автоматично створеної служби Tor.</translation> + </message> + <message> <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> <translation>Перевірте правильність дати та часу комп'ютера. Якщо ваш годинник налаштовано невірно, %s не буде працювати належним чином.</translation> </message> @@ -3380,6 +3578,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Будь ласка, зробіть внесок, якщо ви знаходите %s корисним. Відвідайте %s для отримання додаткової інформації про програмне забезпечення.</translation> </message> <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase: Не вдалося підготувати оператор для отримання версії схеми гаманця: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source> + <translation>SQLiteDatabase: Не вдалося підготувати оператор для отримання ідентифікатора програми: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source> + <translation>SQLiteDatabase: Невідома версія схеми гаманця %d. Підтримується лише версія %d</translation> + </message> + <message> <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> <translation>Схоже, що база даних блоків містить блок з майбутнього. Це може статися із-за некоректно встановленої дати та/або часу. Перебудовуйте базу даних блоків лише тоді, коли ви переконані, що встановлено правильну дату і час</translation> </message> @@ -3484,6 +3694,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Помилка пересканування гаманця під час ініціалізації</translation> </message> <message> + <source>Failed to verify database</source> + <translation>Не вдалося перевірити базу даних</translation> + </message> + <message> <source>Importing...</source> <translation>Імпорт...</translation> </message> @@ -3512,6 +3726,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Невірна сума для зарезервованої комісії -fallbackfee=<amount>: '%s'</translation> </message> <message> + <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source> + <translation>SQLiteDatabase: Не вдалося виконати оператор для перевірки бази даних: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source> + <translation>QLiteDatabase: Не вдалося отримати версію схеми гаманця: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch the application id: %s</source> + <translation>SQLiteDatabase: Не вдалося отримати ідентифікатор програми: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source> + <translation>SQLiteDatabase: Не вдалося підготувати оператор для перевірки бази даних: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>SQLiteDatabase: Не вдалося прочитати помилку перевірки бази даних: %s</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>SQLiteDatabase: Несподіваний ідентифікатор програми. Очікується %u, отримано %u</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation>Зазначений каталог блоків "%s" не існує.</translation> </message> @@ -3596,6 +3834,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Помилка: Не вдалося налаштувати прослуховування вхідних підключень (listen повернув помилку: %s)</translation> </message> <message> + <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source> + <translation>%s пошкоджено. Спробуйте скористатися інструментом гаманця bitcoin-wallet для відновлення або відновлення резервної копії.</translation> + </message> + <message> + <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source> + <translation>Неможливо оновити спліт-гаманець, що не є HD, без оновлення, щоб підтримати попередньо розділений пул ключів. Будь ласка, використовуйте версію 169900 або не вказану версію.</translation> + </message> + <message> <source>Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source> <translation>Неприпустима сума для -maxtxfee = <amount>: «%s» ( плата повинна бути, принаймні %s, щоб запобігти зависанню транзакцій)</translation> </message> @@ -3604,6 +3850,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Залишок від суми транзакції зі сплатою комісії занадто малий</translation> </message> <message> + <source>This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet</source> + <translation>Ця помилка може статися, якщо цей гаманець не було чисто вимкнено і востаннє завантажений за допомогою збірки з новою версією Berkeley DB. Якщо так, будь ласка, використовуйте програмне забезпечення, яке востаннє завантажувало цей гаманець</translation> + </message> + <message> + <source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source> + <translation>Це максимальна комісія за транзакцію, яку ви сплачуєте (на додаток до звичайної комісії), щоб надавати пріоритет частковому уникненню витрат перед регулярним вибором монет.</translation> + </message> + <message> <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source> <translation>Транзакція потребує наявності адреси для отримання решти, але ми не змогли її згенерувати. Будь ласка, спочатку виконайте регенерацію пулу ключів.</translation> </message> @@ -3612,6 +3866,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Вам необхідно перебудувати базу даних з використанням -reindex для завантаження повного ланцюжка блоків.</translation> </message> <message> + <source>A fatal internal error occurred, see debug.log for details</source> + <translation>Виникла фатальна внутрішня помилка, див. debug.log для деталей</translation> + </message> + <message> + <source>Cannot set -peerblockfilters without -blockfilterindex.</source> + <translation>Неможливо встановити -peerblockfilters без -blockfilterindex.</translation> + </message> + <message> + <source>Disk space is too low!</source> + <translation>Місця на диску занадто мало!</translation> + </message> + <message> <source>Error reading from database, shutting down.</source> <translation>Помилка читання бази даних, припиняю роботу.</translation> </message> @@ -3624,6 +3890,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Помилка: для %s бракує місця на диску</translation> </message> <message> + <source>Error: Keypool ran out, please call keypoolrefill first</source> + <translation>Помилка: Пул ключів закінчився, потрібно викликати keypoolrefill вдруге</translation> + </message> + <message> + <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source> + <translation>Ставка комісії (%s) нижча за встановлену мінімальну ставку комісії (%s)</translation> + </message> + <message> <source>Invalid -onion address or hostname: '%s'</source> <translation>Невірна -onion адреса або ім'я хоста: '%s'</translation> </message> @@ -3644,6 +3918,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <translation>Необхідно вказати порт для -whitebind: «%s»</translation> </message> <message> + <source>No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>.</source> + <translation>Не вказано проксі-сервер. Використовуйте -проксі=<ip> або -проксі=<ip:port>.</translation> + </message> + <message> <source>Prune mode is incompatible with -blockfilterindex.</source> <translation>Використання скороченого ланцюжка блоків несумісне з параметром -blockfilterindex.</translation> </message> diff --git a/src/qt/locale/bitcoin_zh-Hans.ts b/src/qt/locale/bitcoin_zh-Hans.ts index efa3982fb2..93335756f2 100644 --- a/src/qt/locale/bitcoin_zh-Hans.ts +++ b/src/qt/locale/bitcoin_zh-Hans.ts @@ -30,6 +30,10 @@ <translation>从列表删除选定的地址</translation> </message> <message> + <source>Enter address or label to search</source> + <translation>输入地址或者标签进行搜索</translation> + </message> + <message> <source>Export the data in the current tab to a file</source> <translation>导出当前数据到文件</translation> </message> @@ -66,6 +70,12 @@ <translation>这是你的比特币发币地址。发送前请确认发送数量和接收地址</translation> </message> <message> + <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses. +Signing is only possible with addresses of the type 'legacy'.</source> + <translation>这是你的比特币接收地址。点击接收选项卡中“创建新的接收地址”按钮来创建新的地址。 +签名只能使用“传统”类型的地址。</translation> + </message> + <message> <source>&Copy Address</source> <translation>复制地址</translation> </message> @@ -112,9 +122,41 @@ <context> <name>AskPassphraseDialog</name> <message> + <source>Passphrase Dialog</source> + <translation>密码对话框</translation> + </message> + <message> + <source>Enter passphrase</source> + <translation>输入密码</translation> + </message> + <message> + <source>New passphrase</source> + <translation>新密码</translation> + </message> + <message> + <source>Repeat new passphrase</source> + <translation>重复输入新密码</translation> + </message> + <message> + <source>Show passphrase</source> + <translation>显示密码</translation> + </message> + <message> <source>Encrypt wallet</source> <translation>加密钱包</translation> </message> + <message> + <source>This operation needs your wallet passphrase to unlock the wallet.</source> + <translation>此操作需要您的钱包密码用来解锁钱包。</translation> + </message> + <message> + <source>Unlock wallet</source> + <translation>解锁钱包</translation> + </message> + <message> + <source>This operation needs your wallet passphrase to decrypt the wallet.</source> + <translation>此操作需要您的钱包密码用来解密钱包。</translation> + </message> </context> <context> <name>BanTableModel</name> diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts index 5a3808820d..fedc4a9c80 100644 --- a/src/qt/locale/bitcoin_zh_CN.ts +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -2599,7 +2599,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p </message> <message> <source>Confirm transaction proposal</source> - <translation>确认交易提案</translation> + <translation>确认交易请求</translation> </message> <message> <source>Send</source> @@ -3572,6 +3572,10 @@ Go to File > Open Wallet to load a wallet. <translation>读取 %s 时发生错误!所有的密钥都可以正确读取,但是交易记录或地址簿数据可能已经丢失或出错。</translation> </message> <message> + <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source> + <translation>提供多个洋葱路由绑定地址。对自动创建的洋葱服务用%s</translation> + </message> + <message> <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> <translation>请检查电脑的日期时间设置是否正确!时间错误可能会导致 %s 运行异常。</translation> </message> @@ -3580,6 +3584,18 @@ Go to File > Open Wallet to load a wallet. <translation>如果你认为%s对你比较有用的话,请对我们进行一些自愿贡献。请访问%s网站来获取有关这个软件的更多信息。</translation> </message> <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase:无法获取sqlit钱包版本:%s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source> + <translation>SQLiteDatabase:无法获取应用ID:%s</translation> + </message> + <message> + <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source> + <translation>SQLiteDatabase:未知sqlite钱包版本%d。只支持%d版本</translation> + </message> + <message> <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> <translation>区块数据库包含未来的交易,这可能是由本机错误的日期时间引起。若确认本机日期时间正确,请重新建立区块数据库。</translation> </message> @@ -3684,6 +3700,10 @@ Go to File > Open Wallet to load a wallet. <translation>初始化时重扫描钱包失败</translation> </message> <message> + <source>Failed to verify database</source> + <translation>校验数据库失败</translation> + </message> + <message> <source>Importing...</source> <translation>导入中...</translation> </message> @@ -3712,6 +3732,26 @@ Go to File > Open Wallet to load a wallet. <translation>参数 -fallbackfee=<amount>: '%s' 指定了无效的金额</translation> </message> <message> + <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source> + <translation>SQLiteDatabase:校验数据库执行语句失败:%s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source> + <translation>SQLiteDatabase:无法获取sqlite钱包版本:%s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source> + <translation>SQLiteDatabase:无法准备语句来校验数据库:%s</translation> + </message> + <message> + <source>SQLiteDatabase: Failed to read database verification error: %s</source> + <translation>SQLiteDatabase:无法读取数据库校验错误:%s</translation> + </message> + <message> + <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> + <translation>SQLiteDatabase:异常应用ID。异常%u,实际%u</translation> + </message> + <message> <source>Specified blocks directory "%s" does not exist.</source> <translation>指定的区块目录"%s"不存在。</translation> </message> diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 4c5601242e..3d78703ff7 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -479,13 +479,6 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty ui->WalletSelector->setVisible(false); ui->WalletSelectorLabel->setVisible(false); - // set library version labels -#ifdef ENABLE_WALLET - ui->berkeleyDBVersion->setText(QString::fromStdString(BerkeleyDatabaseVersion())); -#else - ui->label_berkeleyDBVersion->hide(); - ui->berkeleyDBVersion->hide(); -#endif // Register RPC timer interface rpcTimerInterface = new QtRPCTimerInterface(); // avoid accidentally overwriting an existing, non QTThread diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index de1fbcb94c..ea7b5f0c9e 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -14,17 +14,26 @@ #include <QDir> #include <QtGlobal> -static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request) +static RPCHelpMan rpcNestedTest_rpc() { - if (request.fHelp) { - return "help message"; - } - return request.params.write(0, 0); + return RPCHelpMan{ + "rpcNestedTest", + "echo the passed string(s)", + { + {"arg1", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""}, + {"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""}, + {"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""}, + }, + {}, + RPCExamples{""}, + [](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { + return request.params.write(0, 0); + }, + }; } -static const CRPCCommand vRPCCommands[] = -{ - { "test", "rpcNestedTest", &rpcNestedTest_rpc, {} }, +static const CRPCCommand vRPCCommands[] = { + {"test", "rpcNestedTest", &rpcNestedTest_rpc, {"arg1", "arg2", "arg3"}}, }; void RPCNestedTests::rpcNestedTests() diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index c560dc58e7..3148089b52 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -54,6 +54,30 @@ struct TxLessThan } }; +// queue notifications to show a non freezing progress dialog e.g. for rescan +struct TransactionNotification +{ +public: + TransactionNotification() {} + TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction): + hash(_hash), status(_status), showTransaction(_showTransaction) {} + + void invoke(QObject *ttm) + { + QString strHash = QString::fromStdString(hash.GetHex()); + qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status); + bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection, + Q_ARG(QString, strHash), + Q_ARG(int, status), + Q_ARG(bool, showTransaction)); + assert(invoked); + } +private: + uint256 hash; + ChangeType status; + bool showTransaction; +}; + // Private implementation class TransactionTablePriv { @@ -71,6 +95,12 @@ public: */ QList<TransactionRecord> cachedWallet; + bool fQueueNotifications = false; + std::vector< TransactionNotification > vQueueNotifications; + + void NotifyTransactionChanged(const uint256 &hash, ChangeType status); + void ShowProgress(const std::string &title, int nProgress); + /* Query entire wallet anew from core. */ void refreshWallet(interfaces::Wallet& wallet) @@ -674,34 +704,7 @@ void TransactionTableModel::updateDisplayUnit() Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount)); } -// queue notifications to show a non freezing progress dialog e.g. for rescan -struct TransactionNotification -{ -public: - TransactionNotification() {} - TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction): - hash(_hash), status(_status), showTransaction(_showTransaction) {} - - void invoke(QObject *ttm) - { - QString strHash = QString::fromStdString(hash.GetHex()); - qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status); - bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection, - Q_ARG(QString, strHash), - Q_ARG(int, status), - Q_ARG(bool, showTransaction)); - assert(invoked); - } -private: - uint256 hash; - ChangeType status; - bool showTransaction; -}; - -static bool fQueueNotifications = false; -static std::vector< TransactionNotification > vQueueNotifications; - -static void NotifyTransactionChanged(TransactionTableModel *ttm, const uint256 &hash, ChangeType status) +void TransactionTablePriv::NotifyTransactionChanged(const uint256 &hash, ChangeType status) { // Find transaction in wallet // Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread) @@ -714,10 +717,10 @@ static void NotifyTransactionChanged(TransactionTableModel *ttm, const uint256 & vQueueNotifications.push_back(notification); return; } - notification.invoke(ttm); + notification.invoke(parent); } -static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress) +void TransactionTablePriv::ShowProgress(const std::string &title, int nProgress) { if (nProgress == 0) fQueueNotifications = true; @@ -726,27 +729,27 @@ static void ShowProgress(TransactionTableModel *ttm, const std::string &title, i { fQueueNotifications = false; if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons - bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true)); + bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true)); assert(invoked); } for (unsigned int i = 0; i < vQueueNotifications.size(); ++i) { if (vQueueNotifications.size() - i <= 10) { - bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false)); + bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false)); assert(invoked); } - vQueueNotifications[i].invoke(ttm); + vQueueNotifications[i].invoke(parent); } - std::vector<TransactionNotification >().swap(vQueueNotifications); // clear + vQueueNotifications.clear(); } } void TransactionTableModel::subscribeToCoreSignals() { // Connect signals to wallet - m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2)); - m_handler_show_progress = walletModel->wallet().handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2)); + m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged(std::bind(&TransactionTablePriv::NotifyTransactionChanged, priv, std::placeholders::_1, std::placeholders::_2)); + m_handler_show_progress = walletModel->wallet().handleShowProgress(std::bind(&TransactionTablePriv::ShowProgress, priv, std::placeholders::_1, std::placeholders::_2)); } void TransactionTableModel::unsubscribeFromCoreSignals() diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 4a9b4a5c84..2edb7eff8a 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -196,11 +196,11 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard) } } -void WalletFrame::encryptWallet(bool status) +void WalletFrame::encryptWallet() { WalletView *walletView = currentWalletView(); if (walletView) - walletView->encryptWallet(status); + walletView->encryptWallet(); } void WalletFrame::backupWallet() diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index e2fa8055bd..271ddfc6c2 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -86,7 +86,7 @@ public Q_SLOTS: void gotoLoadPSBT(bool from_clipboard = false); /** Encrypt the wallet */ - void encryptWallet(bool status); + void encryptWallet(); /** Backup the wallet */ void backupWallet(); /** Change encrypted wallet passphrase */ diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 6a3f903206..cad472b43b 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -313,12 +313,9 @@ WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const } } -bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphrase) +bool WalletModel::setWalletEncrypted(const SecureString& passphrase) { - if (encrypted) { - return m_wallet->encryptWallet(passphrase); - } - return false; + return m_wallet->encryptWallet(passphrase); } bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase) diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index fd52db2da3..9a3c3f2f66 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -105,7 +105,7 @@ public: SendCoinsReturn sendCoins(WalletModelTransaction &transaction); // Wallet encryption - bool setWalletEncrypted(bool encrypted, const SecureString &passphrase); + bool setWalletEncrypted(const SecureString& passphrase); // Passphrase only needed when unlocking bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString()); bool changePassphrase(const SecureString &oldPass, const SecureString &newPass); diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 2fc883a5f5..b1e6b43e60 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -258,11 +258,11 @@ void WalletView::updateEncryptionStatus() Q_EMIT encryptionStatusChanged(); } -void WalletView::encryptWallet(bool status) +void WalletView::encryptWallet() { if(!walletModel) return; - AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt : AskPassphraseDialog::Decrypt, this); + AskPassphraseDialog dlg(AskPassphraseDialog::Encrypt, this); dlg.setModel(walletModel); dlg.exec(); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index f186554758..68f8a5e95b 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -92,7 +92,7 @@ public Q_SLOTS: */ void processNewTransaction(const QModelIndex& parent, int start, int /*end*/); /** Encrypt the wallet */ - void encryptWallet(bool status); + void encryptWallet(); /** Backup the wallet */ void backupWallet(); /** Change encrypted wallet passphrase */ diff --git a/src/randomenv.cpp b/src/randomenv.cpp index 07122b7f6d..5e07c3db40 100644 --- a/src/randomenv.cpp +++ b/src/randomenv.cpp @@ -53,7 +53,7 @@ #include <sys/vmmeter.h> #endif #endif -#ifdef __linux__ +#if defined(HAVE_STRONG_GETAUXVAL) || defined(HAVE_WEAK_GETAUXVAL) #include <sys/auxv.h> #endif @@ -326,7 +326,7 @@ void RandAddStaticEnv(CSHA512& hasher) // Bitcoin client version hasher << CLIENT_VERSION; -#ifdef __linux__ +#if defined(HAVE_STRONG_GETAUXVAL) || defined(HAVE_WEAK_GETAUXVAL) // Information available through getauxval() # ifdef AT_HWCAP hasher << getauxval(AT_HWCAP); @@ -346,7 +346,7 @@ void RandAddStaticEnv(CSHA512& hasher) const char* exec_str = (const char*)getauxval(AT_EXECFN); if (exec_str) hasher.Write((const unsigned char*)exec_str, strlen(exec_str) + 1); # endif -#endif // __linux__ +#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL #ifdef HAVE_GETCPUID AddAllCPUID(hasher); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 88c8ebe1f6..042005b9a6 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -41,7 +41,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "sendtoaddress", 5 , "replaceable" }, { "sendtoaddress", 6 , "conf_target" }, { "sendtoaddress", 8, "avoid_reuse" }, - { "sendtoaddress", 9, "verbose"}, + { "sendtoaddress", 9, "fee_rate"}, + { "sendtoaddress", 10, "verbose"}, { "settxfee", 0, "amount" }, { "sethdseed", 0, "newkeypool" }, { "getreceivedbyaddress", 1, "minconf" }, @@ -73,7 +74,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "sendmany", 4, "subtractfeefrom" }, { "sendmany", 5 , "replaceable" }, { "sendmany", 6 , "conf_target" }, - { "sendmany", 8, "verbose" }, + { "sendmany", 8, "fee_rate"}, + { "sendmany", 9, "verbose" }, { "deriveaddresses", 1, "range" }, { "scantxoutset", 1, "scanobjects" }, { "addmultisigaddress", 0, "nrequired" }, @@ -129,7 +131,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "lockunspent", 1, "transactions" }, { "send", 0, "outputs" }, { "send", 1, "conf_target" }, - { "send", 3, "options" }, + { "send", 3, "fee_rate"}, + { "send", 4, "options" }, { "importprivkey", 2, "rescan" }, { "importaddress", 2, "rescan" }, { "importaddress", 3, "p2sh" }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index a561b7e93c..7d45ad9434 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -242,12 +242,7 @@ static RPCHelpMan generatetodescriptor() static RPCHelpMan generate() { return RPCHelpMan{"generate", "has been replaced by the -generate cli option. Refer to -help for more information.", {}, {}, RPCExamples{""}, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - - if (request.fHelp) { - throw std::runtime_error(self.ToString()); - } else { throw JSONRPCError(RPC_METHOD_NOT_FOUND, self.ToString()); - } }}; } @@ -1070,7 +1065,7 @@ static RPCHelpMan estimatesmartfee() if (!request.params[1].isNull()) { FeeEstimateMode fee_mode; if (!FeeModeFromString(request.params[1].get_str(), fee_mode)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); + throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage()); } if (fee_mode == FeeEstimateMode::ECONOMICAL) conservative = false; } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 0c982317f5..b3102a236d 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -624,8 +624,6 @@ static RPCHelpMan echo(const std::string& name) RPCExamples{""}, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - if (request.fHelp) throw std::runtime_error(self.ToString()); - if (request.params[9].isStr()) { CHECK_NONFATAL(request.params[9].get_str() != "trigger_internal_bug"); } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index f98ea63782..e72ef24d12 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -288,10 +288,10 @@ static RPCHelpMan addnode() std::string strCommand; if (!request.params[1].isNull()) strCommand = request.params[1].get_str(); - if (request.fHelp || request.params.size() != 2 || - (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) + if (strCommand != "onetry" && strCommand != "add" && strCommand != "remove") { throw std::runtime_error( self.ToString()); + } NodeContext& node = EnsureNodeContext(request.context); if(!node.connman) @@ -628,7 +628,7 @@ static RPCHelpMan setban() std::string strCommand; if (!request.params[1].isNull()) strCommand = request.params[1].get_str(); - if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) { + if (strCommand != "add" && strCommand != "remove") { throw std::runtime_error(help.ToString()); } NodeContext& node = EnsureNodeContext(request.context); diff --git a/src/rpc/server.h b/src/rpc/server.h index b2358ac5b2..7d13edb8b0 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -85,7 +85,6 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface); */ void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds); -typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest); typedef RPCHelpMan (*RpcMethodFnType)(); class CRPCCommand @@ -116,14 +115,6 @@ public: CHECK_NONFATAL(fn().GetArgNames() == args_in); } - //! Simplified constructor taking plain rpcfn_type function pointer. - CRPCCommand(const char* category, const char* name, rpcfn_type fn, std::initializer_list<const char*> args) - : CRPCCommand(category, name, - [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn(request); return true; }, - {args.begin(), args.end()}, intptr_t(fn)) - { - } - std::string category; std::string name; Actor actor; diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index e20900ed13..c16519a6b1 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(BinaryOperatorTest) BOOST_CHECK(a <= a); BOOST_CHECK(b >= a); BOOST_CHECK(b >= b); - // a should be 0.00000002 BTC/kB now + // a should be 0.00000002 BTC/kvB now a += a; BOOST_CHECK(a == b); } @@ -107,7 +107,9 @@ BOOST_AUTO_TEST_CASE(ToStringTest) { CFeeRate feeRate; feeRate = CFeeRate(1); - BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kB"); + BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeEstimateMode::BTC_KVB), "0.00000001 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeEstimateMode::SAT_VB), "0.001 sat/vB"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp new file mode 100644 index 0000000000..0ceeea2d36 --- /dev/null +++ b/src/test/fuzz/addrman.cpp @@ -0,0 +1,119 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <addrdb.h> +#include <addrman.h> +#include <chainparams.h> +#include <merkleblock.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <time.h> +#include <util/asmap.h> + +#include <cstdint> +#include <optional> +#include <string> +#include <vector> + +void initialize() +{ + SelectParams(CBaseChainParams::REGTEST); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + + SetMockTime(ConsumeTime(fuzzed_data_provider)); + CAddrMan addr_man; + if (fuzzed_data_provider.ConsumeBool()) { + addr_man.m_asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider); + if (!SanityCheckASMap(addr_man.m_asmap)) { + addr_man.m_asmap.clear(); + } + } + while (fuzzed_data_provider.ConsumeBool()) { + switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 11)) { + case 0: { + addr_man.Clear(); + break; + } + case 1: { + addr_man.ResolveCollisions(); + break; + } + case 2: { + (void)addr_man.SelectTriedCollision(); + break; + } + case 3: { + (void)addr_man.Select(fuzzed_data_provider.ConsumeBool()); + break; + } + case 4: { + (void)addr_man.GetAddr(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096)); + break; + } + case 5: { + const std::optional<CAddress> opt_address = ConsumeDeserializable<CAddress>(fuzzed_data_provider); + const std::optional<CNetAddr> opt_net_addr = ConsumeDeserializable<CNetAddr>(fuzzed_data_provider); + if (opt_address && opt_net_addr) { + addr_man.Add(*opt_address, *opt_net_addr, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 100000000)); + } + break; + } + case 6: { + std::vector<CAddress> addresses; + while (fuzzed_data_provider.ConsumeBool()) { + const std::optional<CAddress> opt_address = ConsumeDeserializable<CAddress>(fuzzed_data_provider); + if (!opt_address) { + break; + } + addresses.push_back(*opt_address); + } + const std::optional<CNetAddr> opt_net_addr = ConsumeDeserializable<CNetAddr>(fuzzed_data_provider); + if (opt_net_addr) { + addr_man.Add(addresses, *opt_net_addr, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 100000000)); + } + break; + } + case 7: { + const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider); + if (opt_service) { + addr_man.Good(*opt_service, fuzzed_data_provider.ConsumeBool(), ConsumeTime(fuzzed_data_provider)); + } + break; + } + case 8: { + const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider); + if (opt_service) { + addr_man.Attempt(*opt_service, fuzzed_data_provider.ConsumeBool(), ConsumeTime(fuzzed_data_provider)); + } + break; + } + case 9: { + const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider); + if (opt_service) { + addr_man.Connected(*opt_service, ConsumeTime(fuzzed_data_provider)); + } + break; + } + case 10: { + const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider); + if (opt_service) { + addr_man.SetServices(*opt_service, ServiceFlags{fuzzed_data_provider.ConsumeIntegral<uint64_t>()}); + } + break; + } + case 11: { + (void)addr_man.Check(); + break; + } + } + } + (void)addr_man.size(); + CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION); + data_stream << addr_man; +} diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp new file mode 100644 index 0000000000..6521c3f3b2 --- /dev/null +++ b/src/test/fuzz/connman.cpp @@ -0,0 +1,162 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <chainparams.h> +#include <chainparamsbase.h> +#include <net.h> +#include <netaddress.h> +#include <protocol.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <util/translation.h> + +#include <cstdint> +#include <vector> + +void initialize() +{ + InitializeFuzzingContext(); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; + CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeBool()}; + CAddress random_address; + CNetAddr random_netaddr; + CNode random_node = ConsumeNode(fuzzed_data_provider); + CService random_service; + CSubNet random_subnet; + std::string random_string; + while (fuzzed_data_provider.ConsumeBool()) { + switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 30)) { + case 0: + random_address = ConsumeAddress(fuzzed_data_provider); + break; + case 1: + random_netaddr = ConsumeNetAddr(fuzzed_data_provider); + break; + case 2: + random_service = ConsumeService(fuzzed_data_provider); + break; + case 3: + random_subnet = ConsumeSubNet(fuzzed_data_provider); + break; + case 4: + random_string = fuzzed_data_provider.ConsumeRandomLengthString(64); + break; + case 5: { + std::vector<CAddress> addresses; + while (fuzzed_data_provider.ConsumeBool()) { + addresses.push_back(ConsumeAddress(fuzzed_data_provider)); + } + // Limit nTimePenalty to int32_t to avoid signed integer overflow + (void)connman.AddNewAddresses(addresses, ConsumeAddress(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<int32_t>()); + break; + } + case 6: + connman.AddNode(random_string); + break; + case 7: + connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + break; + case 8: + connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral<NodeId>()); + break; + case 9: + connman.DisconnectNode(random_netaddr); + break; + case 10: + connman.DisconnectNode(random_string); + break; + case 11: + connman.DisconnectNode(random_subnet); + break; + case 12: + connman.ForEachNode([](auto) {}); + break; + case 13: + connman.ForEachNodeThen([](auto) {}, []() {}); + break; + case 14: + (void)connman.ForNode(fuzzed_data_provider.ConsumeIntegral<NodeId>(), [&](auto) { return fuzzed_data_provider.ConsumeBool(); }); + break; + case 15: + (void)connman.GetAddresses(fuzzed_data_provider.ConsumeIntegral<size_t>(), fuzzed_data_provider.ConsumeIntegral<size_t>()); + break; + case 16: { + (void)connman.GetAddresses(random_node, fuzzed_data_provider.ConsumeIntegral<size_t>(), fuzzed_data_provider.ConsumeIntegral<size_t>()); + break; + } + case 17: + (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + break; + case 18: + (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({CConnman::CONNECTIONS_NONE, CConnman::CONNECTIONS_IN, CConnman::CONNECTIONS_OUT, CConnman::CONNECTIONS_ALL})); + break; + case 19: + connman.MarkAddressGood(random_address); + break; + case 20: + (void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool()); + break; + case 21: + // Limit now to int32_t to avoid signed integer overflow + (void)connman.PoissonNextSendInbound(fuzzed_data_provider.ConsumeIntegral<int32_t>(), fuzzed_data_provider.ConsumeIntegral<int>()); + break; + case 22: { + CSerializedNetMsg serialized_net_msg; + serialized_net_msg.m_type = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::COMMAND_SIZE); + serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider); + connman.PushMessage(&random_node, std::move(serialized_net_msg)); + break; + } + case 23: + connman.RemoveAddedNode(random_string); + break; + case 24: { + const std::vector<bool> asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider); + if (SanityCheckASMap(asmap)) { + connman.SetAsmap(asmap); + } + break; + } + case 25: + connman.SetBestHeight(fuzzed_data_provider.ConsumeIntegral<int>()); + break; + case 26: + connman.SetMaxOutboundTarget(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + break; + case 27: + connman.SetMaxOutboundTimeframe(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + break; + case 28: + connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool()); + break; + case 29: + connman.SetServices(random_service, static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>())); + break; + case 30: + connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool()); + break; + } + } + (void)connman.GetAddedNodeInfo(); + (void)connman.GetBestHeight(); + (void)connman.GetExtraOutboundCount(); + (void)connman.GetLocalServices(); + (void)connman.GetMaxOutboundTarget(); + (void)connman.GetMaxOutboundTimeframe(); + (void)connman.GetMaxOutboundTimeLeftInCycle(); + (void)connman.GetNetworkActive(); + std::vector<CNodeStats> stats; + connman.GetNodeStats(stats); + (void)connman.GetOutboundTargetBytesLeft(); + (void)connman.GetReceiveFloodSize(); + (void)connman.GetTotalBytesRecv(); + (void)connman.GetTotalBytesSent(); + (void)connman.GetTryNewOutboundPeer(); + (void)connman.GetUseAddrmanOutgoing(); +} diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index 9803fdc882..8ca5366c8a 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -15,6 +15,7 @@ #include <net.h> #include <netbase.h> #include <node/utxo_snapshot.h> +#include <optional.h> #include <primitives/block.h> #include <protocol.h> #include <psbt.h> @@ -61,15 +62,19 @@ T Deserialize(CDataStream ds) } template <typename T> -void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj) +void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj, const Optional<int> protocol_version = nullopt) { CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); - try { - int version; - ds >> version; - ds.SetVersion(version); - } catch (const std::ios_base::failure&) { - throw invalid_fuzzing_input_exception(); + if (protocol_version) { + ds.SetVersion(*protocol_version); + } else { + try { + int version; + ds >> version; + ds.SetVersion(version); + } catch (const std::ios_base::failure&) { + throw invalid_fuzzing_input_exception(); + } } try { ds >> obj; @@ -125,9 +130,15 @@ void test_one_input(const std::vector<uint8_t>& buffer) CScript script; DeserializeFromFuzzingInput(buffer, script); #elif SUB_NET_DESERIALIZE - CSubNet sub_net; - DeserializeFromFuzzingInput(buffer, sub_net); - AssertEqualAfterSerializeDeserialize(sub_net); + CSubNet sub_net_1; + DeserializeFromFuzzingInput(buffer, sub_net_1, INIT_PROTO_VERSION); + AssertEqualAfterSerializeDeserialize(sub_net_1, INIT_PROTO_VERSION); + CSubNet sub_net_2; + DeserializeFromFuzzingInput(buffer, sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT); + AssertEqualAfterSerializeDeserialize(sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT); + CSubNet sub_net_3; + DeserializeFromFuzzingInput(buffer, sub_net_3); + AssertEqualAfterSerializeDeserialize(sub_net_3, INIT_PROTO_VERSION | ADDRV2_FORMAT); #elif TX_IN_DESERIALIZE CTxIn tx_in; DeserializeFromFuzzingInput(buffer, tx_in); @@ -195,6 +206,13 @@ void test_one_input(const std::vector<uint8_t>& buffer) AssertEqualAfterSerializeDeserialize(s); } AssertEqualAfterSerializeDeserialize(s, INIT_PROTO_VERSION | ADDRV2_FORMAT); + CService s1; + DeserializeFromFuzzingInput(buffer, s1, INIT_PROTO_VERSION); + AssertEqualAfterSerializeDeserialize(s1, INIT_PROTO_VERSION); + assert(s1.IsAddrV1Compatible()); + CService s2; + DeserializeFromFuzzingInput(buffer, s2, INIT_PROTO_VERSION | ADDRV2_FORMAT); + AssertEqualAfterSerializeDeserialize(s2, INIT_PROTO_VERSION | ADDRV2_FORMAT); #elif MESSAGEHEADER_DESERIALIZE CMessageHeader mh; DeserializeFromFuzzingInput(buffer, mh); diff --git a/src/test/fuzz/merkleblock.cpp b/src/test/fuzz/merkleblock.cpp index c44e334272..4710e75757 100644 --- a/src/test/fuzz/merkleblock.cpp +++ b/src/test/fuzz/merkleblock.cpp @@ -16,12 +16,36 @@ void test_one_input(const std::vector<uint8_t>& buffer) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - std::optional<CPartialMerkleTree> partial_merkle_tree = ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider); - if (!partial_merkle_tree) { - return; + CPartialMerkleTree partial_merkle_tree; + switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1)) { + case 0: { + const std::optional<CPartialMerkleTree> opt_partial_merkle_tree = ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider); + if (opt_partial_merkle_tree) { + partial_merkle_tree = *opt_partial_merkle_tree; + } + break; } - (void)partial_merkle_tree->GetNumTransactions(); + case 1: { + CMerkleBlock merkle_block; + const std::optional<CBlock> opt_block = ConsumeDeserializable<CBlock>(fuzzed_data_provider); + CBloomFilter bloom_filter; + std::set<uint256> txids; + if (opt_block && !opt_block->vtx.empty()) { + if (fuzzed_data_provider.ConsumeBool()) { + merkle_block = CMerkleBlock{*opt_block, bloom_filter}; + } else if (fuzzed_data_provider.ConsumeBool()) { + while (fuzzed_data_provider.ConsumeBool()) { + txids.insert(ConsumeUInt256(fuzzed_data_provider)); + } + merkle_block = CMerkleBlock{*opt_block, txids}; + } + } + partial_merkle_tree = merkle_block.txn; + break; + } + } + (void)partial_merkle_tree.GetNumTransactions(); std::vector<uint256> matches; std::vector<unsigned int> indices; - (void)partial_merkle_tree->ExtractMatches(matches, indices); + (void)partial_merkle_tree.ExtractMatches(matches, indices); } diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index 3818838765..c61d406291 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -63,7 +63,7 @@ void test_one_input(const std::vector<uint8_t>& buffer) break; } case 3: { - const std::vector<bool> asmap = ConsumeRandomLengthIntegralVector<bool>(fuzzed_data_provider, 128); + const std::vector<bool> asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider); if (!SanityCheckASMap(asmap)) { break; } diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index 3ef03137ec..9390399878 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -16,6 +16,7 @@ #include <test/util/mining.h> #include <test/util/net.h> #include <test/util/setup_common.h> +#include <test/util/validation.h> #include <util/memory.h> #include <validationinterface.h> #include <version.h> @@ -63,10 +64,14 @@ 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(); + TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate(); + chainstate.ResetIbd(); const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()}; if (!LIMIT_TO_MESSAGE_TYPE.empty() && random_message_type != LIMIT_TO_MESSAGE_TYPE) { return; } + const bool jump_out_of_ibd{fuzzed_data_provider.ConsumeBool()}; + if (jump_out_of_ibd) chainstate.JumpOutOfIbd(); CDataStream random_bytes_data_stream{fuzzed_data_provider.ConsumeRemainingBytes<unsigned char>(), SER_NETWORK, PROTOCOL_VERSION}; CNode& p2p_node = *MakeUnique<CNode>(0, ServiceFlags(NODE_NETWORK | NODE_WITNESS | NODE_BLOOM), 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, ConnectionType::OUTBOUND_FULL_RELAY).release(); p2p_node.fSuccessfullyConnected = true; @@ -76,7 +81,7 @@ void test_one_input(const std::vector<uint8_t>& buffer) g_setup->m_node.peerman->InitializeNode(&p2p_node); try { g_setup->m_node.peerman->ProcessMessage(p2p_node, random_message_type, random_bytes_data_stream, - GetTime<std::chrono::microseconds>(), std::atomic<bool>{false}); + GetTime<std::chrono::microseconds>(), std::atomic<bool>{false}); } catch (const std::ios_base::failure&) { } SyncWithValidationInterfaceQueue(); diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index f722eeac3a..19ea92b750 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -12,6 +12,7 @@ #include <test/util/mining.h> #include <test/util/net.h> #include <test/util/setup_common.h> +#include <test/util/validation.h> #include <util/memory.h> #include <validation.h> #include <validationinterface.h> @@ -39,7 +40,10 @@ 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(); + TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate(); + chainstate.ResetIbd(); std::vector<CNode*> peers; + bool jump_out_of_ibd{false}; const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3); for (int i = 0; i < num_peers_to_add; ++i) { @@ -58,6 +62,8 @@ void test_one_input(const std::vector<uint8_t>& buffer) } while (fuzzed_data_provider.ConsumeBool()) { + if (!jump_out_of_ibd) jump_out_of_ibd = fuzzed_data_provider.ConsumeBool(); + if (jump_out_of_ibd && chainstate.IsInitialBlockDownload()) chainstate.JumpOutOfIbd(); const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()}; CSerializedNetMsg net_msg; diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index ed6093a8a8..e99ed8d72d 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -11,6 +11,8 @@ #include <chainparamsbase.h> #include <coins.h> #include <consensus/consensus.h> +#include <merkleblock.h> +#include <net.h> #include <netaddress.h> #include <netbase.h> #include <primitives/transaction.h> @@ -23,6 +25,7 @@ #include <test/util/setup_common.h> #include <txmempool.h> #include <uint256.h> +#include <util/time.h> #include <version.h> #include <algorithm> @@ -38,6 +41,11 @@ NODISCARD inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataPr return {s.begin(), s.end()}; } +NODISCARD inline std::vector<bool> ConsumeRandomLengthBitVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept +{ + return BytesToBits(ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length)); +} + NODISCARD inline CDataStream ConsumeDataStream(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept { return {ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length), SER_NETWORK, INIT_PROTO_VERSION}; @@ -88,6 +96,13 @@ NODISCARD inline CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider) return fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, MAX_MONEY); } +NODISCARD inline int64_t ConsumeTime(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + static const int64_t time_min = ParseISO8601DateTime("1970-01-01T00:00:00Z"); + static const int64_t time_max = ParseISO8601DateTime("9999-12-31T23:59:59Z"); + return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(time_min, time_max); +} + NODISCARD inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept { const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider); @@ -260,6 +275,32 @@ CSubNet ConsumeSubNet(FuzzedDataProvider& fuzzed_data_provider) noexcept return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint8_t>()}; } +CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint16_t>()}; +} + +CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return {ConsumeService(fuzzed_data_provider), static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()), fuzzed_data_provider.ConsumeIntegral<uint32_t>()}; +} + +CNode ConsumeNode(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + const NodeId node_id = fuzzed_data_provider.ConsumeIntegral<NodeId>(); + const ServiceFlags local_services = static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + const int my_starting_height = fuzzed_data_provider.ConsumeIntegral<int>(); + const SOCKET socket = INVALID_SOCKET; + const CAddress address = ConsumeAddress(fuzzed_data_provider); + const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>(); + const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>(); + const CAddress addr_bind = ConsumeAddress(fuzzed_data_provider); + const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64); + const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH}); + const bool inbound_onion = fuzzed_data_provider.ConsumeBool(); + return {node_id, local_services, my_starting_height, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, conn_type, inbound_onion}; +} + void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST) { static const BasicTestingSetup basic_testing_setup{chain_name, {"-nodebuglogfile"}}; diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index a09c8c122d..1812ce1666 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -11,6 +11,7 @@ #include <node/context.h> #include <pubkey.h> #include <random.h> +#include <stdexcept> #include <txmempool.h> #include <util/check.h> #include <util/string.h> @@ -158,13 +159,15 @@ std::ostream& operator<<(std::ostream& os, const uint256& num); * Use as * BOOST_CHECK_EXCEPTION(code that throws, exception type, HasReason("foo")); */ -class HasReason { +class HasReason +{ public: explicit HasReason(const std::string& reason) : m_reason(reason) {} - template <typename E> - bool operator() (const E& e) const { + bool operator()(const std::exception& e) const + { return std::string(e.what()).find(m_reason) != std::string::npos; }; + private: const std::string m_reason; }; diff --git a/src/test/util/validation.cpp b/src/test/util/validation.cpp new file mode 100644 index 0000000000..1aed492c3c --- /dev/null +++ b/src/test/util/validation.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/util/validation.h> + +#include <util/check.h> +#include <util/time.h> +#include <validation.h> + +void TestChainState::ResetIbd() +{ + m_cached_finished_ibd = false; + assert(IsInitialBlockDownload()); +} + +void TestChainState::JumpOutOfIbd() +{ + Assert(IsInitialBlockDownload()); + m_cached_finished_ibd = true; + Assert(!IsInitialBlockDownload()); +} diff --git a/src/test/util/validation.h b/src/test/util/validation.h new file mode 100644 index 0000000000..b13aa0be60 --- /dev/null +++ b/src/test/util/validation.h @@ -0,0 +1,17 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TEST_UTIL_VALIDATION_H +#define BITCOIN_TEST_UTIL_VALIDATION_H + +#include <validation.h> + +struct TestChainState : public CChainState { + /** Reset the ibd cache to its initial state */ + void ResetIbd(); + /** Toggle IsInitialBlockDownload from true to false */ + void JumpOutOfIbd(); +}; + +#endif // BITCOIN_TEST_UTIL_VALIDATION_H diff --git a/src/util/fees.cpp b/src/util/fees.cpp index 6208a20a97..1855c0bc90 100644 --- a/src/util/fees.cpp +++ b/src/util/fees.cpp @@ -40,8 +40,6 @@ const std::vector<std::pair<std::string, FeeEstimateMode>>& FeeModeMap() {"unset", FeeEstimateMode::UNSET}, {"economical", FeeEstimateMode::ECONOMICAL}, {"conservative", FeeEstimateMode::CONSERVATIVE}, - {(CURRENCY_UNIT + "/kB"), FeeEstimateMode::BTC_KB}, - {(CURRENCY_ATOM + "/B"), FeeEstimateMode::SAT_B}, }; return FEE_MODES; } @@ -51,6 +49,11 @@ std::string FeeModes(const std::string& delimiter) return Join(FeeModeMap(), delimiter, [&](const std::pair<std::string, FeeEstimateMode>& i) { return i.first; }); } +const std::string InvalidEstimateModeErrorMessage() +{ + return "Invalid estimate_mode parameter, must be one of: \"" + FeeModes("\", \"") + "\""; +} + bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) { auto searchkey = ToUpper(mode_string); diff --git a/src/util/fees.h b/src/util/fees.h index d52046a44c..3f1c33ad9c 100644 --- a/src/util/fees.h +++ b/src/util/fees.h @@ -13,5 +13,6 @@ enum class FeeReason; bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode); std::string StringForFeeReason(FeeReason reason); std::string FeeModes(const std::string& delimiter); +const std::string InvalidEstimateModeErrorMessage(); #endif // BITCOIN_UTIL_FEES_H diff --git a/src/util/memory.h b/src/util/memory.h index 15ecf8f80d..4d73b32869 100644 --- a/src/util/memory.h +++ b/src/util/memory.h @@ -10,10 +10,11 @@ #include <utility> //! Substitute for C++14 std::make_unique. +//! DEPRECATED use std::make_unique in new code. template <typename T, typename... Args> std::unique_ptr<T> MakeUnique(Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); + return std::make_unique<T>(std::forward<Args>(args)...); } #endif diff --git a/src/validation.cpp b/src/validation.cpp index 8241cb159f..71402ef263 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1312,8 +1312,6 @@ bool CChainState::IsInitialBlockDownload() const return false; } -static CBlockIndex *pindexBestForkTip = nullptr, *pindexBestForkBase = nullptr; - static void AlertNotify(const std::string& strMessage) { uiInterface.NotifyAlertChanged(); @@ -1339,73 +1337,16 @@ static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main) AssertLockHeld(cs_main); // Before we get past initial download, we cannot reliably alert about forks // (we assume we don't get stuck on a fork before finishing our initial sync) - if (::ChainstateActive().IsInitialBlockDownload()) + if (::ChainstateActive().IsInitialBlockDownload()) { return; - - // If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it) - // of our head, drop it - if (pindexBestForkTip && ::ChainActive().Height() - pindexBestForkTip->nHeight >= 72) - pindexBestForkTip = nullptr; - - if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > ::ChainActive().Tip()->nChainWork + (GetBlockProof(*::ChainActive().Tip()) * 6))) - { - if (!GetfLargeWorkForkFound() && pindexBestForkBase) - { - std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") + - pindexBestForkBase->phashBlock->ToString() + std::string("'"); - AlertNotify(warning); - } - if (pindexBestForkTip && pindexBestForkBase) - { - LogPrintf("%s: Warning: Large valid fork found\n forking the chain at height %d (%s)\n lasting to height %d (%s).\nChain state database corruption likely.\n", __func__, - pindexBestForkBase->nHeight, pindexBestForkBase->phashBlock->ToString(), - pindexBestForkTip->nHeight, pindexBestForkTip->phashBlock->ToString()); - SetfLargeWorkForkFound(true); - } - else - { - LogPrintf("%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__); - SetfLargeWorkInvalidChainFound(true); - } - } - else - { - SetfLargeWorkForkFound(false); - SetfLargeWorkInvalidChainFound(false); } -} -static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) EXCLUSIVE_LOCKS_REQUIRED(cs_main) -{ - AssertLockHeld(cs_main); - // If we are on a fork that is sufficiently large, set a warning flag - CBlockIndex* pfork = pindexNewForkTip; - CBlockIndex* plonger = ::ChainActive().Tip(); - while (pfork && pfork != plonger) - { - while (plonger && plonger->nHeight > pfork->nHeight) - plonger = plonger->pprev; - if (pfork == plonger) - break; - pfork = pfork->pprev; - } - - // We define a condition where we should warn the user about as a fork of at least 7 blocks - // with a tip within 72 blocks (+/- 12 hours if no one mines it) of ours - // We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network - // hash rate operating on the fork. - // or a chain that is entirely longer than ours and invalid (note that this should be detected by both) - // We define it this way because it allows us to only store the highest fork tip (+ base) which meets - // the 7-block condition and from this always have the most-likely-to-cause-warning fork - if (pfork && (!pindexBestForkTip || pindexNewForkTip->nHeight > pindexBestForkTip->nHeight) && - pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) && - ::ChainActive().Height() - pindexNewForkTip->nHeight < 72) - { - pindexBestForkTip = pindexNewForkTip; - pindexBestForkBase = pfork; + if (pindexBestInvalid && pindexBestInvalid->nChainWork > ::ChainActive().Tip()->nChainWork + (GetBlockProof(*::ChainActive().Tip()) * 6)) { + LogPrintf("%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__); + SetfLargeWorkInvalidChainFound(true); + } else { + SetfLargeWorkInvalidChainFound(false); } - - CheckForkWarningConditions(); } // Called both upon regular invalid block discovery *and* InvalidateBlock @@ -2457,9 +2398,7 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C } bilingual_str warning_messages; - int num_unexpected_version = 0; - if (!::ChainstateActive().IsInitialBlockDownload()) - { + if (!::ChainstateActive().IsInitialBlockDownload()) { const CBlockIndex* pindex = pindexNew; for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { WarningBitsConditionChecker checker(bit); @@ -2473,14 +2412,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C } } } - // Check the version of the last 100 blocks to see if we need to upgrade: - for (int i = 0; i < 100 && pindex != nullptr; i++) - { - int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus()); - if (pindex->nVersion > VERSIONBITS_LAST_OLD_BLOCK_VERSION && (pindex->nVersion & ~nExpectedVersion) != 0) - ++num_unexpected_version; - pindex = pindex->pprev; - } } LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s\n", __func__, pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion, @@ -2488,10 +2419,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C FormatISO8601DateTime(pindexNew->GetBlockTime()), GuessVerificationProgress(chainParams.TxData(), pindexNew), ::ChainstateActive().CoinsTip().DynamicMemoryUsage() * (1.0 / (1<<20)), ::ChainstateActive().CoinsTip().GetCacheSize(), !warning_messages.empty() ? strprintf(" warning='%s'", warning_messages.original) : ""); - - if (num_unexpected_version > 0) { - LogPrint(BCLog::VALIDATION, "%d of last 100 blocks have unexpected version\n", num_unexpected_version); - } } /** Disconnect m_chain's tip. @@ -2746,8 +2673,8 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai AssertLockHeld(cs_main); AssertLockHeld(m_mempool.cs); - const CBlockIndex *pindexOldTip = m_chain.Tip(); - const CBlockIndex *pindexFork = m_chain.FindFork(pindexMostWork); + const CBlockIndex* pindexOldTip = m_chain.Tip(); + const CBlockIndex* pindexFork = m_chain.FindFork(pindexMostWork); // Disconnect active blocks which are no longer in the best chain. bool fBlocksDisconnected = false; @@ -2767,7 +2694,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai fBlocksDisconnected = true; } - // Build list of new blocks to connect. + // Build list of new blocks to connect (in descending height order). std::vector<CBlockIndex*> vpindexToConnect; bool fContinue = true; int nHeight = pindexFork ? pindexFork->nHeight : -1; @@ -2777,7 +2704,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight); vpindexToConnect.clear(); vpindexToConnect.reserve(nTargetHeight - nHeight); - CBlockIndex *pindexIter = pindexMostWork->GetAncestor(nTargetHeight); + CBlockIndex* pindexIter = pindexMostWork->GetAncestor(nTargetHeight); while (pindexIter && pindexIter->nHeight != nHeight) { vpindexToConnect.push_back(pindexIter); pindexIter = pindexIter->pprev; @@ -2785,7 +2712,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai nHeight = nTargetHeight; // Connect new blocks. - for (CBlockIndex *pindexConnect : reverse_iterate(vpindexToConnect)) { + for (CBlockIndex* pindexConnect : reverse_iterate(vpindexToConnect)) { if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) { if (state.IsInvalid()) { // The block violates a consensus rule. @@ -2821,11 +2748,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai } m_mempool.check(&CoinsTip()); - // Callbacks/notifications for a new best chain. - if (fInvalidFound) - CheckForkWarningConditionsOnNewFork(vpindexToConnect.back()); - else - CheckForkWarningConditions(); + CheckForkWarningConditions(); return true; } @@ -5084,7 +5007,7 @@ bool LoadMempool(CTxMemPool& pool) pool.PrioritiseTransaction(tx->GetHash(), amountdelta); } TxValidationState state; - if (nTime + nExpiryTimeout > nNow) { + if (nTime > nNow - nExpiryTimeout) { LOCK(cs_main); AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, nTime, nullptr /* plTxnReplaced */, false /* bypass_limits */, diff --git a/src/validation.h b/src/validation.h index 3d9fa92c15..ffb038ad75 100644 --- a/src/validation.h +++ b/src/validation.h @@ -503,9 +503,9 @@ enum class CoinsCacheSizeState * whereas block information and metadata independent of the current tip is * kept in `BlockMetadataManager`. */ -class CChainState { -private: - +class CChainState +{ +protected: /** * Every received block is assigned a unique and increasing identifier, so we * know which one to give priority in case of a fork. diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 17bdc06c78..6b46868d10 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1523,7 +1523,9 @@ static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue& // Need to ExpandPrivate to check if private keys are available for all pubkeys FlatSigningProvider expand_keys; std::vector<CScript> scripts; - parsed_desc->Expand(0, keys, scripts, expand_keys); + if (!parsed_desc->Expand(0, keys, scripts, expand_keys)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Cannot expand descriptor. Probably because of hardened derivations without private keys provided"); + } parsed_desc->ExpandPrivate(0, keys, expand_keys); // Check if all private keys are provided diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ebcab1227d..6efa3d0c27 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -8,6 +8,7 @@ #include <interfaces/chain.h> #include <key_io.h> #include <node/context.h> +#include <optional.h> #include <outputtype.h> #include <policy/feerate.h> #include <policy/fees.h> @@ -28,6 +29,7 @@ #include <util/translation.h> #include <util/url.h> #include <util/vector.h> +#include <validation.h> #include <wallet/coincontrol.h> #include <wallet/context.h> #include <wallet/feebumper.h> @@ -47,8 +49,6 @@ using interfaces::FoundBlock; static const std::string WALLET_ENDPOINT_BASE = "/wallet/"; static const std::string HELP_REQUIRING_PASSPHRASE{"\nRequires wallet passphrase to be set with walletpassphrase call if wallet is encrypted.\n"}; -static const uint32_t WALLET_BTC_KB_TO_SAT_B = COIN / 1000; // 1 sat / B = 0.00001 BTC / kB - static inline bool GetAvoidReuseFlag(const CWallet* const pwallet, const UniValue& param) { bool can_avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE); bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool(); @@ -198,36 +198,44 @@ static std::string LabelFromValue(const UniValue& value) /** * Update coin control with fee estimation based on the given parameters * - * @param[in] pwallet Wallet pointer - * @param[in,out] cc Coin control which is to be updated - * @param[in] estimate_mode String value (e.g. "ECONOMICAL") - * @param[in] estimate_param Parameter (blocks to confirm, explicit fee rate, etc) - * @throws a JSONRPCError if estimate_mode is unknown, or if estimate_param is missing when required + * @param[in] pwallet Wallet pointer + * @param[in,out] cc Coin control to be updated + * @param[in] conf_target UniValue integer; confirmation target in blocks, values between 1 and 1008 are valid per policy/fees.h; + * if a fee_rate is present, 0 is allowed here as a no-op positional placeholder + * @param[in] estimate_mode UniValue string; fee estimation mode, valid values are "unset", "economical" or "conservative"; + * if a fee_rate is present, "" is allowed here as a no-op positional placeholder + * @param[in] fee_rate UniValue real; fee rate in sat/vB; + * if a fee_rate is present, both conf_target and estimate_mode must either be null, or no-op + * @param[in] override_min_fee bool; whether to set fOverrideFeeRate to true to disable minimum fee rate checks and instead + * verify only that fee_rate is greater than 0 + * @throws a JSONRPCError if conf_target, estimate_mode, or fee_rate contain invalid values or are in conflict */ -static void SetFeeEstimateMode(const CWallet* pwallet, CCoinControl& cc, const UniValue& estimate_mode, const UniValue& estimate_param) +static void SetFeeEstimateMode(const CWallet* pwallet, CCoinControl& cc, const UniValue& conf_target, const UniValue& estimate_mode, const UniValue& fee_rate, bool override_min_fee) { - if (!estimate_mode.isNull()) { - if (!FeeModeFromString(estimate_mode.get_str(), cc.m_fee_mode)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); + if (!fee_rate.isNull()) { + if (!conf_target.isNull() && conf_target.get_int() > 0) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate."); } - } - - if (cc.m_fee_mode == FeeEstimateMode::BTC_KB || cc.m_fee_mode == FeeEstimateMode::SAT_B) { - if (estimate_param.isNull()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Selected estimate_mode %s requires a fee rate to be specified in conf_target", estimate_mode.get_str())); + if (!estimate_mode.isNull() && !estimate_mode.get_str().empty()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and fee_rate"); } - - CAmount fee_rate = AmountFromValue(estimate_param); - if (cc.m_fee_mode == FeeEstimateMode::SAT_B) { - fee_rate /= WALLET_BTC_KB_TO_SAT_B; + CFeeRate fee_rate_in_sat_vb{CFeeRate(AmountFromValue(fee_rate), COIN)}; + if (override_min_fee) { + if (fee_rate_in_sat_vb <= CFeeRate(0)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid fee_rate %s (must be greater than 0)", fee_rate_in_sat_vb.ToString(FeeEstimateMode::SAT_VB))); + } + cc.fOverrideFeeRate = true; } - - cc.m_feerate = CFeeRate(fee_rate); - - // default RBF to true for explicit fee rate modes + cc.m_feerate = fee_rate_in_sat_vb; + // Default RBF to true for explicit fee_rate, if unset. if (cc.m_signal_bip125_rbf == nullopt) cc.m_signal_bip125_rbf = true; - } else if (!estimate_param.isNull()) { - cc.m_confirm_target = ParseConfirmTarget(estimate_param, pwallet->chain().estimateMaxBlocks()); + return; + } + if (!estimate_mode.isNull() && !FeeModeFromString(estimate_mode.get_str(), cc.m_fee_mode)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage()); + } + if (!conf_target.isNull()) { + cc.m_confirm_target = ParseConfirmTarget(conf_target, pwallet->chain().estimateMaxBlocks()); } } @@ -440,12 +448,12 @@ static RPCHelpMan sendtoaddress() {"subtractfeefromamount", RPCArg::Type::BOOL, /* default */ "false", "The fee will be deducted from the amount being sent.\n" "The recipient will receive less bitcoins than you enter in the amount field."}, {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"}, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target (in blocks)\n" - "or fee rate (for " + CURRENCY_UNIT + "/kB and " + CURRENCY_ATOM + "/B estimate modes)"}, + {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"}, {"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n" " \"" + FeeModes("\"\n\"") + "\""}, {"avoid_reuse", RPCArg::Type::BOOL, /* default */ "true", "(only available if avoid_reuse wallet flag is set) Avoid spending from dirty addresses; addresses are considered\n" "dirty if they have previously been used in a transaction."}, + {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, {"verbose", RPCArg::Type::BOOL, /* default */ "false", "If true, return extra information about the transaction."}, }, { @@ -461,12 +469,17 @@ static RPCHelpMan sendtoaddress() }, }, RPCExamples{ - HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1") - + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"seans outpost\"") - + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" true") - + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" false true 0.00002 " + (CURRENCY_UNIT + "/kB")) - + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" false true 2 " + (CURRENCY_ATOM + "/B")) - + HelpExampleRpc("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 0.1, \"donation\", \"seans outpost\"") + "\nSend 0.1 BTC\n" + + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1") + + "\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode using positional arguments\n" + + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"sean's outpost\" false true 6 economical") + + "\nSend 0.1 BTC with a fee rate of 1 " + CURRENCY_ATOM + "/vB, subtract fee from amount, BIP125-replaceable, using positional arguments\n" + + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"drinks\" \"room77\" true true 0 \"\" 1") + + "\nSend 0.2 BTC with a confirmation target of 6 blocks in economical fee estimate mode using named arguments\n" + + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.2 conf_target=6 estimate_mode=\"economical\"") + + "\nSend 0.5 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n" + + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25") + + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25 subtractfeefromamount=false replaceable=true avoid_reuse=true comment=\"2 pizzas\" comment_to=\"jeremy\" verbose=true") }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { @@ -501,7 +514,7 @@ static RPCHelpMan sendtoaddress() // We also enable partial spend avoidance if reuse avoidance is set. coin_control.m_avoid_partial_spends |= coin_control.m_avoid_address_reuse; - SetFeeEstimateMode(pwallet, coin_control, request.params[7], request.params[6]); + SetFeeEstimateMode(pwallet, coin_control, /* conf_target */ request.params[6], /* estimate_mode */ request.params[7], /* fee_rate */ request.params[9], /* override_min_fee */ false); EnsureWalletIsUnlocked(pwallet); @@ -515,7 +528,7 @@ static RPCHelpMan sendtoaddress() std::vector<CRecipient> recipients; ParseRecipients(address_amounts, subtractFeeFromAmount, recipients); - bool verbose = request.params[9].isNull() ? false: request.params[9].get_bool(); + const bool verbose{request.params[10].isNull() ? false : request.params[10].get_bool()}; return SendMoney(pwallet, coin_control, recipients, mapValue, verbose); }, @@ -869,10 +882,10 @@ static RPCHelpMan sendmany() }, }, {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"}, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target (in blocks)\n" - "or fee rate (for " + CURRENCY_UNIT + "/kB and " + CURRENCY_ATOM + "/B estimate modes)"}, + {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"}, {"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n" " \"" + FeeModes("\"\n\"") + "\""}, + {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, {"verbose", RPCArg::Type::BOOL, /* default */ "false", "If true, return extra infomration about the transaction."}, }, { @@ -929,11 +942,11 @@ static RPCHelpMan sendmany() coin_control.m_signal_bip125_rbf = request.params[5].get_bool(); } - SetFeeEstimateMode(pwallet, coin_control, request.params[7], request.params[6]); + SetFeeEstimateMode(pwallet, coin_control, /* conf_target */ request.params[6], /* estimate_mode */ request.params[7], /* fee_rate */ request.params[8], /* override_min_fee */ false); std::vector<CRecipient> recipients; ParseRecipients(sendTo, subtractFeeFromAmount, recipients); - bool verbose = request.params[8].isNull() ? false : request.params[8].get_bool(); + const bool verbose{request.params[9].isNull() ? false : request.params[9].get_bool()}; return SendMoney(pwallet, coin_control, recipients, std::move(mapValue), verbose); }, @@ -2310,7 +2323,7 @@ static RPCHelpMan settxfee() "\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n" "Can be deactivated by passing 0 as the fee. In that case automatic fee selection will be used by default.\n", { - {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kB"}, + {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kvB"}, }, RPCResult{ RPCResult::Type::BOOL, "", "Returns true if successful" @@ -2433,7 +2446,7 @@ static RPCHelpMan getwalletinfo() {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"}, {RPCResult::Type::NUM, "keypoolsize_hd_internal", "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"}, {RPCResult::Type::NUM_TIME, "unlocked_until", /* optional */ true, "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets)"}, - {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB"}, + {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"}, {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true, "the Hash160 of the HD seed (only present when HD is enabled)"}, {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"}, {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"}, @@ -3046,7 +3059,7 @@ static RPCHelpMan listunspent() }; } -void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, const UniValue& options, CCoinControl& coinControl) +void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, const UniValue& options, CCoinControl& coinControl, bool override_min_fee) { // Make sure the results are valid at least up to the most recent block // the user could have gotten from another RPC command prior to now @@ -3079,7 +3092,8 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f {"lockUnspents", UniValueType(UniValue::VBOOL)}, {"lock_unspents", UniValueType(UniValue::VBOOL)}, {"locktime", UniValueType(UniValue::VNUM)}, - {"feeRate", UniValueType()}, // will be checked below + {"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode() + {"feeRate", UniValueType()}, // will be checked by AmountFromValue() below {"psbt", UniValueType(UniValue::VBOOL)}, {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)}, {"subtract_fee_from_outputs", UniValueType(UniValue::VARR)}, @@ -3126,15 +3140,21 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f lockUnspents = (options.exists("lock_unspents") ? options["lock_unspents"] : options["lockUnspents"]).get_bool(); } - if (options.exists("feeRate")) - { + if (options.exists("feeRate")) { + if (options.exists("fee_rate")) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both fee_rate (" + CURRENCY_ATOM + "/vB) and feeRate (" + CURRENCY_UNIT + "/kvB)"); + } if (options.exists("conf_target")) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate."); } if (options.exists("estimate_mode")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate"); } - coinControl.m_feerate = CFeeRate(AmountFromValue(options["feeRate"])); + CFeeRate fee_rate(AmountFromValue(options["feeRate"])); + if (fee_rate <= CFeeRate(0)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid feeRate %s (must be greater than 0)", fee_rate.ToString(FeeEstimateMode::BTC_KVB))); + } + coinControl.m_feerate = fee_rate; coinControl.fOverrideFeeRate = true; } @@ -3144,7 +3164,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f if (options.exists("replaceable")) { coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool(); } - SetFeeEstimateMode(pwallet, coinControl, options["estimate_mode"], options["conf_target"]); + SetFeeEstimateMode(pwallet, coinControl, options["conf_target"], options["estimate_mode"], options["fee_rate"], override_min_fee); } } else { // if options is null and not a bool @@ -3201,7 +3221,8 @@ static RPCHelpMan fundrawtransaction() "Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n" "e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."}, {"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"}, - {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"}, + {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, + {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."}, {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "The integers.\n" "The fee will be equally deducted from the amount of each specified output.\n" "Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n" @@ -3212,8 +3233,7 @@ static RPCHelpMan fundrawtransaction() }, {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n" "Allows this transaction to be replaced by a transaction with higher fees"}, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target (in blocks)\n" - "or fee rate (for " + CURRENCY_UNIT + "/kB and " + CURRENCY_ATOM + "/B estimate modes)"}, + {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"}, {"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n" " \"" + FeeModes("\"\n\"") + "\""}, }, @@ -3265,7 +3285,7 @@ static RPCHelpMan fundrawtransaction() CCoinControl coin_control; // Automatically select (additional) coins. Can be overridden by options.add_inputs. coin_control.m_add_inputs = true; - FundTransaction(pwallet, tx, fee, change_position, request.params[1], coin_control); + FundTransaction(pwallet, tx, fee, change_position, request.params[1], coin_control, /* override_min_fee */ true); UniValue result(UniValue::VOBJ); result.pushKV("hex", EncodeHexTx(CTransaction(tx))); @@ -3373,35 +3393,38 @@ RPCHelpMan signrawtransactionwithwallet() static RPCHelpMan bumpfee_helper(std::string method_name) { bool want_psbt = method_name == "psbtbumpfee"; + const std::string incremental_fee{CFeeRate(DEFAULT_MIN_RELAY_TX_FEE).ToString(FeeEstimateMode::SAT_VB)}; return RPCHelpMan{method_name, "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n" + std::string(want_psbt ? "Returns a PSBT instead of creating and signing a new transaction.\n" : "") + "An opt-in RBF transaction with the given txid must be in the wallet.\n" - "The command will pay the additional fee by reducing change outputs or adding inputs when necessary. It may add a new change output if one does not already exist.\n" + "The command will pay the additional fee by reducing change outputs or adding inputs when necessary.\n" + "It may add a new change output if one does not already exist.\n" "All inputs in the original transaction will be included in the replacement transaction.\n" "The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n" "By default, the new fee will be calculated automatically using the estimatesmartfee RPC.\n" "The user can specify a confirmation target for estimatesmartfee.\n" - "Alternatively, the user can specify a fee_rate (" + CURRENCY_UNIT + " per kB) for the new transaction.\n" + "Alternatively, the user can specify a fee rate in " + CURRENCY_ATOM + "/vB for the new transaction.\n" "At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n" - "returned by getnetworkinfo) to enter the node's mempool.\n", + "returned by getnetworkinfo) to enter the node's mempool.\n" + "* WARNING: before version 0.21, fee_rate was in " + CURRENCY_UNIT + "/kvB. As of 0.21, fee_rate is in " + CURRENCY_ATOM + "/vB. *\n", { {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid to be bumped"}, {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "", { - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target (in blocks)\n" - "or fee rate (for " + CURRENCY_UNIT + "/kB and " + CURRENCY_ATOM + "/B estimate modes)"}, - {"fee_rate", RPCArg::Type::NUM, /* default */ "fall back to 'conf_target'", "fee rate (NOT total fee) to pay, in " + CURRENCY_UNIT + "/kB.\n" - "Specify a fee rate instead of relying on the built-in fee estimator.\n" - "Must be at least 0.0001 " + CURRENCY_UNIT + "/kB higher than the current transaction fee rate.\n"}, + {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks\n"}, + {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", + "\nSpecify a fee rate in " + CURRENCY_ATOM + "/vB instead of relying on the built-in fee estimator.\n" + "Must be at least " + incremental_fee + " " + CURRENCY_ATOM + "/vB higher than the current transaction fee rate.\n" + "WARNING: before version 0.21, fee_rate was in " + CURRENCY_UNIT + "/kvB. As of 0.21, fee_rate is in " + CURRENCY_ATOM + "/vB.\n"}, {"replaceable", RPCArg::Type::BOOL, /* default */ "true", "Whether the new transaction should still be\n" "marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n" "be left unchanged from the original. If false, any input sequence numbers in the\n" "original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n" "so the new transaction will not be explicitly bip-125 replaceable (though it may\n" "still be replaceable in practice, for example if it has unconfirmed ancestors which\n" - "are replaceable)."}, + "are replaceable).\n"}, {"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n" " \"" + FeeModes("\"\n\"") + "\""}, }, @@ -3454,7 +3477,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name) { {"confTarget", UniValueType(UniValue::VNUM)}, {"conf_target", UniValueType(UniValue::VNUM)}, - {"fee_rate", UniValueType(UniValue::VNUM)}, + {"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode() {"replaceable", UniValueType(UniValue::VBOOL)}, {"estimate_mode", UniValueType(UniValue::VSTR)}, }, @@ -3466,22 +3489,10 @@ static RPCHelpMan bumpfee_helper(std::string method_name) auto conf_target = options.exists("confTarget") ? options["confTarget"] : options["conf_target"]; - if (!conf_target.isNull()) { - if (options.exists("fee_rate")) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate."); - } - } else if (options.exists("fee_rate")) { - CFeeRate fee_rate(AmountFromValue(options["fee_rate"])); - if (fee_rate <= CFeeRate(0)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid fee_rate %s (must be greater than 0)", fee_rate.ToString())); - } - coin_control.m_feerate = fee_rate; - } - if (options.exists("replaceable")) { coin_control.m_signal_bip125_rbf = options["replaceable"].get_bool(); } - SetFeeEstimateMode(pwallet, coin_control, options["estimate_mode"], conf_target); + SetFeeEstimateMode(pwallet, coin_control, conf_target, options["estimate_mode"], options["fee_rate"], /* override_min_fee */ false); } // Make sure the results are valid at least up to the most recent block @@ -3593,7 +3604,7 @@ static RPCHelpMan rescanblockchain() } int start_height = 0; - Optional<int> stop_height; + Optional<int> stop_height = MakeOptional(false, int()); uint256 start_block; { LOCK(pwallet->cs_wallet); @@ -4017,10 +4028,10 @@ static RPCHelpMan send() }, }, }, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target (in blocks)\n" - "or fee rate (for " + CURRENCY_UNIT + "/kB and " + CURRENCY_ATOM + "/B estimate modes)"}, + {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"}, {"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n" " \"" + FeeModes("\"\n\"") + "\""}, + {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "", { {"add_inputs", RPCArg::Type::BOOL, /* default */ "false", "If inputs are specified, automatically include more if they are not enough."}, @@ -4028,10 +4039,10 @@ static RPCHelpMan send() {"change_address", RPCArg::Type::STR_HEX, /* default */ "pool address", "The bitcoin address to receive the change"}, {"change_position", RPCArg::Type::NUM, /* default */ "random", "The index of the change output"}, {"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target (in blocks)\n" - "or fee rate (for " + CURRENCY_UNIT + "/kB and " + CURRENCY_ATOM + "/B estimate modes)"}, + {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"}, {"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n" " \"" + FeeModes("\"\n\"") + "\""}, + {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, {"include_watching", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Also select inputs which are watch only.\n" "Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n" "e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."}, @@ -4068,18 +4079,25 @@ static RPCHelpMan send() } }, RPCExamples{"" - "\nSend with a fee rate of 1 satoshi per byte\n" - + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 sat/b\n") + - "\nCreate a transaction that should confirm the next block, with a specific input, and return result without adding to wallet or broadcasting to the network\n" + "\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode\n" + + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 6 economical\n") + + "Send 0.2 BTC with a fee rate of 1 " + CURRENCY_ATOM + "/vB using positional arguments\n" + + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' 0 \"\" 1\n") + + "Send 0.2 BTC with a fee rate of 1 " + CURRENCY_ATOM + "/vB using the options argument\n" + + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' '{\"fee_rate\": 1}'\n") + + "Send 0.3 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n" + + HelpExampleCli("-named send", "outputs='{\"" + EXAMPLE_ADDRESS[0] + "\": 0.3}' fee_rate=25\n") + + "Create a transaction that should confirm the next block, with a specific input, and return result without adding to wallet or broadcasting to the network\n" + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 economical '{\"add_to_wallet\": false, \"inputs\": [{\"txid\":\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\", \"vout\":1}]}'") }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { RPCTypeCheck(request.params, { - UniValueType(), // ARR or OBJ, checked later - UniValue::VNUM, - UniValue::VSTR, - UniValue::VOBJ + UniValueType(), // outputs (ARR or OBJ, checked later) + UniValue::VNUM, // conf_target + UniValue::VSTR, // estimate_mode + UniValue::VNUM, // fee_rate + UniValue::VOBJ, // options }, true ); @@ -4087,18 +4105,28 @@ static RPCHelpMan send() if (!wallet) return NullUniValue; CWallet* const pwallet = wallet.get(); - UniValue options = request.params[3]; - if (options.exists("feeRate") || options.exists("fee_rate") || options.exists("estimate_mode") || options.exists("conf_target")) { + UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]}; + if (options.exists("conf_target") || options.exists("estimate_mode")) { if (!request.params[1].isNull() || !request.params[2].isNull()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Use either conf_target and estimate_mode or the options dictionary to control fee rate"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Pass conf_target and estimate_mode either as arguments or in the options object, but not both"); } } else { options.pushKV("conf_target", request.params[1]); options.pushKV("estimate_mode", request.params[2]); } + if (options.exists("fee_rate")) { + if (!request.params[3].isNull()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Pass the fee_rate either as an argument, or in the options object, but not both"); + } + } else { + options.pushKV("fee_rate", request.params[3]); + } if (!options["conf_target"].isNull() && (options["estimate_mode"].isNull() || (options["estimate_mode"].get_str() == "unset"))) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Specify estimate_mode"); } + if (options.exists("feeRate")) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Use fee_rate (" + CURRENCY_ATOM + "/vB) instead of feeRate"); + } if (options.exists("changeAddress")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Use change_address"); } @@ -4128,7 +4156,7 @@ static RPCHelpMan send() // Automatically select coins, unless at least one is manually selected. Can // be overridden by options.add_inputs. coin_control.m_add_inputs = rawTx.vin.size() == 0; - FundTransaction(pwallet, rawTx, fee, change_position, options, coin_control); + FundTransaction(pwallet, rawTx, fee, change_position, options, coin_control, /* override_min_fee */ false); bool add_to_wallet = true; if (options.exists("add_to_wallet")) { @@ -4356,7 +4384,8 @@ static RPCHelpMan walletcreatefundedpsbt() {"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, {"includeWatching", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Also select inputs which are watch only"}, {"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"}, - {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"}, + {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, + {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."}, {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "The outputs to subtract the fee from.\n" "The fee will be equally deducted from the amount of each specified output.\n" "Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n" @@ -4367,8 +4396,7 @@ static RPCHelpMan walletcreatefundedpsbt() }, {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n" "Allows this transaction to be replaced by a transaction with higher fees"}, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target (in blocks)\n" - "or fee rate (for " + CURRENCY_UNIT + "/kB and " + CURRENCY_ATOM + "/B estimate modes)"}, + {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"}, {"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n" " \"" + FeeModes("\"\n\"") + "\""}, }, @@ -4415,7 +4443,7 @@ static RPCHelpMan walletcreatefundedpsbt() // Automatically select coins, unless at least one is manually selected. Can // be overridden by options.add_inputs. coin_control.m_add_inputs = rawTx.vin.size() == 0; - FundTransaction(pwallet, rawTx, fee, change_position, request.params[3], coin_control); + FundTransaction(pwallet, rawTx, fee, change_position, request.params[3], coin_control, /* override_min_fee */ true); // Make a blank psbt PartiallySignedTransaction psbtx(rawTx); @@ -4473,10 +4501,8 @@ static RPCHelpMan upgradewallet() if (!request.params[0].isNull()) { version = request.params[0].get_int(); } - bilingual_str error; - std::vector<bilingual_str> warnings; - if (!pwallet->UpgradeWallet(version, error, warnings)) { + if (!pwallet->UpgradeWallet(version, error)) { throw JSONRPCError(RPC_WALLET_ERROR, error.original); } UniValue obj(UniValue::VOBJ); @@ -4550,9 +4576,9 @@ static const CRPCCommand commands[] = { "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} }, { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} }, { "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} }, - { "wallet", "send", &send, {"outputs","conf_target","estimate_mode","options"} }, - { "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode","verbose"} }, - { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse","verbose"} }, + { "wallet", "send", &send, {"outputs","conf_target","estimate_mode","fee_rate","options"} }, + { "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode","fee_rate","verbose"} }, + { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse","fee_rate","verbose"} }, { "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} }, { "wallet", "setlabel", &setlabel, {"address","label"} }, { "wallet", "settxfee", &settxfee, {"amount"} }, diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index 188289b010..d2e1be6402 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -438,12 +438,12 @@ bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal) const return keypool_has_keys; } -bool LegacyScriptPubKeyMan::Upgrade(int prev_version, bilingual_str& error) +bool LegacyScriptPubKeyMan::Upgrade(int prev_version, int new_version, bilingual_str& error) { LOCK(cs_KeyStore); bool hd_upgrade = false; bool split_upgrade = false; - if (m_storage.CanSupportFeature(FEATURE_HD) && !IsHDEnabled()) { + if (IsFeatureSupported(new_version, FEATURE_HD) && !IsHDEnabled()) { WalletLogPrintf("Upgrading wallet to HD\n"); m_storage.SetMinVersion(FEATURE_HD); @@ -453,10 +453,17 @@ bool LegacyScriptPubKeyMan::Upgrade(int prev_version, bilingual_str& error) hd_upgrade = true; } // Upgrade to HD chain split if necessary - if (m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) { + if (IsFeatureSupported(new_version, FEATURE_HD_SPLIT)) { WalletLogPrintf("Upgrading wallet to use HD chain split\n"); m_storage.SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL); split_upgrade = FEATURE_HD_SPLIT > prev_version; + // Upgrade the HDChain + if (m_hd_chain.nVersion < CHDChain::VERSION_HD_CHAIN_SPLIT) { + m_hd_chain.nVersion = CHDChain::VERSION_HD_CHAIN_SPLIT; + if (!WalletBatch(m_storage.GetDatabase()).WriteHDChain(m_hd_chain)) { + throw std::runtime_error(std::string(__func__) + ": writing chain failed"); + } + } } // Mark all keys currently in the keypool as pre-split if (split_upgrade) { diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index 63c10b7a0d..3bf8f78120 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -37,7 +37,7 @@ public: virtual bool IsWalletFlagSet(uint64_t) const = 0; virtual void UnsetBlankWalletFlag(WalletBatch&) = 0; virtual bool CanSupportFeature(enum WalletFeature) const = 0; - virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr, bool = false) = 0; + virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr) = 0; virtual const CKeyingMaterial& GetEncryptionKey() const = 0; virtual bool HasEncryptionKeys() const = 0; virtual bool IsLocked() const = 0; @@ -206,7 +206,7 @@ public: virtual bool CanGetAddresses(bool internal = false) const { return false; } /** Upgrades the wallet to the specified version */ - virtual bool Upgrade(int prev_version, bilingual_str& error) { return false; } + virtual bool Upgrade(int prev_version, int new_version, bilingual_str& error) { return false; } virtual bool HavePrivateKeys() const { return false; } @@ -371,7 +371,7 @@ public: bool SetupGeneration(bool force = false) override; - bool Upgrade(int prev_version, bilingual_str& error) override; + bool Upgrade(int prev_version, int new_version, bilingual_str& error) override; bool HavePrivateKeys() const override; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index c42114c394..4911af08c6 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -688,7 +688,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup) BOOST_CHECK_EXCEPTION(vr >> w_desc, std::ios_base::failure, malformed_descriptor); } -//! Test CreateWalletFromFile function and its behavior handling potential race +//! Test CWallet::Create() and its behavior handling potential race //! conditions if it's called the same time an incoming transaction shows up in //! the mempool or a new block. //! @@ -706,7 +706,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup) //! wallet rescan and notifications are immediately synced, to verify the wallet //! must already have a handler in place for them, and there's no gap after //! rescanning where new transactions in new blocks could be lost. -BOOST_FIXTURE_TEST_CASE(CreateWalletFromFile, TestChain100Setup) +BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup) { // Create new wallet with known key and unload it. auto chain = interfaces::MakeChain(m_node); diff --git a/src/wallet/test/walletdb_tests.cpp b/src/wallet/test/walletdb_tests.cpp new file mode 100644 index 0000000000..a3859e2e4b --- /dev/null +++ b/src/wallet/test/walletdb_tests.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2012-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/util/setup_common.h> +#include <clientversion.h> +#include <streams.h> +#include <uint256.h> + +#include <boost/test/unit_test.hpp> + +BOOST_FIXTURE_TEST_SUITE(walletdb_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(walletdb_readkeyvalue) +{ + /** + * When ReadKeyValue() reads from either a "key" or "wkey" it first reads the CDataStream steam into a + * CPrivKey or CWalletKey respectively and then reads a hash of the pubkey and privkey into a uint256. + * Wallets from 0.8 or before do not store the pubkey/privkey hash, trying to read the hash from old + * wallets throws an exception, for backwards compatibility this read is wrapped in a try block to + * silently fail. The test here makes sure the type of exception thrown from CDataStream::read() + * matches the type we expect, otherwise we need to update the "key"/"wkey" exception type caught. + */ + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + uint256 dummy; + BOOST_CHECK_THROW(ssValue >> dummy, std::ios_base::failure); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index bdc9e4fb56..ff8bfff872 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -436,21 +436,13 @@ void CWallet::chainStateFlushed(const CBlockLocator& loc) batch.WriteBestBlock(loc); } -void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit) +void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in) { LOCK(cs_wallet); if (nWalletVersion >= nVersion) return; - - // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way - if (fExplicit && nVersion > nWalletMaxVersion) - nVersion = FEATURE_LATEST; - nWalletVersion = nVersion; - if (nVersion > nWalletMaxVersion) - nWalletMaxVersion = nVersion; - { WalletBatch* batch = batch_in ? batch_in : new WalletBatch(*database); if (nWalletVersion > 40000) @@ -460,18 +452,6 @@ void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, } } -bool CWallet::SetMaxVersion(int nVersion) -{ - LOCK(cs_wallet); - // cannot downgrade below current version - if (nWalletVersion > nVersion) - return false; - - nWalletMaxVersion = nVersion; - - return true; -} - std::set<uint256> CWallet::GetConflicts(const uint256& txid) const { std::set<uint256> result; @@ -656,7 +636,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) } // Encryption was introduced in version 0.4.0 - SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch, true); + SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch); if (!encrypted_batch->TxnCommit()) { delete encrypted_batch; @@ -1778,7 +1758,11 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc double progress_current = progress_begin; int block_height = start_height; while (!fAbortRescan && !chain().shutdownRequested()) { - m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin); + if (progress_end - progress_begin > 0.0) { + m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin); + } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal) + m_scanning_progress = 0; + } if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) { ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100)))); } @@ -2834,7 +2818,7 @@ bool CWallet::CreateTransactionInternal( // Do not, ever, assume that it's fine to change the fee rate if the user has explicitly // provided one if (coin_control.m_feerate && nFeeRateNeeded > *coin_control.m_feerate) { - error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(), nFeeRateNeeded.ToString()); + error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), nFeeRateNeeded.ToString(FeeEstimateMode::SAT_VB)); return false; } @@ -3106,10 +3090,10 @@ bool CWallet::CreateTransactionInternal( WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n", nFeeRet, nBytes, nFeeNeeded, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay, feeCalc.est.pass.start, feeCalc.est.pass.end, - 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool), + (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) > 0.0 ? 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) : 0.0, feeCalc.est.pass.withinTarget, feeCalc.est.pass.totalConfirmed, feeCalc.est.pass.inMempool, feeCalc.est.pass.leftMempool, feeCalc.est.fail.start, feeCalc.est.fail.end, - 100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool), + (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) > 0.0 ? 100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) : 0.0, feeCalc.est.fail.withinTarget, feeCalc.est.fail.totalConfirmed, feeCalc.est.fail.inMempool, feeCalc.est.fail.leftMempool); return true; } @@ -4118,36 +4102,34 @@ const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest return &address_book_it->second; } -bool CWallet::UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings) +bool CWallet::UpgradeWallet(int version, bilingual_str& error) { int prev_version = GetVersion(); - int nMaxVersion = version; - if (nMaxVersion == 0) // the -upgradewallet without argument case - { + if (version == 0) { WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST); - nMaxVersion = FEATURE_LATEST; - SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately + version = FEATURE_LATEST; } else { - WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); + WalletLogPrintf("Allowing wallet upgrade up to %i\n", version); } - if (nMaxVersion < GetVersion()) + if (version < prev_version) { error = _("Cannot downgrade wallet"); 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) { + if (!CanSupportFeature(FEATURE_HD_SPLIT) && version >= FEATURE_HD_SPLIT && 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."); return false; } + // Permanently upgrade to the version + SetMinVersion(GetClosestWalletFeature(version)); + for (auto spk_man : GetActiveScriptPubKeyMans()) { - if (!spk_man->Upgrade(prev_version, error)) { + if (!spk_man->Upgrade(prev_version, version, error)) { return false; } } @@ -4556,7 +4538,10 @@ ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const Flat } // Top up key pool, the manager will generate new scriptPubKeys internally - new_spk_man->TopUp(); + if (!new_spk_man->TopUp()) { + WalletLogPrintf("Could not top up scriptPubKeys\n"); + return nullptr; + } // Apply the label if necessary // Note: we disable labels for ranged descriptors diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 00e0e3c84d..69cf6b66a4 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -636,9 +636,6 @@ private: //! the current wallet version: clients below this version are not able to load the wallet int nWalletVersion GUARDED_BY(cs_wallet){FEATURE_BASE}; - //! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded - int nWalletMaxVersion GUARDED_BY(cs_wallet) = FEATURE_BASE; - int64_t nNextResend = 0; bool fBroadcastTransactions = false; // Local time that the tip block was received. Used to schedule wallet rebroadcasts. @@ -800,8 +797,8 @@ public: const CWalletTx* GetWalletTx(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool IsTrusted(const CWalletTx& wtx, std::set<uint256>& trusted_parents) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - //! check whether we are allowed to upgrade (or already support) to the named feature - bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } + //! check whether we support the named feature + bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return IsFeatureSupported(nWalletVersion, wf); } /** * populate vCoins with vector of available COutputs. @@ -853,7 +850,7 @@ public: //! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; } + bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; return true; } /** * Adds a destination data tuple to the store, and saves it to disk @@ -1076,11 +1073,8 @@ public: unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - //! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower - void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr, bool fExplicit = false) override; - - //! change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format) - bool SetMaxVersion(int nVersion); + //! signify that a particular wallet feature is now used. + void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr) override; //! get the current wallet format (the oldest client version guaranteed to understand this wallet) int GetVersion() const { LOCK(cs_wallet); return nWalletVersion; } @@ -1201,7 +1195,7 @@ public: }; /** Upgrade the wallet */ - bool UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings); + bool UpgradeWallet(int version, bilingual_str& error); //! Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers std::set<ScriptPubKeyMan*> GetActiveScriptPubKeyMans() const; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index aa3b3c10b0..5d3fbd3431 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -362,7 +362,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, { ssValue >> hash; } - catch (...) {} + catch (const std::ios_base::failure&) {} bool fSkipCheck = false; diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index 2f3e597b90..702293e6c7 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -49,28 +49,51 @@ std::vector<fs::path> ListWalletDir() continue; } - // Get wallet path relative to walletdir by removing walletdir from the wallet path. - // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60. - const fs::path path = it->path().string().substr(offset); + try { + // Get wallet path relative to walletdir by removing walletdir from the wallet path. + // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60. + const fs::path path = it->path().string().substr(offset); - if (it->status().type() == fs::directory_file && - (ExistsBerkeleyDatabase(it->path()) || ExistsSQLiteDatabase(it->path()))) { - // Found a directory which contains wallet.dat btree file, add it as a wallet. - paths.emplace_back(path); - } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && ExistsBerkeleyDatabase(it->path())) { - if (it->path().filename() == "wallet.dat") { - // Found top-level wallet.dat btree file, add top level directory "" - // as a wallet. - paths.emplace_back(); - } else { - // Found top-level btree file not called wallet.dat. Current bitcoin - // software will never create these files but will allow them to be - // opened in a shared database environment for backwards compatibility. - // Add it to the list of available wallets. + if (it->status().type() == fs::directory_file && + (ExistsBerkeleyDatabase(it->path()) || ExistsSQLiteDatabase(it->path()))) { + // Found a directory which contains wallet.dat btree file, add it as a wallet. paths.emplace_back(path); + } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && ExistsBerkeleyDatabase(it->path())) { + if (it->path().filename() == "wallet.dat") { + // Found top-level wallet.dat btree file, add top level directory "" + // as a wallet. + paths.emplace_back(); + } else { + // Found top-level btree file not called wallet.dat. Current bitcoin + // software will never create these files but will allow them to be + // opened in a shared database environment for backwards compatibility. + // Add it to the list of available wallets. + paths.emplace_back(path); + } } + } catch (const std::exception& e) { + LogPrintf("%s: Error scanning %s: %s\n", __func__, it->path().string(), e.what()); + it.no_push(); } } return paths; } + +bool IsFeatureSupported(int wallet_version, int feature_version) +{ + return wallet_version >= feature_version; +} + +WalletFeature GetClosestWalletFeature(int version) +{ + if (version >= FEATURE_LATEST) return FEATURE_LATEST; + if (version >= FEATURE_PRE_SPLIT_KEYPOOL) return FEATURE_PRE_SPLIT_KEYPOOL; + if (version >= FEATURE_NO_DEFAULT_KEY) return FEATURE_NO_DEFAULT_KEY; + if (version >= FEATURE_HD_SPLIT) return FEATURE_HD_SPLIT; + if (version >= FEATURE_HD) return FEATURE_HD; + if (version >= FEATURE_COMPRPUBKEY) return FEATURE_COMPRPUBKEY; + if (version >= FEATURE_WALLETCRYPT) return FEATURE_WALLETCRYPT; + if (version >= FEATURE_BASE) return FEATURE_BASE; + return static_cast<WalletFeature>(0); +} diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h index afdcb2e18a..27521abd81 100644 --- a/src/wallet/walletutil.h +++ b/src/wallet/walletutil.h @@ -29,7 +29,8 @@ enum WalletFeature FEATURE_LATEST = FEATURE_PRE_SPLIT_KEYPOOL }; - +bool IsFeatureSupported(int wallet_version, int feature_version); +WalletFeature GetClosestWalletFeature(int version); enum WalletFlags : uint64_t { // wallet flags in the upper section (> 1 << 31) will lead to not opening the wallet if flag is unknown diff --git a/src/warnings.cpp b/src/warnings.cpp index 501bf7e637..1dec663a73 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -14,7 +14,6 @@ static Mutex g_warnings_mutex; static bilingual_str g_misc_warnings GUARDED_BY(g_warnings_mutex); -static bool fLargeWorkForkFound GUARDED_BY(g_warnings_mutex) = false; static bool fLargeWorkInvalidChainFound GUARDED_BY(g_warnings_mutex) = false; void SetMiscWarning(const bilingual_str& warning) @@ -23,18 +22,6 @@ void SetMiscWarning(const bilingual_str& warning) g_misc_warnings = warning; } -void SetfLargeWorkForkFound(bool flag) -{ - LOCK(g_warnings_mutex); - fLargeWorkForkFound = flag; -} - -bool GetfLargeWorkForkFound() -{ - LOCK(g_warnings_mutex); - return fLargeWorkForkFound; -} - void SetfLargeWorkInvalidChainFound(bool flag) { LOCK(g_warnings_mutex); @@ -60,10 +47,7 @@ bilingual_str GetWarnings(bool verbose) warnings_verbose.emplace_back(warnings_concise); } - if (fLargeWorkForkFound) { - warnings_concise = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); - warnings_verbose.emplace_back(warnings_concise); - } else if (fLargeWorkInvalidChainFound) { + if (fLargeWorkInvalidChainFound) { warnings_concise = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); warnings_verbose.emplace_back(warnings_concise); } diff --git a/src/warnings.h b/src/warnings.h index 28546eb753..e87b64a86d 100644 --- a/src/warnings.h +++ b/src/warnings.h @@ -11,8 +11,6 @@ struct bilingual_str; void SetMiscWarning(const bilingual_str& warning); -void SetfLargeWorkForkFound(bool flag); -bool GetfLargeWorkForkFound(); void SetfLargeWorkInvalidChainFound(bool flag); /** Format a string that describes several potential problems detected by the core. * @param[in] verbose bool diff --git a/test/functional/README.md b/test/functional/README.md index 82b30fed51..2764acbf18 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -34,7 +34,7 @@ don't have test cases for. - When subclassing the BitcoinTestFramework, place overrides for the `set_test_params()`, `add_options()` and `setup_xxxx()` methods at the top of the subclass, then locally-defined helper methods, then the `run_test()` method. -- Use `'{}'.format(x)` for string formatting, not `'%s' % x`. +- Use `f'{x}'` for string formatting in preference to `'{}'.format(x)` or `'%s' % x`. #### Naming guidelines diff --git a/test/functional/data/wallets/high_minversion/.walletlock b/test/functional/data/wallets/high_minversion/.walletlock deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/functional/data/wallets/high_minversion/.walletlock +++ /dev/null diff --git a/test/functional/data/wallets/high_minversion/GENERATE.md b/test/functional/data/wallets/high_minversion/GENERATE.md deleted file mode 100644 index e55c4557ca..0000000000 --- a/test/functional/data/wallets/high_minversion/GENERATE.md +++ /dev/null @@ -1,8 +0,0 @@ -The wallet has been created by starting Bitcoin Core with the options -`-regtest -datadir=/tmp -nowallet -walletdir=$(pwd)/test/functional/data/wallets/`. - -In the source code, `WalletFeature::FEATURE_LATEST` has been modified to be large, so that the minversion is too high -for a current build of the wallet. - -The wallet has then been created with the RPC `createwallet high_minversion true true`, so that a blank wallet with -private keys disabled is created. diff --git a/test/functional/data/wallets/high_minversion/db.log b/test/functional/data/wallets/high_minversion/db.log deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/functional/data/wallets/high_minversion/db.log +++ /dev/null diff --git a/test/functional/data/wallets/high_minversion/wallet.dat b/test/functional/data/wallets/high_minversion/wallet.dat Binary files differdeleted file mode 100644 index 99ab809263..0000000000 --- a/test/functional/data/wallets/high_minversion/wallet.dat +++ /dev/null diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index 3cf7f3890c..158efb52c9 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -119,7 +119,7 @@ class FullBlockTest(BitcoinTestFramework): # Allow the block to mature blocks = [] for i in range(NUM_BUFFER_BLOCKS_TO_GENERATE): - blocks.append(self.next_block("maturitybuffer.{}".format(i))) + blocks.append(self.next_block(f"maturitybuffer.{i}")) self.save_spendable_output() self.send_blocks(blocks) @@ -151,8 +151,8 @@ class FullBlockTest(BitcoinTestFramework): if template.valid_in_block: continue - self.log.info("Reject block with invalid tx: %s", TxTemplate.__name__) - blockname = "for_invalid.%s" % TxTemplate.__name__ + self.log.info(f"Reject block with invalid tx: {TxTemplate.__name__}") + blockname = f"for_invalid.{TxTemplate.__name__}" badblock = self.next_block(blockname) badtx = template.get_tx() if TxTemplate != invalid_txs.InputMissing: @@ -1355,12 +1355,12 @@ class FullBlockTest(BitcoinTestFramework): # save the current tip so it can be spent by a later block def save_spendable_output(self): - self.log.debug("saving spendable output %s" % self.tip.vtx[0]) + self.log.debug(f"saving spendable output {self.tip.vtx[0]}") self.spendable_outputs.append(self.tip) # get an output that we previously marked as spendable def get_spendable_output(self): - self.log.debug("getting spendable output %s" % self.spendable_outputs[0].vtx[0]) + self.log.debug(f"getting spendable output {self.spendable_outputs[0].vtx[0]}") return self.spendable_outputs.pop(0).vtx[0] # move the tip back to a previous block diff --git a/test/functional/p2p_fingerprint.py b/test/functional/p2p_fingerprint.py index aaf862e6c8..f60eba2dbf 100755 --- a/test/functional/p2p_fingerprint.py +++ b/test/functional/p2p_fingerprint.py @@ -18,6 +18,7 @@ from test_framework.p2p import ( msg_block, msg_getdata, msg_getheaders, + p2p_lock, ) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( @@ -57,18 +58,6 @@ class P2PFingerprintTest(BitcoinTestFramework): msg.hashstop = block_hash node.send_message(msg) - # Check whether last block received from node has a given hash - def last_block_equals(self, expected_hash, node): - block_msg = node.last_message.get("block") - return block_msg and block_msg.block.rehash() == expected_hash - - # Check whether last block header received from node has a given hash - def last_header_equals(self, expected_hash, node): - headers_msg = node.last_message.get("headers") - return (headers_msg and - headers_msg.headers and - headers_msg.headers[0].rehash() == expected_hash) - # Checks that stale blocks timestamped more than a month ago are not served # by the node while recent stale blocks and old active chain blocks are. # This does not currently test that stale blocks timestamped within the @@ -101,34 +90,31 @@ class P2PFingerprintTest(BitcoinTestFramework): # Check that getdata request for stale block succeeds self.send_block_request(stale_hash, node0) - test_function = lambda: self.last_block_equals(stale_hash, node0) - self.wait_until(test_function, timeout=3) + node0.wait_for_block(stale_hash, timeout=3) # Check that getheader request for stale block header succeeds self.send_header_request(stale_hash, node0) - test_function = lambda: self.last_header_equals(stale_hash, node0) - self.wait_until(test_function, timeout=3) + node0.wait_for_header(hex(stale_hash), timeout=3) # Longest chain is extended so stale is much older than chain tip self.nodes[0].setmocktime(0) - tip = self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)[0] + self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address) assert_equal(self.nodes[0].getblockcount(), 14) - - # Send getdata & getheaders to refresh last received getheader message - block_hash = int(tip, 16) - self.send_block_request(block_hash, node0) - self.send_header_request(block_hash, node0) node0.sync_with_ping() # Request for very old stale block should now fail + with p2p_lock: + node0.last_message.pop("block", None) self.send_block_request(stale_hash, node0) - time.sleep(3) - assert not self.last_block_equals(stale_hash, node0) + node0.sync_with_ping() + assert "block" not in node0.last_message # Request for very old stale block header should now fail + with p2p_lock: + node0.last_message.pop("headers", None) self.send_header_request(stale_hash, node0) - time.sleep(3) - assert not self.last_header_equals(stale_hash, node0) + node0.sync_with_ping() + assert "headers" not in node0.last_message # Verify we can fetch very old blocks and headers on the active chain block_hash = int(block_hashes[2], 16) @@ -137,12 +123,10 @@ class P2PFingerprintTest(BitcoinTestFramework): node0.sync_with_ping() self.send_block_request(block_hash, node0) - test_function = lambda: self.last_block_equals(block_hash, node0) - self.wait_until(test_function, timeout=3) + node0.wait_for_block(block_hash, timeout=3) self.send_header_request(block_hash, node0) - test_function = lambda: self.last_header_equals(block_hash, node0) - self.wait_until(test_function, timeout=3) + node0.wait_for_header(hex(block_hash), timeout=3) if __name__ == '__main__': P2PFingerprintTest().main() diff --git a/test/functional/rpc_estimatefee.py b/test/functional/rpc_estimatefee.py index 1fff9e1512..3b76c7dd1e 100755 --- a/test/functional/rpc_estimatefee.py +++ b/test/functional/rpc_estimatefee.py @@ -28,7 +28,7 @@ class EstimateFeeTest(BitcoinTestFramework): # wrong type for estimatesmartfee(estimate_mode) assert_raises_rpc_error(-3, "Expected type string, got number", self.nodes[0].estimatesmartfee, 1, 1) - assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", self.nodes[0].estimatesmartfee, 1, 'foo') + assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"', self.nodes[0].estimatesmartfee, 1, 'foo') # wrong type for estimaterawfee(threshold) assert_raises_rpc_error(-3, "Expected type number, got string", self.nodes[0].estimaterawfee, 1, 'foo') diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index 503993162b..f987867e61 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -90,7 +90,6 @@ class RawTransactionsTest(BitcoinTestFramework): self.test_op_return() self.test_watchonly() self.test_all_watched_funds() - self.test_feerate_with_conf_target_and_estimate_mode() self.test_option_feerate() self.test_address_reuse() self.test_option_subtract_fee_from_outputs() @@ -708,74 +707,86 @@ class RawTransactionsTest(BitcoinTestFramework): wwatch.unloadwallet() def test_option_feerate(self): - self.log.info("Test fundrawtxn feeRate option") - - # Make sure there is exactly one input so coin selection can't skew the result. - assert_equal(len(self.nodes[3].listunspent(1)), 1) - - inputs = [] - outputs = {self.nodes[3].getnewaddress() : 1} - rawtx = self.nodes[3].createrawtransaction(inputs, outputs) - result = self.nodes[3].fundrawtransaction(rawtx) # uses self.min_relay_tx_fee (set by settxfee) - result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee}) - result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10 * self.min_relay_tx_fee}) - assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[3].fundrawtransaction, rawtx, {"feeRate": 1}) - result_fee_rate = result['fee'] * 1000 / count_bytes(result['hex']) - assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate) - assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) - - def test_feerate_with_conf_target_and_estimate_mode(self): - self.log.info("Test fundrawtxn passing an explicit fee rate using conf_target and estimate_mode") + self.log.info("Test fundrawtxn with explicit fee rates (fee_rate sat/vB and feeRate BTC/kvB)") node = self.nodes[3] # Make sure there is exactly one input so coin selection can't skew the result. - assert_equal(len(node.listunspent(1)), 1) + assert_equal(len(self.nodes[3].listunspent(1)), 1) inputs = [] outputs = {node.getnewaddress() : 1} rawtx = node.createrawtransaction(inputs, outputs) - for unit, fee_rate in {"btc/kb": 0.1, "sat/b": 10000}.items(): - self.log.info("Test fundrawtxn with conf_target {} estimate_mode {} produces expected fee".format(fee_rate, unit)) - # With no arguments passed, expect fee of 141 sats/b. - assert_approx(node.fundrawtransaction(rawtx)["fee"], vexp=0.00000141, vspan=0.00000001) - # Expect fee to be 10,000x higher when explicit fee 10,000x greater is specified. - result = node.fundrawtransaction(rawtx, {"conf_target": fee_rate, "estimate_mode": unit}) - assert_approx(result["fee"], vexp=0.0141, vspan=0.0001) + result = node.fundrawtransaction(rawtx) # uses self.min_relay_tx_fee (set by settxfee) + btc_kvb_to_sat_vb = 100000 # (1e5) + result1 = node.fundrawtransaction(rawtx, {"fee_rate": 2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee}) + result2 = node.fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee}) + result3 = node.fundrawtransaction(rawtx, {"fee_rate": 10 * btc_kvb_to_sat_vb * self.min_relay_tx_fee}) + result4 = node.fundrawtransaction(rawtx, {"feeRate": 10 * self.min_relay_tx_fee}) + result_fee_rate = result['fee'] * 1000 / count_bytes(result['hex']) + assert_fee_amount(result1['fee'], count_bytes(result2['hex']), 2 * result_fee_rate) + assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate) + assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) + assert_fee_amount(result4['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) - for field, fee_rate in {"conf_target": 0.1, "estimate_mode": "sat/b"}.items(): - self.log.info("Test fundrawtxn raises RPC error if both feeRate and {} are passed".format(field)) - assert_raises_rpc_error( - -8, "Cannot specify both {} and feeRate".format(field), - lambda: node.fundrawtransaction(rawtx, {"feeRate": 0.1, field: fee_rate})) + # With no arguments passed, expect fee of 141 satoshis. + assert_approx(node.fundrawtransaction(rawtx)["fee"], vexp=0.00000141, vspan=0.00000001) + # Expect fee to be 10,000x higher when an explicit fee rate 10,000x greater is specified. + result = node.fundrawtransaction(rawtx, {"fee_rate": 10000}) + assert_approx(result["fee"], vexp=0.0141, vspan=0.0001) self.log.info("Test fundrawtxn with invalid estimate_mode settings") for k, v in {"number": 42, "object": {"foo": "bar"}}.items(): assert_raises_rpc_error(-3, "Expected type string for estimate_mode, got {}".format(k), - lambda: self.nodes[1].fundrawtransaction(rawtx, {"estimate_mode": v, "conf_target": 0.1})) - for mode in ["foo", Decimal("3.141592")]: - assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", - lambda: self.nodes[1].fundrawtransaction(rawtx, {"estimate_mode": mode, "conf_target": 0.1})) + node.fundrawtransaction, rawtx, {"estimate_mode": v, "conf_target": 0.1, "add_inputs": True}) + for mode in ["", "foo", Decimal("3.141592")]: + assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"', + node.fundrawtransaction, rawtx, {"estimate_mode": mode, "conf_target": 0.1, "add_inputs": True}) self.log.info("Test fundrawtxn with invalid conf_target settings") - for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]: + for mode in ["unset", "economical", "conservative"]: self.log.debug("{}".format(mode)) for k, v in {"string": "", "object": {"foo": "bar"}}.items(): assert_raises_rpc_error(-3, "Expected type number for conf_target, got {}".format(k), - lambda: self.nodes[1].fundrawtransaction(rawtx, {"estimate_mode": mode, "conf_target": v})) - if mode in ["btc/kb", "sat/b"]: - assert_raises_rpc_error(-3, "Amount out of range", - lambda: self.nodes[1].fundrawtransaction(rawtx, {"estimate_mode": mode, "conf_target": -1})) - assert_raises_rpc_error(-4, "Fee rate (0.00000000 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", - lambda: self.nodes[1].fundrawtransaction(rawtx, {"estimate_mode": mode, "conf_target": 0})) - else: - for n in [-1, 0, 1009]: - assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", - lambda: self.nodes[1].fundrawtransaction(rawtx, {"estimate_mode": mode, "conf_target": n})) - - for unit, fee_rate in {"sat/B": 0.99999999, "BTC/kB": 0.00000999}.items(): - self.log.info("- raises RPC error 'fee rate too low' if conf_target {} and estimate_mode {} are passed".format(fee_rate, unit)) - assert_raises_rpc_error(-4, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", - lambda: self.nodes[1].fundrawtransaction(rawtx, {"estimate_mode": unit, "conf_target": fee_rate, "add_inputs": True})) - + node.fundrawtransaction, rawtx, {"estimate_mode": mode, "conf_target": v, "add_inputs": True}) + for n in [-1, 0, 1009]: + assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h + node.fundrawtransaction, rawtx, {"estimate_mode": mode, "conf_target": n, "add_inputs": True}) + + self.log.info("Test invalid fee rate settings") + assert_raises_rpc_error(-8, "Invalid fee_rate 0.000 sat/vB (must be greater than 0)", + node.fundrawtransaction, rawtx, {"fee_rate": 0, "add_inputs": True}) + assert_raises_rpc_error(-8, "Invalid feeRate 0.00000000 BTC/kvB (must be greater than 0)", + node.fundrawtransaction, rawtx, {"feeRate": 0, "add_inputs": True}) + for param, value in {("fee_rate", 100000), ("feeRate", 1.000)}: + assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", + node.fundrawtransaction, rawtx, {param: value, "add_inputs": True}) + assert_raises_rpc_error(-3, "Amount out of range", + node.fundrawtransaction, rawtx, {"fee_rate": -1, "add_inputs": True}) + assert_raises_rpc_error(-3, "Amount is not a number or string", + node.fundrawtransaction, rawtx, {"fee_rate": {"foo": "bar"}, "add_inputs": True}) + assert_raises_rpc_error(-3, "Invalid amount", + node.fundrawtransaction, rawtx, {"fee_rate": "", "add_inputs": True}) + + self.log.info("Test min fee rate checks are bypassed with fundrawtxn, e.g. a fee_rate under 1 sat/vB is allowed") + node.fundrawtransaction(rawtx, {"fee_rate": 0.99999999, "add_inputs": True}) + node.fundrawtransaction(rawtx, {"feeRate": 0.00000999, "add_inputs": True}) + + self.log.info("- raises RPC error if both feeRate and fee_rate are passed") + assert_raises_rpc_error(-8, "Cannot specify both fee_rate (sat/vB) and feeRate (BTC/kvB)", + node.fundrawtransaction, rawtx, {"fee_rate": 0.1, "feeRate": 0.1, "add_inputs": True}) + + self.log.info("- raises RPC error if both feeRate and estimate_mode passed") + assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and feeRate", + node.fundrawtransaction, rawtx, {"estimate_mode": "economical", "feeRate": 0.1, "add_inputs": True}) + + for param in ["feeRate", "fee_rate"]: + self.log.info("- raises RPC error if both {} and conf_target are passed".format(param)) + assert_raises_rpc_error(-8, "Cannot specify both conf_target and {}. Please provide either a confirmation " + "target in blocks for automatic fee estimation, or an explicit fee rate.".format(param), + node.fundrawtransaction, rawtx, {param: 1, "conf_target": 1, "add_inputs": True}) + + self.log.info("- raises RPC error if both fee_rate and estimate_mode are passed") + assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate", + node.fundrawtransaction, rawtx, {"fee_rate": 1, "estimate_mode": "economical", "add_inputs": True}) def test_address_reuse(self): """Test no address reuse occurs.""" @@ -803,12 +814,32 @@ class RawTransactionsTest(BitcoinTestFramework): outputs = {self.nodes[2].getnewaddress(): 1} rawtx = self.nodes[3].createrawtransaction(inputs, outputs) + # Test subtract fee from outputs with feeRate (BTC/kvB) result = [self.nodes[3].fundrawtransaction(rawtx), # uses self.min_relay_tx_fee (set by settxfee) self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": []}), # empty subtraction list self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0]}), # uses self.min_relay_tx_fee (set by settxfee) self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee}), self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee, "subtractFeeFromOutputs": [0]}),] + dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result] + output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)] + change = [d['vout'][r['changepos']]['value'] for d, r in zip(dec_tx, result)] + + assert_equal(result[0]['fee'], result[1]['fee'], result[2]['fee']) + assert_equal(result[3]['fee'], result[4]['fee']) + assert_equal(change[0], change[1]) + assert_equal(output[0], output[1]) + assert_equal(output[0], output[2] + result[2]['fee']) + assert_equal(change[0] + result[0]['fee'], change[2]) + assert_equal(output[3], output[4] + result[4]['fee']) + assert_equal(change[3] + result[3]['fee'], change[4]) + # Test subtract fee from outputs with fee_rate (sat/vB) + btc_kvb_to_sat_vb = 100000 # (1e5) + result = [self.nodes[3].fundrawtransaction(rawtx), # uses self.min_relay_tx_fee (set by settxfee) + self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": []}), # empty subtraction list + self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0]}), # uses self.min_relay_tx_fee (set by settxfee) + self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee}), + self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee, "subtractFeeFromOutputs": [0]}),] dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result] output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)] change = [d['vout'][r['changepos']]['value'] for d, r in zip(dec_tx, result)] diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index ca75bcb9bb..498197b5e5 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -187,60 +187,74 @@ class PSBTTest(BitcoinTestFramework): assert_equal(walletprocesspsbt_out['complete'], True) self.nodes[1].sendrawtransaction(self.nodes[1].finalizepsbt(walletprocesspsbt_out['psbt'])['hex']) - self.log.info("Test walletcreatefundedpsbt feeRate of 0.1 BTC/kB produces a total fee at or slightly below -maxtxfee (~0.05290000)") - res = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.1, "add_inputs": True}) - assert_approx(res["fee"], 0.055, 0.005) - - self.log.info("Test walletcreatefundedpsbt explicit fee rate with conf_target and estimate_mode") - for unit, fee_rate in {"btc/kb": 0.1, "sat/b": 10000}.items(): - fee = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"conf_target": fee_rate, "estimate_mode": unit, "add_inputs": True})["fee"] - self.log.info("- conf_target {}, estimate_mode {} produces fee {} at or slightly below -maxtxfee (~0.05290000)".format(fee_rate, unit, fee)) - assert_approx(fee, vexp=0.055, vspan=0.005) - - for field, fee_rate in {"conf_target": 0.1, "estimate_mode": "sat/b"}.items(): - self.log.info("- raises RPC error if both feeRate and {} are passed".format(field)) - assert_raises_rpc_error(-8, "Cannot specify both {} and feeRate".format(field), - lambda: self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.1, field: fee_rate, "add_inputs": True})) + self.log.info("Test walletcreatefundedpsbt fee rate of 10000 sat/vB and 0.1 BTC/kvB produces a total fee at or slightly below -maxtxfee (~0.05290000)") + res1 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": 10000, "add_inputs": True}) + assert_approx(res1["fee"], 0.055, 0.005) + res2 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.1, "add_inputs": True}) + assert_approx(res2["fee"], 0.055, 0.005) + self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed, e.g. a fee_rate under 1 sat/vB is allowed") + res3 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": 0.99999999, "add_inputs": True}) + assert_approx(res3["fee"], 0.00000381, 0.0000001) + res4 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.00000999, "add_inputs": True}) + assert_approx(res4["fee"], 0.00000381, 0.0000001) + + self.log.info("Test invalid fee rate settings") + assert_raises_rpc_error(-8, "Invalid fee_rate 0.000 sat/vB (must be greater than 0)", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0, "add_inputs": True}) + assert_raises_rpc_error(-8, "Invalid feeRate 0.00000000 BTC/kvB (must be greater than 0)", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"feeRate": 0, "add_inputs": True}) + for param, value in {("fee_rate", 100000), ("feeRate", 1)}: + assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: value, "add_inputs": True}) + assert_raises_rpc_error(-3, "Amount out of range", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": -1, "add_inputs": True}) + assert_raises_rpc_error(-3, "Amount is not a number or string", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": {"foo": "bar"}, "add_inputs": True}) + assert_raises_rpc_error(-3, "Invalid amount", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": "", "add_inputs": True}) + + self.log.info("- raises RPC error if both feeRate and fee_rate are passed") + assert_raises_rpc_error(-8, "Cannot specify both fee_rate (sat/vB) and feeRate (BTC/kvB)", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0.1, "feeRate": 0.1, "add_inputs": True}) + + self.log.info("- raises RPC error if both feeRate and estimate_mode passed") + assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and feeRate", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": "economical", "feeRate": 0.1, "add_inputs": True}) + + for param in ["feeRate", "fee_rate"]: + self.log.info("- raises RPC error if both {} and conf_target are passed".format(param)) + assert_raises_rpc_error(-8, "Cannot specify both conf_target and {}. Please provide either a confirmation " + "target in blocks for automatic fee estimation, or an explicit fee rate.".format(param), + self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {param: 1, "conf_target": 1, "add_inputs": True}) + + self.log.info("- raises RPC error if both fee_rate and estimate_mode are passed") + assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate", + self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {"fee_rate": 1, "estimate_mode": "economical", "add_inputs": True}) self.log.info("- raises RPC error with invalid estimate_mode settings") for k, v in {"number": 42, "object": {"foo": "bar"}}.items(): assert_raises_rpc_error(-3, "Expected type string for estimate_mode, got {}".format(k), - lambda: self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"estimate_mode": v, "conf_target": 0.1, "add_inputs": True})) - for mode in ["foo", Decimal("3.141592")]: - assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", - lambda: self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"estimate_mode": mode, "conf_target": 0.1, "add_inputs": True})) - - self.log.info("- raises RPC error if estimate_mode is passed without a conf_target") - for unit in ["SAT/B", "BTC/KB"]: - assert_raises_rpc_error(-8, "Selected estimate_mode {} requires a fee rate to be specified in conf_target".format(unit), - lambda: self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"estimate_mode": unit})) + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": v, "conf_target": 0.1, "add_inputs": True}) + for mode in ["", "foo", Decimal("3.141592")]: + assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"', + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": 0.1, "add_inputs": True}) self.log.info("- raises RPC error with invalid conf_target settings") - for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]: + for mode in ["unset", "economical", "conservative"]: self.log.debug("{}".format(mode)) for k, v in {"string": "", "object": {"foo": "bar"}}.items(): assert_raises_rpc_error(-3, "Expected type number for conf_target, got {}".format(k), - lambda: self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"estimate_mode": mode, "conf_target": v, "add_inputs": True})) - if mode in ["btc/kb", "sat/b"]: - assert_raises_rpc_error(-3, "Amount out of range", - lambda: self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"estimate_mode": mode, "conf_target": -1, "add_inputs": True})) - assert_raises_rpc_error(-4, "Fee rate (0.00000000 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", - lambda: self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"estimate_mode": mode, "conf_target": 0, "add_inputs": True})) - else: - for n in [-1, 0, 1009]: - assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", - lambda: self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"estimate_mode": mode, "conf_target": n, "add_inputs": True})) - - for unit, fee_rate in {"SAT/B": 0.99999999, "BTC/KB": 0.00000999}.items(): - self.log.info("- raises RPC error 'fee rate too low' if conf_target {} and estimate_mode {} are passed".format(fee_rate, unit)) - assert_raises_rpc_error(-4, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", - lambda: self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"estimate_mode": unit, "conf_target": fee_rate, "add_inputs": True})) - - self.log.info("Test walletcreatefundedpsbt feeRate of 10 BTC/kB produces total fee well above -maxtxfee and raises RPC error") + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": v, "add_inputs": True}) + for n in [-1, 0, 1009]: + assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": n, "add_inputs": True}) + + self.log.info("Test walletcreatefundedpsbt with too-high fee rate produces total fee well above -maxtxfee and raises RPC error") # previously this was silently capped at -maxtxfee for bool_add, outputs_array in {True: outputs, False: [{self.nodes[1].getnewaddress(): 1}]}.items(): - assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", - self.nodes[1].walletcreatefundedpsbt, inputs, outputs_array, 0, {"feeRate": 10, "add_inputs": bool_add}) + msg = "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)" + assert_raises_rpc_error(-4, msg, self.nodes[1].walletcreatefundedpsbt, inputs, outputs_array, 0, {"fee_rate": 1000000, "add_inputs": bool_add}) + assert_raises_rpc_error(-4, msg, self.nodes[1].walletcreatefundedpsbt, inputs, outputs_array, 0, {"feeRate": 1, "add_inputs": bool_add}) self.log.info("Test various PSBT operations") # partially sign multisig things with node 1 diff --git a/test/functional/test_framework/bdb.py b/test/functional/test_framework/bdb.py new file mode 100644 index 0000000000..9de358aa0a --- /dev/null +++ b/test/functional/test_framework/bdb.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +# Copyright (c) 2020 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +""" +Utilities for working directly with the wallet's BDB database file + +This is specific to the configuration of BDB used in this project: + - pagesize: 4096 bytes + - Outer database contains single subdatabase named 'main' + - btree + - btree leaf pages + +Each key-value pair is two entries in a btree leaf. The first is the key, the one that follows +is the value. And so on. Note that the entry data is itself not in the correct order. Instead +entry offsets are stored in the correct order and those offsets are needed to then retrieve +the data itself. + +Page format can be found in BDB source code dbinc/db_page.h +This only implements the deserialization of btree metadata pages and normal btree pages. Overflow +pages are not implemented but may be needed in the future if dealing with wallets with large +transactions. + +`db_dump -da wallet.dat` is useful to see the data in a wallet.dat BDB file +""" + +import binascii +import struct + +# Important constants +PAGESIZE = 4096 +OUTER_META_PAGE = 0 +INNER_META_PAGE = 2 + +# Page type values +BTREE_INTERNAL = 3 +BTREE_LEAF = 5 +BTREE_META = 9 + +# Some magic numbers for sanity checking +BTREE_MAGIC = 0x053162 +DB_VERSION = 9 + +# Deserializes a leaf page into a dict. +# Btree internal pages have the same header, for those, return None. +# For the btree leaf pages, deserialize them and put all the data into a dict +def dump_leaf_page(data): + page_info = {} + page_header = data[0:26] + _, pgno, prev_pgno, next_pgno, entries, hf_offset, level, pg_type = struct.unpack('QIIIHHBB', page_header) + page_info['pgno'] = pgno + page_info['prev_pgno'] = prev_pgno + page_info['next_pgno'] = next_pgno + page_info['entries'] = entries + page_info['hf_offset'] = hf_offset + page_info['level'] = level + page_info['pg_type'] = pg_type + page_info['entry_offsets'] = struct.unpack('{}H'.format(entries), data[26:26 + entries * 2]) + page_info['entries'] = [] + + if pg_type == BTREE_INTERNAL: + # Skip internal pages. These are the internal nodes of the btree and don't contain anything relevant to us + return None + + assert pg_type == BTREE_LEAF, 'A non-btree leaf page has been encountered while dumping leaves' + + for i in range(0, entries): + offset = page_info['entry_offsets'][i] + entry = {'offset': offset} + page_data_header = data[offset:offset + 3] + e_len, pg_type = struct.unpack('HB', page_data_header) + entry['len'] = e_len + entry['pg_type'] = pg_type + entry['data'] = data[offset + 3:offset + 3 + e_len] + page_info['entries'].append(entry) + + return page_info + +# Deserializes a btree metadata page into a dict. +# Does a simple sanity check on the magic value, type, and version +def dump_meta_page(page): + # metadata page + # general metadata + metadata = {} + meta_page = page[0:72] + _, pgno, magic, version, pagesize, encrypt_alg, pg_type, metaflags, _, free, last_pgno, nparts, key_count, record_count, flags, uid = struct.unpack('QIIIIBBBBIIIIII20s', meta_page) + metadata['pgno'] = pgno + metadata['magic'] = magic + metadata['version'] = version + metadata['pagesize'] = pagesize + metadata['encrypt_alg'] = encrypt_alg + metadata['pg_type'] = pg_type + metadata['metaflags'] = metaflags + metadata['free'] = free + metadata['last_pgno'] = last_pgno + metadata['nparts'] = nparts + metadata['key_count'] = key_count + metadata['record_count'] = record_count + metadata['flags'] = flags + metadata['uid'] = binascii.hexlify(uid) + + assert magic == BTREE_MAGIC, 'bdb magic does not match bdb btree magic' + assert pg_type == BTREE_META, 'Metadata page is not a btree metadata page' + assert version == DB_VERSION, 'Database too new' + + # btree metadata + btree_meta_page = page[72:512] + _, minkey, re_len, re_pad, root, _, crypto_magic, _, iv, chksum = struct.unpack('IIIII368sI12s16s20s', btree_meta_page) + metadata['minkey'] = minkey + metadata['re_len'] = re_len + metadata['re_pad'] = re_pad + metadata['root'] = root + metadata['crypto_magic'] = crypto_magic + metadata['iv'] = binascii.hexlify(iv) + metadata['chksum'] = binascii.hexlify(chksum) + return metadata + +# Given the dict from dump_leaf_page, get the key-value pairs and put them into a dict +def extract_kv_pairs(page_data): + out = {} + last_key = None + for i, entry in enumerate(page_data['entries']): + # By virtue of these all being pairs, even number entries are keys, and odd are values + if i % 2 == 0: + out[entry['data']] = b'' + last_key = entry['data'] + else: + out[last_key] = entry['data'] + return out + +# Extract the key-value pairs of the BDB file given in filename +def dump_bdb_kv(filename): + # Read in the BDB file and start deserializing it + pages = [] + with open(filename, 'rb') as f: + data = f.read(PAGESIZE) + while len(data) > 0: + pages.append(data) + data = f.read(PAGESIZE) + + # Sanity check the meta pages + dump_meta_page(pages[OUTER_META_PAGE]) + dump_meta_page(pages[INNER_META_PAGE]) + + # Fetch the kv pairs from the leaf pages + kv = {} + for i in range(3, len(pages)): + info = dump_leaf_page(pages[i]) + if info is not None: + info_kv = extract_kv_pairs(info) + kv = {**kv, **info_kv} + return kv diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 3356f1ab10..62ff5c6e33 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -8,6 +8,7 @@ from base64 import b64encode from binascii import unhexlify from decimal import Decimal, ROUND_DOWN from subprocess import CalledProcessError +import hashlib import inspect import json import logging @@ -260,6 +261,14 @@ def wait_until_helper(predicate, *, attempts=float('inf'), timeout=float('inf'), raise AssertionError("Predicate {} not true after {} seconds".format(predicate_source, timeout)) raise RuntimeError('Unreachable') +def sha256sum_file(filename): + h = hashlib.sha256() + with open(filename, 'rb') as f: + d = f.read(4096) + while len(d) > 0: + h.update(d) + d = f.read(4096) + return h.digest() # RPC/P2P connection constants and functions ############################################ diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 40daffd2c2..ead56046a4 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -4,6 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet.""" from decimal import Decimal +from itertools import product from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( @@ -14,6 +15,8 @@ from test_framework.util import ( ) from test_framework.wallet_util import test_address +OUT_OF_RANGE = "Amount out of range" + class WalletTest(BitcoinTestFramework): def set_test_params(self): @@ -74,7 +77,7 @@ class WalletTest(BitcoinTestFramework): assert_equal(len(self.nodes[1].listunspent()), 1) assert_equal(len(self.nodes[2].listunspent()), 0) - self.log.info("test gettxout") + self.log.info("Test gettxout") confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[0]["vout"] # First, outputs that are unspent both in the chain and in the # mempool should appear with or without include_mempool @@ -87,7 +90,7 @@ class WalletTest(BitcoinTestFramework): self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) - self.log.info("test gettxout (second part)") + self.log.info("Test gettxout (second part)") # utxo spent in mempool should be visible if you exclude mempool # but invisible if you include mempool txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False) @@ -227,65 +230,41 @@ 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.log.info("Test case-insensitive explicit fee rate (sendmany as BTC/kB)") - # Throw if no conf_target provided - assert_raises_rpc_error(-8, "Selected estimate_mode bTc/kB requires a fee rate to be specified in conf_target", - self.nodes[2].sendmany, - amounts={ address: 10 }, - estimate_mode='bTc/kB') - # Throw if negative feerate - assert_raises_rpc_error(-3, "Amount out of range", - self.nodes[2].sendmany, - amounts={ address: 10 }, - conf_target=-1, - estimate_mode='bTc/kB') - fee_per_kb = 0.0002500 - explicit_fee_per_byte = Decimal(fee_per_kb) / 1000 - txid = self.nodes[2].sendmany( - amounts={ address: 10 }, - conf_target=fee_per_kb, - estimate_mode='bTc/kB', - ) - self.nodes[2].generate(1) - self.sync_all(self.nodes[0:3]) - node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])) - assert_equal(self.nodes[2].getbalance(), node_2_bal) - node_0_bal += Decimal('10') - assert_equal(self.nodes[0].getbalance(), node_0_bal) + self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)") + fee_rate_sat_vb = 2 + fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8 + explicit_fee_rate_btc_kvb = Decimal(fee_rate_btc_kvb) / 1000 - self.log.info("Test case-insensitive explicit fee rate (sendmany as sat/B)") - # Throw if no conf_target provided - assert_raises_rpc_error(-8, "Selected estimate_mode sat/b requires a fee rate to be specified in conf_target", - self.nodes[2].sendmany, - amounts={ address: 10 }, - estimate_mode='sat/b') - # Throw if negative feerate - assert_raises_rpc_error(-3, "Amount out of range", - self.nodes[2].sendmany, - amounts={ address: 10 }, - conf_target=-1, - estimate_mode='sat/b') - fee_sat_per_b = 2 - fee_per_kb = fee_sat_per_b / 100000.0 - explicit_fee_per_byte = Decimal(fee_per_kb) / 1000 - txid = self.nodes[2].sendmany( - amounts={ address: 10 }, - conf_target=fee_sat_per_b, - estimate_mode='sAT/b', - ) + # Passing conf_target 0, estimate_mode "" as placeholder arguments should allow fee_rate to apply. + txid = self.nodes[2].sendmany(amounts={address: 10}, conf_target=0, estimate_mode="", fee_rate=fee_rate_sat_vb) self.nodes[2].generate(1) self.sync_all(self.nodes[0:3]) balance = self.nodes[2].getbalance() - node_2_bal = self.check_fee_amount(balance, node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])) + node_2_bal = self.check_fee_amount(balance, node_2_bal - Decimal('10'), explicit_fee_rate_btc_kvb, self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])) assert_equal(balance, node_2_bal) node_0_bal += Decimal('10') assert_equal(self.nodes[0].getbalance(), node_0_bal) + for key in ["totalFee", "feeRate"]: + assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1) + # Test setting explicit fee rate just below the minimum. - for unit, fee_rate in {"BTC/kB": 0.00000999, "sat/B": 0.99999999}.items(): - self.log.info("Test sendmany raises 'fee rate too low' if conf_target {} and estimate_mode {} are passed".format(fee_rate, unit)) - assert_raises_rpc_error(-6, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", - self.nodes[2].sendmany, amounts={address: 10}, estimate_mode=unit, conf_target=fee_rate) + self.log.info("Test sendmany raises 'fee rate too low' if fee_rate of 0.99999999 is passed") + assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)", + self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0.99999999) + + self.log.info("Test sendmany raises if fee_rate of 0 or -1 is passed") + assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)", + self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0) + assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=-1) + + self.log.info("Test sendmany raises if an invalid conf_target or estimate_mode is passed") + for target, mode in product([-1, 0, 1009], ["economical", "conservative"]): + assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h + self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode) + for target, mode in product([-1, 0], ["btc/kb", "sat/b"]): + assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"', + self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode) self.start_node(3, self.nodes[3].extra_args) self.connect_nodes(0, 3) @@ -318,7 +297,7 @@ class WalletTest(BitcoinTestFramework): assert_equal(uTx['amount'], Decimal('0')) assert found - # do some -walletbroadcast tests + self.log.info("Test -walletbroadcast") self.stop_nodes() self.start_node(0, ["-walletbroadcast=0"]) self.start_node(1, ["-walletbroadcast=0"]) @@ -378,7 +357,7 @@ class WalletTest(BitcoinTestFramework): # General checks for errors from incorrect inputs # This will raise an exception because the amount is negative - assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "-1") + assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "-1") # This will raise an exception because the amount type is wrong assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4") @@ -420,78 +399,43 @@ class WalletTest(BitcoinTestFramework): self.nodes[0].generate(1) self.sync_all(self.nodes[0:3]) - self.log.info("Test case-insensitive explicit fee rate (sendtoaddress as BTC/kB)") - self.nodes[0].generate(1) - self.sync_all(self.nodes[0:3]) + self.log.info("Test sendtoaddress with fee_rate param (explicit fee rate in sat/vB)") prebalance = self.nodes[2].getbalance() assert prebalance > 2 address = self.nodes[1].getnewaddress() - # Throw if no conf_target provided - assert_raises_rpc_error(-8, "Selected estimate_mode BTc/Kb requires a fee rate to be specified in conf_target", - self.nodes[2].sendtoaddress, - address=address, - amount=1.0, - estimate_mode='BTc/Kb') - # Throw if negative feerate - assert_raises_rpc_error(-3, "Amount out of range", - self.nodes[2].sendtoaddress, - address=address, - amount=1.0, - conf_target=-1, - estimate_mode='btc/kb') - txid = self.nodes[2].sendtoaddress( - address=address, - amount=1.0, - conf_target=0.00002500, - estimate_mode='btc/kb', - ) - tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex']) - self.sync_all(self.nodes[0:3]) - self.nodes[0].generate(1) - self.sync_all(self.nodes[0:3]) - postbalance = self.nodes[2].getbalance() - fee = prebalance - postbalance - Decimal('1') - assert_fee_amount(fee, tx_size, Decimal('0.00002500')) + amount = 3 + fee_rate_sat_vb = 2 + fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8 - self.sync_all(self.nodes[0:3]) - - self.log.info("Test case-insensitive explicit fee rate (sendtoaddress as sat/B)") - self.nodes[0].generate(1) - prebalance = self.nodes[2].getbalance() - assert prebalance > 2 - address = self.nodes[1].getnewaddress() - # Throw if no conf_target provided - assert_raises_rpc_error(-8, "Selected estimate_mode SAT/b requires a fee rate to be specified in conf_target", - self.nodes[2].sendtoaddress, - address=address, - amount=1.0, - estimate_mode='SAT/b') - # Throw if negative feerate - assert_raises_rpc_error(-3, "Amount out of range", - self.nodes[2].sendtoaddress, - address=address, - amount=1.0, - conf_target=-1, - estimate_mode='SAT/b') - txid = self.nodes[2].sendtoaddress( - address=address, - amount=1.0, - conf_target=2, - estimate_mode='SAT/B', - ) + # Passing conf_target 0, estimate_mode "" as placeholder arguments should allow fee_rate to apply. + txid = self.nodes[2].sendtoaddress(address=address, amount=amount, conf_target=0, estimate_mode="", fee_rate=fee_rate_sat_vb) tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex']) - self.sync_all(self.nodes[0:3]) self.nodes[0].generate(1) self.sync_all(self.nodes[0:3]) postbalance = self.nodes[2].getbalance() - fee = prebalance - postbalance - Decimal('1') - assert_fee_amount(fee, tx_size, Decimal('0.00002000')) + fee = prebalance - postbalance - Decimal(amount) + assert_fee_amount(fee, tx_size, Decimal(fee_rate_btc_kvb)) + + for key in ["totalFee", "feeRate"]: + assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1) # Test setting explicit fee rate just below the minimum. - for unit, fee_rate in {"BTC/kB": 0.00000999, "sat/B": 0.99999999}.items(): - self.log.info("Test sendtoaddress raises 'fee rate too low' if conf_target {} and estimate_mode {} are passed".format(fee_rate, unit)) - assert_raises_rpc_error(-6, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", - self.nodes[2].sendtoaddress, address=address, amount=1, estimate_mode=unit, conf_target=fee_rate) + self.log.info("Test sendtoaddress raises 'fee rate too low' if fee_rate of 0.99999999 is passed") + assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)", + self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=0.99999999) + + self.log.info("Test sendtoaddress raises if fee_rate of 0 or -1 is passed") + assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)", + self.nodes[2].sendtoaddress, address=address, amount=10, fee_rate=0) + assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=-1) + + self.log.info("Test sendtoaddress raises if an invalid conf_target or estimate_mode is passed") + for target, mode in product([-1, 0, 1009], ["economical", "conservative"]): + assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h + self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode) + for target, mode in product([-1, 0], ["btc/kb", "sat/b"]): + assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"', + self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode) # 2. Import address from node2 to node1 self.nodes[1].importaddress(address_to_import) @@ -549,7 +493,7 @@ class WalletTest(BitcoinTestFramework): ] chainlimit = 6 for m in maintenance: - self.log.info("check " + m) + self.log.info("Test " + m) self.stop_nodes() # set lower ancestor limit for later self.start_node(0, [m, "-limitancestorcount=" + str(chainlimit)]) diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index 88a7778e19..c323aac3cc 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -17,7 +17,7 @@ from decimal import Decimal import io from test_framework.blocktools import add_witness_commitment, create_block, create_coinbase, send_to_witness -from test_framework.messages import BIP125_SEQUENCE_NUMBER, COIN, CTransaction +from test_framework.messages import BIP125_SEQUENCE_NUMBER, CTransaction from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, @@ -29,15 +29,13 @@ from test_framework.util import ( WALLET_PASSPHRASE = "test" WALLET_PASSPHRASE_TIMEOUT = 3600 -# Fee rates (in BTC per 1000 vbytes) -INSUFFICIENT = 0.00001000 -ECONOMICAL = 0.00050000 -NORMAL = 0.00100000 -HIGH = 0.00500000 -TOO_HIGH = 1.00000000 +# Fee rates (sat/vB) +INSUFFICIENT = 1 +ECONOMICAL = 50 +NORMAL = 100 +HIGH = 500 +TOO_HIGH = 100000 -BTC_MODE = "BTC/kB" -SAT_MODE = "sat/B" class BumpFeeTest(BitcoinTestFramework): def set_test_params(self): @@ -78,7 +76,7 @@ class BumpFeeTest(BitcoinTestFramework): self.log.info("Running tests") dest_address = peer_node.getnewaddress() - for mode in ["default", "fee_rate", BTC_MODE, SAT_MODE]: + for mode in ["default", "fee_rate"]: test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address) self.test_invalid_parameters(rbf_node, peer_node, dest_address) test_segwit_bumpfee_succeeds(self, rbf_node, dest_address) @@ -105,50 +103,44 @@ class BumpFeeTest(BitcoinTestFramework): self.sync_mempools((rbf_node, peer_node)) assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool() - assert_raises_rpc_error(-3, "Unexpected key totalFee", rbf_node.bumpfee, rbfid, {"totalFee": NORMAL}) - assert_raises_rpc_error(-4, "is too high (cannot be higher than", rbf_node.bumpfee, rbfid, {"fee_rate": TOO_HIGH}) + for key in ["totalFee", "feeRate"]: + assert_raises_rpc_error(-3, "Unexpected key {}".format(key), rbf_node.bumpfee, rbfid, {key: NORMAL}) - # For each fee mode, bumping to just above minrelay should fail to increase the total fee enough. - for options in [{"fee_rate": INSUFFICIENT}, {"conf_target": INSUFFICIENT, "estimate_mode": BTC_MODE}, {"conf_target": 1, "estimate_mode": SAT_MODE}]: - assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, rbfid, options) + # Bumping to just above minrelay should fail to increase the total fee enough. + assert_raises_rpc_error(-8, "Insufficient total fee 0.00000141, must be at least 0.00001704 (oldFee 0.00000999 + incrementalFee 0.00000705)", + rbf_node.bumpfee, rbfid, {"fee_rate": INSUFFICIENT}) - self.log.info("Test explicit fee rate raises RPC error if estimate_mode is passed without a conf_target") - for unit, fee_rate in {"SAT/B": 100, "BTC/KB": NORMAL}.items(): - assert_raises_rpc_error(-8, "Selected estimate_mode {} requires a fee rate to be specified in conf_target".format(unit), - rbf_node.bumpfee, rbfid, {"fee_rate": fee_rate, "estimate_mode": unit}) + self.log.info("Test invalid fee rate settings") + assert_raises_rpc_error(-8, "Insufficient total fee 0.00, must be at least 0.00001704 (oldFee 0.00000999 + incrementalFee 0.00000705)", + rbf_node.bumpfee, rbfid, {"fee_rate": 0}) + assert_raises_rpc_error(-4, "Specified or calculated fee 0.141 is too high (cannot be higher than -maxtxfee 0.10", + rbf_node.bumpfee, rbfid, {"fee_rate": TOO_HIGH}) + assert_raises_rpc_error(-3, "Amount out of range", rbf_node.bumpfee, rbfid, {"fee_rate": -1}) + for value in [{"foo": "bar"}, True]: + assert_raises_rpc_error(-3, "Amount is not a number or string", rbf_node.bumpfee, rbfid, {"fee_rate": value}) + assert_raises_rpc_error(-3, "Invalid amount", rbf_node.bumpfee, rbfid, {"fee_rate": ""}) self.log.info("Test explicit fee rate raises RPC error if both fee_rate and conf_target are passed") - error_both = "Cannot specify both conf_target and fee_rate. Please provide either a confirmation " \ - "target in blocks for automatic fee estimation, or an explicit fee rate." - assert_raises_rpc_error(-8, error_both, rbf_node.bumpfee, rbfid, {"conf_target": NORMAL, "fee_rate": NORMAL}) + assert_raises_rpc_error(-8, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation " + "target in blocks for automatic fee estimation, or an explicit fee rate.", + rbf_node.bumpfee, rbfid, {"conf_target": NORMAL, "fee_rate": NORMAL}) + + self.log.info("Test explicit fee rate raises RPC error if both fee_rate and estimate_mode are passed") + assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate", + rbf_node.bumpfee, rbfid, {"estimate_mode": "economical", "fee_rate": NORMAL}) self.log.info("Test invalid conf_target settings") assert_raises_rpc_error(-8, "confTarget and conf_target options should not both be set", - rbf_node.bumpfee, rbfid, {"confTarget": 123, "conf_target": 456}) - for field in ["confTarget", "conf_target"]: - assert_raises_rpc_error(-4, "is too high (cannot be higher than -maxtxfee", - lambda: rbf_node.bumpfee(rbfid, {"estimate_mode": BTC_MODE, "conf_target": 2009})) - assert_raises_rpc_error(-4, "is too high (cannot be higher than -maxtxfee", - lambda: rbf_node.bumpfee(rbfid, {"estimate_mode": SAT_MODE, "conf_target": 2009 * 10000})) + rbf_node.bumpfee, rbfid, {"confTarget": 123, "conf_target": 456}) self.log.info("Test invalid estimate_mode settings") for k, v in {"number": 42, "object": {"foo": "bar"}}.items(): assert_raises_rpc_error(-3, "Expected type string for estimate_mode, got {}".format(k), - lambda: rbf_node.bumpfee(rbfid, {"estimate_mode": v, "fee_rate": NORMAL})) - for mode in ["foo", Decimal("3.141592")]: - assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", - lambda: rbf_node.bumpfee(rbfid, {"estimate_mode": mode, "fee_rate": NORMAL})) - - self.log.info("Test invalid fee_rate settings") - for mode in ["unset", "economical", "conservative", BTC_MODE, SAT_MODE]: - self.log.debug("{}".format(mode)) - for k, v in {"string": "", "object": {"foo": "bar"}}.items(): - assert_raises_rpc_error(-3, "Expected type number for fee_rate, got {}".format(k), - lambda: rbf_node.bumpfee(rbfid, {"estimate_mode": mode, "fee_rate": v})) - assert_raises_rpc_error(-3, "Amount out of range", - lambda: rbf_node.bumpfee(rbfid, {"estimate_mode": mode, "fee_rate": -1})) - assert_raises_rpc_error(-8, "Invalid fee_rate 0.00000000 BTC/kB (must be greater than 0)", - lambda: rbf_node.bumpfee(rbfid, {"estimate_mode": mode, "fee_rate": 0})) + rbf_node.bumpfee, rbfid, {"estimate_mode": v}) + for mode in ["foo", Decimal("3.1415"), "sat/B", "BTC/kB"]: + assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"', + rbf_node.bumpfee, rbfid, {"estimate_mode": mode}) + self.clear_mempool() @@ -161,13 +153,6 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address): if mode == "fee_rate": bumped_psbt = rbf_node.psbtbumpfee(rbfid, {"fee_rate": NORMAL}) bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": NORMAL}) - elif mode == BTC_MODE: - bumped_psbt = rbf_node.psbtbumpfee(rbfid, {"conf_target": NORMAL, "estimate_mode": BTC_MODE}) - bumped_tx = rbf_node.bumpfee(rbfid, {"conf_target": NORMAL, "estimate_mode": BTC_MODE}) - elif mode == SAT_MODE: - sat_fee = NORMAL * COIN / 1000 # convert NORMAL from BTC/kB to sat/B - bumped_psbt = rbf_node.psbtbumpfee(rbfid, {"conf_target": sat_fee, "estimate_mode": SAT_MODE}) - bumped_tx = rbf_node.bumpfee(rbfid, {"conf_target": sat_fee, "estimate_mode": SAT_MODE}) else: bumped_psbt = rbf_node.psbtbumpfee(rbfid) bumped_tx = rbf_node.bumpfee(rbfid) @@ -319,11 +304,11 @@ def test_dust_to_fee(self, rbf_node, dest_address): # boundary. Thus expected transaction size (p2wpkh, 1 input, 2 outputs) is 140-141 vbytes, usually 141. if not 140 <= fulltx["vsize"] <= 141: raise AssertionError("Invalid tx vsize of {} (140-141 expected), full tx: {}".format(fulltx["vsize"], fulltx)) - # Bump with fee_rate of 0.00350250 BTC per 1000 vbytes to create dust. + # Bump with fee_rate of 350.25 sat/vB vbytes to create dust. # Expected fee is 141 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049385 BTC. # or occasionally 140 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049035 BTC. # Dust should be dropped to the fee, so actual bump fee is 0.00050000 BTC. - bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": 0.00350250}) + bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": 350.25}) full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1) assert_equal(bumped_tx["fee"], Decimal("0.00050000")) assert_equal(len(fulltx["vout"]), 2) diff --git a/test/functional/wallet_importdescriptors.py b/test/functional/wallet_importdescriptors.py index 74a9994258..2903a84998 100755 --- a/test/functional/wallet_importdescriptors.py +++ b/test/functional/wallet_importdescriptors.py @@ -221,6 +221,15 @@ class ImportDescriptorsTest(BitcoinTestFramework): success=False, error_code=-4, error_message='Cannot import private keys to a wallet with private keys disabled') + + self.log.info("Should not import a descriptor with hardened derivations when private keys are disabled") + self.test_importdesc({"desc": descsum_create("wpkh(" + xpub + "/1h/*)"), + "timestamp": "now", + "range": 1}, + success=False, + error_code=-4, + error_message='Cannot expand descriptor. Probably because of hardened derivations without private keys provided') + for address in addresses: test_address(w1, address, diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py index 07c14db6b1..6a1b9097c5 100755 --- a/test/functional/wallet_listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py @@ -191,6 +191,7 @@ class ListSinceBlockTest(BitcoinTestFramework): address = key_to_p2wpkh(eckey.get_pubkey().get_bytes()) self.nodes[2].sendtoaddress(address, 10) self.nodes[2].generate(6) + self.sync_all() self.nodes[2].importprivkey(privkey) utxos = self.nodes[2].listunspent() utxo = [u for u in utxos if u["address"] == address][0] diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index abdc279197..df16ec741f 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -10,6 +10,7 @@ from decimal import Decimal from threading import Thread import os import shutil +import stat import time from test_framework.authproxy import JSONRPCException @@ -78,6 +79,11 @@ class MultiWalletTest(BitcoinTestFramework): os.mkdir(wallet_dir('w7')) os.symlink('w7', wallet_dir('w7_symlink')) + os.symlink('..', wallet_dir('recursive_dir_symlink')) + + os.mkdir(wallet_dir('self_walletdat_symlink')) + os.symlink('wallet.dat', wallet_dir('self_walletdat_symlink/wallet.dat')) + # rename wallet.dat to make sure plain wallet file paths (as opposed to # directory paths) can be loaded # create another dummy wallet for use in testing backups later @@ -117,7 +123,16 @@ class MultiWalletTest(BitcoinTestFramework): self.nodes[0].createwallet(wallet_name) for wallet_name in to_load: self.nodes[0].loadwallet(wallet_name) - assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), sorted(in_wallet_dir)) + + os.mkdir(wallet_dir('no_access')) + os.chmod(wallet_dir('no_access'), 0) + try: + with self.nodes[0].assert_debug_log(expected_msgs=['Too many levels of symbolic links', 'Error scanning']): + walletlist = self.nodes[0].listwalletdir()['wallets'] + finally: + # Need to ensure access is restored for cleanup + os.chmod(wallet_dir('no_access'), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) + assert_equal(sorted(map(lambda w: w['name'], walletlist)), sorted(in_wallet_dir)) assert_equal(set(node.listwallets()), set(wallet_names)) @@ -156,6 +171,9 @@ class MultiWalletTest(BitcoinTestFramework): open(not_a_dir, 'a', encoding="utf8").close() self.nodes[0].assert_start_raises_init_error(['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory') + self.log.info("Do not allow -upgradewallet with multiwallet") + self.nodes[0].assert_start_raises_init_error(['-upgradewallet'], "Error: Error parsing command line arguments: Invalid parameter -upgradewallet") + # if wallets/ doesn't exist, datadir should be the default wallet dir wallet_dir2 = data_dir('walletdir') os.rename(wallet_dir(), wallet_dir2) diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py index 921a726d4b..5da71c85f9 100755 --- a/test/functional/wallet_send.py +++ b/test/functional/wallet_send.py @@ -5,13 +5,15 @@ """Test the send RPC command.""" from decimal import Decimal, getcontext +from itertools import product + from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, assert_fee_amount, assert_greater_than, - assert_raises_rpc_error + assert_raises_rpc_error, ) class WalletSendTest(BitcoinTestFramework): @@ -28,8 +30,8 @@ class WalletSendTest(BitcoinTestFramework): self.skip_if_no_wallet() def test_send(self, from_wallet, to_wallet=None, amount=None, data=None, - arg_conf_target=None, arg_estimate_mode=None, - conf_target=None, estimate_mode=None, add_to_wallet=None, psbt=None, + arg_conf_target=None, arg_estimate_mode=None, arg_fee_rate=None, + conf_target=None, estimate_mode=None, fee_rate=None, add_to_wallet=None, psbt=None, inputs=None, add_inputs=None, change_address=None, change_position=None, change_type=None, include_watching=None, locktime=None, lock_unspents=None, replaceable=None, subtract_fee_from_outputs=None, expect_error=None): @@ -62,6 +64,8 @@ class WalletSendTest(BitcoinTestFramework): options["conf_target"] = conf_target if estimate_mode is not None: options["estimate_mode"] = estimate_mode + if fee_rate is not None: + options["fee_rate"] = fee_rate if inputs is not None: options["inputs"] = inputs if add_inputs is not None: @@ -89,18 +93,19 @@ class WalletSendTest(BitcoinTestFramework): options = None if expect_error is None: - res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, options=options) + res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, fee_rate=arg_fee_rate, options=options) else: try: assert_raises_rpc_error(expect_error[0], expect_error[1], from_wallet.send, - outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, options=options) + outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, fee_rate=arg_fee_rate, options=options) except AssertionError: # Provide debug info if the test fails self.log.error("Unexpected successful result:") self.log.error(arg_conf_target) self.log.error(arg_estimate_mode) + self.log.error(arg_fee_rate) self.log.error(options) - res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, options=options) + res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, fee_rate=arg_fee_rate, options=options) self.log.error(res) if "txid" in res and add_to_wallet: self.log.error("Transaction details:") @@ -226,10 +231,10 @@ class WalletSendTest(BitcoinTestFramework): assert_equal(self.nodes[1].decodepsbt(res1["psbt"])["fee"], self.nodes[1].decodepsbt(res2["psbt"])["fee"]) # but not at the same time - for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]: + for mode in ["unset", "economical", "conservative"]: self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=1, arg_estimate_mode="economical", conf_target=1, estimate_mode=mode, add_to_wallet=False, - expect_error=(-8, "Use either conf_target and estimate_mode or the options dictionary to control fee rate")) + expect_error=(-8, "Pass conf_target and estimate_mode either as arguments or in the options object, but not both")) self.log.info("Create PSBT from watch-only wallet w3, sign with w2...") res = self.test_send(from_wallet=w3, to_wallet=w1, amount=1) @@ -251,60 +256,57 @@ class WalletSendTest(BitcoinTestFramework): assert res["complete"] self.log.info("Test setting explicit fee rate") - res1 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=1, arg_estimate_mode="economical", add_to_wallet=False) - res2 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=1, estimate_mode="economical", add_to_wallet=False) + res1 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=1, add_to_wallet=False) + res2 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=1, add_to_wallet=False) assert_equal(self.nodes[1].decodepsbt(res1["psbt"])["fee"], self.nodes[1].decodepsbt(res2["psbt"])["fee"]) - res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.00007, estimate_mode="btc/kb", add_to_wallet=False) + # Passing conf_target 0, estimate_mode "" as placeholder arguments should allow fee_rate to apply. + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0, estimate_mode="", fee_rate=7, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00007")) - res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=2, estimate_mode="sat/b", add_to_wallet=False) + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=2, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00002")) - res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0.00004531, arg_estimate_mode="btc/kb", add_to_wallet=False) + # Passing conf_target 0, estimate_mode "" as placeholder arguments should allow fee_rate to apply. + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0, arg_estimate_mode="", arg_fee_rate=4.531, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00004531")) - res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=3, arg_estimate_mode="sat/b", add_to_wallet=False) + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=3, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00003")) - # TODO: This test should pass with all modes, e.g. with the next line uncommented, for consistency with the other explicit feerate RPCs. - # for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]: - for mode in ["btc/kb", "sat/b"]: - self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=-1, estimate_mode=mode, - expect_error=(-3, "Amount out of range")) - self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0, estimate_mode=mode, - expect_error=(-4, "Fee rate (0.00000000 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)")) - - for mode in ["foo", Decimal("3.141592")]: - self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode=mode, - expect_error=(-8, "Invalid estimate_mode parameter")) - # TODO: these 2 equivalent sends with an invalid estimate_mode arg should both fail, but they do not...why? - # self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0.1, arg_estimate_mode=mode, - # expect_error=(-8, "Invalid estimate_mode parameter")) - # assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", lambda: w0.send({w1.getnewaddress(): 1}, 0.1, mode)) - - # TODO: These tests should pass for consistency with the other explicit feerate RPCs, but they do not. - # for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]: - # self.log.debug("{}".format(mode)) - # for k, v in {"string": "", "object": {"foo": "bar"}}.items(): - # self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=v, estimate_mode=mode, - # expect_error=(-3, "Expected type number for conf_target, got {}".format(k))) - - # TODO: error should use sat/B instead of BTC/kB if sat/B is selected. + # Test that passing fee_rate as both an argument and an option raises. + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=1, fee_rate=1, add_to_wallet=False, + expect_error=(-8, "Pass the fee_rate either as an argument, or in the options object, but not both")) + + assert_raises_rpc_error(-8, "Use fee_rate (sat/vB) instead of feeRate", w0.send, {w1.getnewaddress(): 1}, 6, "conservative", 1, {"feeRate": 0.01}) + + assert_raises_rpc_error(-3, "Unexpected key totalFee", w0.send, {w1.getnewaddress(): 1}, 6, "conservative", 1, {"totalFee": 0.01}) + + for target, mode in product([-1, 0, 1009], ["economical", "conservative"]): + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=target, estimate_mode=mode, + expect_error=(-8, "Invalid conf_target, must be between 1 and 1008")) # max value of 1008 per src/policy/fees.h + msg = 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"' + for target, mode in product([-1, 0], ["btc/kb", "sat/b"]): + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=target, estimate_mode=mode, expect_error=(-8, msg)) + for mode in ["", "foo", Decimal("3.141592")]: + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode=mode, expect_error=(-8, msg)) + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0.1, arg_estimate_mode=mode, expect_error=(-8, msg)) + assert_raises_rpc_error(-8, msg, w0.send, {w1.getnewaddress(): 1}, 0.1, mode) + + for mode in ["economical", "conservative", "btc/kb", "sat/b"]: + self.log.debug("{}".format(mode)) + for k, v in {"string": "true", "object": {"foo": "bar"}}.items(): + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=v, estimate_mode=mode, + expect_error=(-3, "Expected type number for conf_target, got {}".format(k))) + # Test setting explicit fee rate just below the minimum. - for unit, fee_rate in {"sat/B": 0.99999999, "BTC/kB": 0.00000999}.items(): - self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if conf_target {} and estimate_mode {} are passed".format(fee_rate, unit)) - self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=fee_rate, estimate_mode=unit, - expect_error=(-4, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)")) - - self.log.info("Explicit fee rate raises RPC error if estimate_mode is passed without a conf_target") - for unit, fee_rate in {"sat/B": 100, "BTC/kB": 0.001}.items(): - self.test_send(from_wallet=w0, to_wallet=w1, amount=1, estimate_mode=unit, - expect_error=(-8, "Selected estimate_mode {} requires a fee rate to be specified in conf_target".format(unit))) + self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if fee_rate of 0.99999999 is passed") + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0.99999999, + expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)")) # TODO: Return hex if fee rate is below -maxmempool # res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", add_to_wallet=False) diff --git a/test/functional/wallet_upgradewallet.py b/test/functional/wallet_upgradewallet.py index 15d9b109c5..8ab4b3f76c 100755 --- a/test/functional/wallet_upgradewallet.py +++ b/test/functional/wallet_upgradewallet.py @@ -13,23 +13,47 @@ Only v0.15.2 and v0.16.3 are required by this test. The others are used in featu import os import shutil +import struct +from io import BytesIO + +from test_framework.bdb import dump_bdb_kv +from test_framework.messages import deser_compact_size, deser_string from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, assert_greater_than, assert_is_hex_string, + assert_raises_rpc_error, + sha256sum_file, ) +UPGRADED_KEYMETA_VERSION = 12 + +def deser_keymeta(f): + ver, create_time = struct.unpack('<Iq', f.read(12)) + kp_str = deser_string(f) + seed_id = f.read(20) + fpr = f.read(4) + path_len = 0 + path = [] + has_key_orig = False + if ver == UPGRADED_KEYMETA_VERSION: + path_len = deser_compact_size(f) + for i in range(0, path_len): + path.append(struct.unpack('<I', f.read(4))[0]) + has_key_orig = bool(f.read(1)) + return ver, create_time, kp_str, seed_id, fpr, path_len, path, has_key_orig + class UpgradeWalletTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 3 self.extra_args = [ - ["-addresstype=bech32"], # current wallet version - ["-usehd=1"], # v0.16.3 wallet - ["-usehd=0"] # v0.15.2 wallet + ["-addresstype=bech32", "-keypool=2"], # current wallet version + ["-usehd=1", "-keypool=2"], # v0.16.3 wallet + ["-usehd=0", "-keypool=2"] # v0.15.2 wallet ] self.wallet_names = [self.default_wallet_name, None, None] @@ -87,22 +111,53 @@ class UpgradeWalletTest(BitcoinTestFramework): self.log.info("Test upgradewallet RPC...") # Prepare for copying of the older wallet - node_master_wallet_dir = os.path.join(node_master.datadir, "regtest/wallets") + node_master_wallet_dir = os.path.join(node_master.datadir, "regtest/wallets", self.default_wallet_name) + node_master_wallet = os.path.join(node_master_wallet_dir, self.default_wallet_name, self.wallet_data_filename) v16_3_wallet = os.path.join(v16_3_node.datadir, "regtest/wallets/wallet.dat") v15_2_wallet = os.path.join(v15_2_node.datadir, "regtest/wallet.dat") + split_hd_wallet = os.path.join(v15_2_node.datadir, "regtest/splithd") self.stop_nodes() - # Copy the 0.16.3 wallet to the last Bitcoin Core version and open it: - shutil.rmtree(node_master_wallet_dir) - os.mkdir(node_master_wallet_dir) - shutil.copy( - v16_3_wallet, - node_master_wallet_dir - ) - self.restart_node(0, ['-nowallet']) - node_master.loadwallet('') + # Make split hd wallet + self.start_node(2, ['-usehd=1', '-keypool=2', '-wallet=splithd']) + self.stop_node(2) + + def copy_v16(): + node_master.get_wallet_rpc(self.default_wallet_name).unloadwallet() + # Copy the 0.16.3 wallet to the last Bitcoin Core version and open it: + shutil.rmtree(node_master_wallet_dir) + os.mkdir(node_master_wallet_dir) + shutil.copy( + v16_3_wallet, + node_master_wallet_dir + ) + node_master.loadwallet(self.default_wallet_name) + + def copy_non_hd(): + node_master.get_wallet_rpc(self.default_wallet_name).unloadwallet() + # Copy the 0.15.2 non hd wallet to the last Bitcoin Core version and open it: + shutil.rmtree(node_master_wallet_dir) + os.mkdir(node_master_wallet_dir) + shutil.copy( + v15_2_wallet, + node_master_wallet_dir + ) + node_master.loadwallet(self.default_wallet_name) - wallet = node_master.get_wallet_rpc('') + def copy_split_hd(): + node_master.get_wallet_rpc(self.default_wallet_name).unloadwallet() + # Copy the 0.15.2 split hd wallet to the last Bitcoin Core version and open it: + shutil.rmtree(node_master_wallet_dir) + os.mkdir(node_master_wallet_dir) + shutil.copy( + split_hd_wallet, + os.path.join(node_master_wallet_dir, 'wallet.dat') + ) + node_master.loadwallet(self.default_wallet_name) + + self.restart_node(0) + copy_v16() + wallet = node_master.get_wallet_rpc(self.default_wallet_name) old_version = wallet.getwalletinfo()["walletversion"] # calling upgradewallet without version arguments @@ -114,18 +169,8 @@ class UpgradeWalletTest(BitcoinTestFramework): # wallet should still contain the same balance assert_equal(wallet.getbalance(), v16_3_balance) - self.stop_node(0) - # Copy the 0.15.2 wallet to the last Bitcoin Core version and open it: - shutil.rmtree(node_master_wallet_dir) - os.mkdir(node_master_wallet_dir) - shutil.copy( - v15_2_wallet, - node_master_wallet_dir - ) - self.restart_node(0, ['-nowallet']) - node_master.loadwallet('') - - wallet = node_master.get_wallet_rpc('') + copy_non_hd() + wallet = node_master.get_wallet_rpc(self.default_wallet_name) # should have no master key hash before conversion assert_equal('hdseedid' in wallet.getwalletinfo(), False) # calling upgradewallet with explicit version number @@ -137,5 +182,165 @@ class UpgradeWalletTest(BitcoinTestFramework): # after conversion master key hash should be present assert_is_hex_string(wallet.getwalletinfo()['hdseedid']) + self.log.info('Intermediary versions don\'t effect anything') + copy_non_hd() + # Wallet starts with 60000 + assert_equal(60000, wallet.getwalletinfo()['walletversion']) + wallet.unloadwallet() + before_checksum = sha256sum_file(node_master_wallet) + node_master.loadwallet('') + # Can "upgrade" to 129999 which should have no effect on the wallet + wallet.upgradewallet(129999) + assert_equal(60000, wallet.getwalletinfo()['walletversion']) + wallet.unloadwallet() + assert_equal(before_checksum, sha256sum_file(node_master_wallet)) + node_master.loadwallet('') + + self.log.info('Wallets cannot be downgraded') + copy_non_hd() + assert_raises_rpc_error(-4, 'Cannot downgrade wallet', wallet.upgradewallet, 40000) + wallet.unloadwallet() + assert_equal(before_checksum, sha256sum_file(node_master_wallet)) + node_master.loadwallet('') + + self.log.info('Can upgrade to HD') + # Inspect the old wallet and make sure there is no hdchain + orig_kvs = dump_bdb_kv(node_master_wallet) + assert b'\x07hdchain' not in orig_kvs + # Upgrade to HD, no split + wallet.upgradewallet(130000) + assert_equal(130000, wallet.getwalletinfo()['walletversion']) + # Check that there is now a hd chain and it is version 1, no internal chain counter + new_kvs = dump_bdb_kv(node_master_wallet) + assert b'\x07hdchain' in new_kvs + hd_chain = new_kvs[b'\x07hdchain'] + assert_equal(28, len(hd_chain)) + hd_chain_version, external_counter, seed_id = struct.unpack('<iI20s', hd_chain) + assert_equal(1, hd_chain_version) + seed_id = bytearray(seed_id) + seed_id.reverse() + old_kvs = new_kvs + # First 2 keys should still be non-HD + for i in range(0, 2): + info = wallet.getaddressinfo(wallet.getnewaddress()) + assert 'hdkeypath' not in info + assert 'hdseedid' not in info + # Next key should be HD + info = wallet.getaddressinfo(wallet.getnewaddress()) + assert_equal(seed_id.hex(), info['hdseedid']) + assert_equal('m/0\'/0\'/0\'', info['hdkeypath']) + prev_seed_id = info['hdseedid'] + # Change key should be the same keypool + info = wallet.getaddressinfo(wallet.getrawchangeaddress()) + assert_equal(prev_seed_id, info['hdseedid']) + assert_equal('m/0\'/0\'/1\'', info['hdkeypath']) + + self.log.info('Cannot upgrade to HD Split, needs Pre Split Keypool') + assert_raises_rpc_error(-4, 'Cannot upgrade a non HD split wallet without upgrading to support pre split keypool', wallet.upgradewallet, 139900) + assert_equal(130000, wallet.getwalletinfo()['walletversion']) + assert_raises_rpc_error(-4, 'Cannot upgrade a non HD split wallet without upgrading to support pre split keypool', wallet.upgradewallet, 159900) + assert_equal(130000, wallet.getwalletinfo()['walletversion']) + assert_raises_rpc_error(-4, 'Cannot upgrade a non HD split wallet without upgrading to support pre split keypool', wallet.upgradewallet, 169899) + assert_equal(130000, wallet.getwalletinfo()['walletversion']) + + self.log.info('Upgrade HD to HD chain split') + wallet.upgradewallet(169900) + assert_equal(169900, wallet.getwalletinfo()['walletversion']) + # Check that the hdchain updated correctly + new_kvs = dump_bdb_kv(node_master_wallet) + hd_chain = new_kvs[b'\x07hdchain'] + assert_equal(32, len(hd_chain)) + hd_chain_version, external_counter, seed_id, internal_counter = struct.unpack('<iI20sI', hd_chain) + assert_equal(2, hd_chain_version) + assert_equal(0, internal_counter) + seed_id = bytearray(seed_id) + seed_id.reverse() + assert_equal(seed_id.hex(), prev_seed_id) + # Next change address is the same keypool + info = wallet.getaddressinfo(wallet.getrawchangeaddress()) + assert_equal(prev_seed_id, info['hdseedid']) + assert_equal('m/0\'/0\'/2\'', info['hdkeypath']) + # Next change address is the new keypool + info = wallet.getaddressinfo(wallet.getrawchangeaddress()) + assert_equal(prev_seed_id, info['hdseedid']) + assert_equal('m/0\'/1\'/0\'', info['hdkeypath']) + # External addresses use the same keypool + info = wallet.getaddressinfo(wallet.getnewaddress()) + assert_equal(prev_seed_id, info['hdseedid']) + assert_equal('m/0\'/0\'/3\'', info['hdkeypath']) + + self.log.info('Upgrade non-HD to HD chain split') + copy_non_hd() + wallet.upgradewallet(169900) + assert_equal(169900, wallet.getwalletinfo()['walletversion']) + # Check that the hdchain updated correctly + new_kvs = dump_bdb_kv(node_master_wallet) + hd_chain = new_kvs[b'\x07hdchain'] + assert_equal(32, len(hd_chain)) + hd_chain_version, external_counter, seed_id, internal_counter = struct.unpack('<iI20sI', hd_chain) + assert_equal(2, hd_chain_version) + assert_equal(2, internal_counter) + # Drain the keypool by fetching one external key and one change key. Should still be the same keypool + info = wallet.getaddressinfo(wallet.getnewaddress()) + assert 'hdseedid' not in info + assert 'hdkeypath' not in info + info = wallet.getaddressinfo(wallet.getrawchangeaddress()) + assert 'hdseedid' not in info + assert 'hdkeypath' not in info + # The next addresses are HD and should be on different HD chains + info = wallet.getaddressinfo(wallet.getnewaddress()) + ext_id = info['hdseedid'] + assert_equal('m/0\'/0\'/0\'', info['hdkeypath']) + info = wallet.getaddressinfo(wallet.getrawchangeaddress()) + assert_equal(ext_id, info['hdseedid']) + assert_equal('m/0\'/1\'/0\'', info['hdkeypath']) + + self.log.info('KeyMetadata should upgrade when loading into master') + copy_v16() + old_kvs = dump_bdb_kv(v16_3_wallet) + new_kvs = dump_bdb_kv(node_master_wallet) + for k, old_v in old_kvs.items(): + if k.startswith(b'\x07keymeta'): + new_ver, new_create_time, new_kp_str, new_seed_id, new_fpr, new_path_len, new_path, new_has_key_orig = deser_keymeta(BytesIO(new_kvs[k])) + old_ver, old_create_time, old_kp_str, old_seed_id, old_fpr, old_path_len, old_path, old_has_key_orig = deser_keymeta(BytesIO(old_v)) + assert_equal(10, old_ver) + if old_kp_str == b"": # imported things that don't have keymeta (i.e. imported coinbase privkeys) won't be upgraded + assert_equal(new_kvs[k], old_v) + continue + assert_equal(12, new_ver) + assert_equal(new_create_time, old_create_time) + assert_equal(new_kp_str, old_kp_str) + assert_equal(new_seed_id, old_seed_id) + assert_equal(0, old_path_len) + assert_equal(new_path_len, len(new_path)) + assert_equal([], old_path) + assert_equal(False, old_has_key_orig) + assert_equal(True, new_has_key_orig) + + # Check that the path is right + built_path = [] + for s in new_kp_str.decode().split('/')[1:]: + h = 0 + if s[-1] == '\'': + s = s[:-1] + h = 0x80000000 + p = int(s) | h + built_path.append(p) + assert_equal(new_path, built_path) + + self.log.info('Upgrading to NO_DEFAULT_KEY should not remove the defaultkey') + copy_split_hd() + # Check the wallet has a default key initially + old_kvs = dump_bdb_kv(node_master_wallet) + defaultkey = old_kvs[b'\x0adefaultkey'] + # Upgrade the wallet. Should still have the same default key + wallet.upgradewallet(159900) + new_kvs = dump_bdb_kv(node_master_wallet) + up_defaultkey = new_kvs[b'\x0adefaultkey'] + assert_equal(defaultkey, up_defaultkey) + # 0.16.3 doesn't have a default key + v16_3_kvs = dump_bdb_kv(v16_3_wallet) + assert b'\x0adefaultkey' not in v16_3_kvs + if __name__ == '__main__': UpgradeWalletTest().main() diff --git a/test/lint/lint-python.sh b/test/lint/lint-python.sh index 72e8ef7c7d..4fc130497b 100755 --- a/test/lint/lint-python.sh +++ b/test/lint/lint-python.sh @@ -55,6 +55,7 @@ enabled=( F621 # too many expressions in an assignment with star-unpacking F622 # two or more starred expressions in an assignment (a, *b, *c = d) F631 # assertion test is a tuple, which are always True + F632 # use ==/!= to compare str, bytes, and int literals F701 # a break statement outside of a while or for loop F702 # a continue statement outside of a while or for loop F703 # a continue statement in a finally block in a loop diff --git a/test/lint/lint-rpc-help.sh b/test/lint/lint-rpc-help.sh deleted file mode 100755 index faac5d43e2..0000000000 --- a/test/lint/lint-rpc-help.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2018 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# -# Check that all RPC help texts are generated by RPCHelpMan. - -export LC_ALL=C - -EXIT_CODE=0 - -# Assume that all multiline strings passed into a runtime_error are help texts. -# This is potentially fragile, but the linter is only temporary and can safely -# be removed early 2019. - -non_autogenerated_help=$(grep --perl-regexp --null-data --only-matching 'runtime_error\(\n\s*".*\\n"\n' $(git ls-files -- "*.cpp")) -if [[ ${non_autogenerated_help} != "" ]]; then - echo "Must use RPCHelpMan to generate the help for the following RPC methods:" - echo "${non_autogenerated_help}" - echo - EXIT_CODE=1 -fi -exit ${EXIT_CODE} diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh index 9a26cd9c02..351b65dea6 100755 --- a/test/lint/lint-shell.sh +++ b/test/lint/lint-shell.sh @@ -36,7 +36,8 @@ fi SHELLCHECK_CMD=(shellcheck --external-sources --check-sourced) EXCLUDE="--exclude=$(IFS=','; echo "${disabled[*]}")" -if ! "${SHELLCHECK_CMD[@]}" "$EXCLUDE" $(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|secp256k1|univalue)/'); then +SOURCED_FILES=$(git ls-files | xargs gawk '/^# shellcheck shell=/ {print FILENAME} {nextfile}') # Check shellcheck directive used for sourced files +if ! "${SHELLCHECK_CMD[@]}" "$EXCLUDE" $SOURCED_FILES $(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|secp256k1|univalue)/'); then EXIT_CODE=1 fi diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan index 625085c55b..48f81f3dbf 100644 --- a/test/sanitizer_suppressions/tsan +++ b/test/sanitizer_suppressions/tsan @@ -32,7 +32,7 @@ deadlock:CConnman::ForNode deadlock:CConnman::GetNodeStats deadlock:CChainState::ConnectTip deadlock:UpdateTip -deadlock:wallet_tests::CreateWalletFromFile +deadlock:wallet_tests::CreateWallet # WalletBatch (unidentified deadlock) deadlock:WalletBatch @@ -47,3 +47,4 @@ deadlock:src/qt/test/* # External libraries deadlock:libdb race:libzmq +race:epoll_ctl # https://github.com/bitcoin/bitcoin/pull/20218 diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index 75257d886b..e2f3fec851 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -1,8 +1,3 @@ -# -fsanitize=undefined suppressions -# ================================= -float-divide-by-zero:validation.cpp -float-divide-by-zero:wallet/wallet.cpp - # -fsanitize=integer suppressions # =============================== # Unsigned integer overflow occurs when the result of an unsigned integer |