diff options
226 files changed, 9616 insertions, 3680 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index 0d026748b5..bf93d7a990 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,6 +24,7 @@ install: git pull origin master > $null git -c advice.detachedHead=false checkout $env:VCPKG_COMMIT_ID .\bootstrap-vcpkg.bat > $null + Add-Content "C:\tools\vcpkg\triplets\$env:PLATFORM-windows-static.cmake" "set(VCPKG_BUILD_TYPE release)" cd "$env:APPVEYOR_BUILD_FOLDER" before_build: # Powershell block below is to download and extract the Qt static libraries. The pseudo code is: diff --git a/.cirrus.yml b/.cirrus.yml index 237560fc2e..dcd1323291 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -63,7 +63,7 @@ task: FILE_ENV: "./ci/test/00_setup_env_arm.sh" task: - name: 'Win64 [GOAL: deploy] [unit tests, no gui, no boost::process, no functional tests]' + name: 'Win64 [GOAL: deploy] [unit tests, no gui tests, no boost::process, no functional tests]' << : *GLOBAL_TASK_TEMPLATE container: image: ubuntu:bionic @@ -71,7 +71,16 @@ task: FILE_ENV: "./ci/test/00_setup_env_win64.sh" task: - name: 'x86_64 Linux [GOAL: install] [bionic] [C++17, previous releases, uses qt5 dev package and some depends packages] [unsigned char]' + name: '32-bit + dash [GOAL: install] [CentOS 8] [gui]' + << : *GLOBAL_TASK_TEMPLATE + container: + image: centos:8 + env: + PACKAGE_MANAGER_INSTALL: "yum install -y" + FILE_ENV: "./ci/test/00_setup_env_i686_centos.sh" + +task: + name: 'x86_64 Linux [GOAL: install] [bionic] [previous releases, uses qt5 dev package and some depends packages] [unsigned char]' << : *GLOBAL_TASK_TEMPLATE container: image: ubuntu:bionic @@ -122,7 +131,15 @@ task: FILE_ENV: "./ci/test/00_setup_env_native_multiprocess.sh" task: - name: 'macOS 10.12 [GOAL: deploy] [no functional tests]' + name: 'x86_64 Linux [GOAL: install] [bionic] [no wallet]' + << : *GLOBAL_TASK_TEMPLATE + container: + image: ubuntu:bionic + env: + FILE_ENV: "./ci/test/00_setup_env_native_nowallet.sh" + +task: + name: 'macOS 10.14 [GOAL: deploy] [no functional tests]' << : *GLOBAL_TASK_TEMPLATE container: image: ubuntu:bionic @@ -130,7 +147,7 @@ task: FILE_ENV: "./ci/test/00_setup_env_mac.sh" task: - name: 'macOS 10.14 native [GOAL: install] [GUI] [no depends]' + name: 'macOS 10.15 native [GOAL: install] [GUI] [no depends]' macos_brew_addon_script: - brew install boost libevent berkeley-db4 qt miniupnpc ccache zeromq qrencode sqlite libtool automake pkg-config gnu-getopt << : *GLOBAL_TASK_TEMPLATE 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..dd76aaacaf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,20 +57,10 @@ 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: - set -o errexit; source ./ci/lint/05_before_script.sh script: - set -o errexit; source ./ci/lint/06_script.sh - - - stage: test - name: '32-bit + dash [GOAL: install] [CentOS 7] [gui]' - env: >- - FILE_ENV="./ci/test/00_setup_env_i686_centos.sh" - - - stage: test - name: 'x86_64 Linux [GOAL: install] [xenial] [no wallet]' - env: >- - FILE_ENV="./ci/test/00_setup_env_native_nowallet.sh" diff --git a/build-aux/m4/bitcoin_find_bdb48.m4 b/build-aux/m4/bitcoin_find_bdb48.m4 index aa0111e5a2..5fc5b493d3 100644 --- a/build-aux/m4/bitcoin_find_bdb48.m4 +++ b/build-aux/m4/bitcoin_find_bdb48.m4 @@ -6,7 +6,9 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[ AC_ARG_VAR(BDB_CFLAGS, [C compiler flags for BerkeleyDB, bypasses autodetection]) AC_ARG_VAR(BDB_LIBS, [Linker flags for BerkeleyDB, bypasses autodetection]) - if test "x$BDB_CFLAGS" = "x"; then + if test "x$use_bdb" = "xno"; then + use_bdb=no + elif test "x$BDB_CFLAGS" = "x"; then AC_MSG_CHECKING([for Berkeley DB C++ headers]) BDB_CPPFLAGS= bdbpath=X @@ -44,25 +46,30 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[ ],[]) done if test "x$bdbpath" = "xX"; then + use_bdb=no AC_MSG_RESULT([no]) - AC_MSG_ERROR([libdb_cxx headers missing, ]AC_PACKAGE_NAME[ requires this library for wallet functionality (--disable-wallet to disable wallet functionality)]) + AC_MSG_ERROR([libdb_cxx headers missing, ]AC_PACKAGE_NAME[ requires this library for BDB wallet support (--without-bdb to disable BDB wallet support)]) elif test "x$bdb48path" = "xX"; then BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdbpath}],db_cxx) AC_ARG_WITH([incompatible-bdb],[AS_HELP_STRING([--with-incompatible-bdb], [allow using a bdb version other than 4.8])],[ - AC_MSG_WARN([Found Berkeley DB other than 4.8; wallets opened by this build will not be portable!]) + AC_MSG_WARN([Found Berkeley DB other than 4.8; BDB wallets opened by this build will not be portable!]) ],[ - AC_MSG_ERROR([Found Berkeley DB other than 4.8, required for portable wallets (--with-incompatible-bdb to ignore or --disable-wallet to disable wallet functionality)]) + AC_MSG_ERROR([Found Berkeley DB other than 4.8, required for portable BDB wallets (--with-incompatible-bdb to ignore or --without-bdb to disable BDB wallet support)]) ]) + use_bdb=yes else BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdb48path}],db_cxx) bdbpath="${bdb48path}" + use_bdb=yes fi else BDB_CPPFLAGS=${BDB_CFLAGS} fi AC_SUBST(BDB_CPPFLAGS) - if test "x$BDB_LIBS" = "x"; then + if test "x$use_bdb" = "xno"; then + use_bdb=no + elif test "x$BDB_LIBS" = "x"; then # TODO: Ideally this could find the library version and make sure it matches the headers being used for searchlib in db_cxx-4.8 db_cxx db4_cxx; do AC_CHECK_LIB([$searchlib],[main],[ @@ -71,8 +78,12 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[ ]) done if test "x$BDB_LIBS" = "x"; then - AC_MSG_ERROR([libdb_cxx missing, ]AC_PACKAGE_NAME[ requires this library for wallet functionality (--disable-wallet to disable wallet functionality)]) + AC_MSG_ERROR([libdb_cxx missing, ]AC_PACKAGE_NAME[ requires this library for BDB wallet support (--without-bdb to disable BDB wallet support)]) fi fi - AC_SUBST(BDB_LIBS) + if test "x$use_bdb" != "xno"; then + AC_SUBST(BDB_LIBS) + AC_DEFINE([USE_BDB], [1], [Define if BDB support should be compiled in]) + use_bdb=yes + fi ]) diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index 6c7665830b..658dfc5476 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -128,7 +128,6 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)],[-lqxcb -lxcb-static]) AC_DEFINE(QT_QPA_PLATFORM_XCB, 1, [Define this symbol if the qt platform is xcb]) elif test "x$TARGET_OS" = xdarwin; then - AX_CHECK_LINK_FLAG([[-framework IOKit]],[QT_LIBS="$QT_LIBS -framework IOKit"],[AC_MSG_ERROR(could not iokit framework)]) _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)],[-lqcocoa]) AC_DEFINE(QT_QPA_PLATFORM_COCOA, 1, [Define this symbol if the qt platform is cocoa]) elif test "x$TARGET_OS" = xandroid; then @@ -202,7 +201,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ *darwin*) BITCOIN_QT_CHECK([ MOC_DEFS="${MOC_DEFS} -DQ_OS_MAC" - base_frameworks="-framework Foundation -framework ApplicationServices -framework AppKit" + base_frameworks="-framework Foundation -framework AppKit" AX_CHECK_LINK_FLAG([[$base_frameworks]],[QT_LIBS="$QT_LIBS $base_frameworks"],[AC_MSG_ERROR(could not find base frameworks)]) ]) ;; diff --git a/build_msvc/bitcoin_config.h b/build_msvc/bitcoin_config.h index 9d0b50a0b4..53aead38b5 100644 --- a/build_msvc/bitcoin_config.h +++ b/build_msvc/bitcoin_config.h @@ -15,13 +15,10 @@ #define CLIENT_VERSION_IS_RELEASE false /* Major version */ -#define CLIENT_VERSION_MAJOR 0 +#define CLIENT_VERSION_MAJOR 21 /* Minor version */ -#define CLIENT_VERSION_MINOR 20 - -/* Build revision */ -#define CLIENT_VERSION_REVISION 99 +#define CLIENT_VERSION_MINOR 99 /* Copyright holder(s) before %s replacement */ #define COPYRIGHT_HOLDERS "The %s developers" @@ -38,6 +35,12 @@ /* Define to 1 to enable wallet functions */ #define ENABLE_WALLET 1 +/* Define to 1 to enable BDB wallet */ +#define USE_BDB 1 + +/* Define to 1 to enable SQLite wallet */ +#define USE_SQLITE 1 + /* Define to 1 to enable ZMQ functions */ #define ENABLE_ZMQ 1 @@ -253,7 +256,7 @@ #define PACKAGE_NAME "Bitcoin Core" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "Bitcoin Core 0.19.99" +#define PACKAGE_STRING "Bitcoin Core 21.99.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "bitcoin" @@ -262,7 +265,7 @@ #define PACKAGE_URL "https://bitcoincore.org/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "0.19.99" +#define PACKAGE_VERSION "21.99.0" /* Define to necessary symbol if this constant uses a non-standard name on your system. */ diff --git a/build_msvc/bitcoind/bitcoind.vcxproj b/build_msvc/bitcoind/bitcoind.vcxproj index ae24cb100e..48dfafaee0 100644 --- a/build_msvc/bitcoind/bitcoind.vcxproj +++ b/build_msvc/bitcoind/bitcoind.vcxproj @@ -63,6 +63,10 @@ <ReplaceInFile FilePath="$(ConfigIniOut)" Replace="@ENABLE_WALLET_TRUE@" By=""></ReplaceInFile> <ReplaceInFile FilePath="$(ConfigIniOut)" + Replace="@USE_BDB_TRUE@" By=""></ReplaceInFile> + <ReplaceInFile FilePath="$(ConfigIniOut)" + Replace="@USE_SQLITE_TRUE@" By=""></ReplaceInFile> + <ReplaceInFile FilePath="$(ConfigIniOut)" Replace="@BUILD_BITCOIN_CLI_TRUE@" By=""></ReplaceInFile> <ReplaceInFile FilePath="$(ConfigIniOut)" Replace="@BUILD_BITCOIND_TRUE@" By=""></ReplaceInFile> diff --git a/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in b/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in index 9c8279c72a..613d5c7199 100644 --- a/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in +++ b/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in @@ -8,6 +8,9 @@ <ConfigurationType>StaticLibrary</ConfigurationType> </PropertyGroup> <ItemGroup> + <ClCompile Include="..\..\src\wallet\bdb.cpp" /> + <ClCompile Include="..\..\src\wallet\salvage.cpp" /> + <ClCompile Include="..\..\src\wallet\sqlite.cpp" /> @SOURCE_FILES@ </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> diff --git a/ci/test/00_setup_env_i686_centos.sh b/ci/test/00_setup_env_i686_centos.sh index e58003ab19..eaa68b2ded 100644 --- a/ci/test/00_setup_env_i686_centos.sh +++ b/ci/test/00_setup_env_i686_centos.sh @@ -7,9 +7,11 @@ 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" +export TEST_RUNNER_ENV="LC_ALL=en_US.UTF-8" diff --git a/ci/test/00_setup_env_mac.sh b/ci/test/00_setup_env_mac.sh index e4450a65ce..4a022f9b39 100644 --- a/ci/test/00_setup_env_mac.sh +++ b/ci/test/00_setup_env_mac.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_macos_cross export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can cross-compile to macos (bionic is used in the gitian build as well) -export HOST=x86_64-apple-darwin16 +export HOST=x86_64-apple-darwin18 export PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools" export XCODE_VERSION=11.3.1 export XCODE_BUILD_ID=11C505 diff --git a/ci/test/00_setup_env_mac_host.sh b/ci/test/00_setup_env_mac_host.sh index 7c25a34cfe..906f51fc1a 100644 --- a/ci/test/00_setup_env_mac_host.sh +++ b/ci/test/00_setup_env_mac_host.sh @@ -6,7 +6,7 @@ export LC_ALL=C.UTF-8 -export HOST=x86_64-apple-darwin16 +export HOST=x86_64-apple-darwin18 export PIP_PACKAGES="zmq" export GOAL="install" export BITCOIN_CONFIG="--with-gui --enable-reduce-exports --enable-werror --with-boost-process" diff --git a/ci/test/00_setup_env_native_msan.sh b/ci/test/00_setup_env_native_msan.sh index b88ee2b50f..3ce50f816f 100644 --- a/ci/test/00_setup_env_native_msan.sh +++ b/ci/test/00_setup_env_native_msan.sh @@ -15,7 +15,7 @@ export BDB_PREFIX="${BASE_ROOT_DIR}/db4" export CONTAINER_NAME="ci_native_msan" export PACKAGES="clang-9 llvm-9 cmake" -export DEP_OPTS="NO_BDB=1 NO_QT=1 CC='clang' CXX='clang++' CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' boost_cxxflags='-std=c++11 -fvisibility=hidden -fPIC ${MSAN_AND_LIBCXX_FLAGS}' zeromq_cxxflags='-std=c++11 ${MSAN_AND_LIBCXX_FLAGS}'" +export DEP_OPTS="NO_BDB=1 NO_QT=1 CC='clang' CXX='clang++' CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' boost_cxxflags='-std=c++17 -fvisibility=hidden -fPIC ${MSAN_AND_LIBCXX_FLAGS}' zeromq_cxxflags='-std=c++17 ${MSAN_AND_LIBCXX_FLAGS}'" export GOAL="install" export BITCOIN_CONFIG="--enable-wallet --with-sanitizers=memory --with-asm=no --prefix=${BASE_ROOT_DIR}/depends/x86_64-pc-linux-gnu/ CC=clang CXX=clang++ CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' BDB_LIBS='-L${BDB_PREFIX}/lib -ldb_cxx-4.8' BDB_CFLAGS='-I${BDB_PREFIX}/include'" export USE_MEMORY_SANITIZER="true" diff --git a/ci/test/00_setup_env_native_nowallet.sh b/ci/test/00_setup_env_native_nowallet.sh index 0a09bfe230..7ff044c020 100644 --- a/ci/test/00_setup_env_native_nowallet.sh +++ b/ci/test/00_setup_env_native_nowallet.sh @@ -7,8 +7,8 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_nowallet -export DOCKER_NAME_TAG=ubuntu:16.04 # Use xenial to have one config run the tests in python3.5, see doc/dependencies.md -export PACKAGES="python3-zmq clang-3.8 llvm-3.8" # Use clang-3.8 to test C++11 compatibility, see doc/dependencies.md +export DOCKER_NAME_TAG=ubuntu:18.04 # Use bionic to have one config run the tests in python3.6, see doc/dependencies.md +export PACKAGES="python3-zmq clang-5.0 llvm-5.0" # Use clang-5 to test C++17 compatibility, see doc/dependencies.md export DEP_OPTS="NO_WALLET=1" export GOAL="install" -export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-3.8 CXX=clang++-3.8 --with-boost-process" +export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-5.0 CXX=clang++-5.0 --with-boost-process" diff --git a/ci/test/00_setup_env_native_qt5.sh b/ci/test/00_setup_env_native_qt5.sh index 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..f0ed314d19 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -6,9 +6,6 @@ export LC_ALL=C.UTF-8 -if [[ $DOCKER_NAME_TAG == centos* ]]; then - export LC_ALL=en_US.utf8 -fi if [[ $QEMU_USER_CMD == qemu-s390* ]]; then export LC_ALL=C fi @@ -60,8 +57,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/ci/test/05_before_script.sh b/ci/test/05_before_script.sh index 42c244c2f5..d7dd5d9dec 100755 --- a/ci/test/05_before_script.sh +++ b/ci/test/05_before_script.sh @@ -40,7 +40,7 @@ if [ -z "$NO_DEPENDS" ]; then # CentOS has problems building the depends if the config shell is not explicitly set # (i.e. for libevent a Makefile with an empty SHELL variable is generated, leading to # an error as the first command is executed) - SHELL_OPTS="CONFIG_SHELL=/bin/bash" + SHELL_OPTS="LC_ALL=en_US.UTF-8 CONFIG_SHELL=/bin/bash" else SHELL_OPTS="CONFIG_SHELL=" fi diff --git a/configure.ac b/configure.ac index 9a16b7c880..e89d86df8b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,14 +1,13 @@ AC_PREREQ([2.69]) -define(_CLIENT_VERSION_MAJOR, 0) -define(_CLIENT_VERSION_MINOR, 20) -define(_CLIENT_VERSION_REVISION, 99) +define(_CLIENT_VERSION_MAJOR, 21) +define(_CLIENT_VERSION_MINOR, 99) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_RC, 0) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2020) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Bitcoin Core]]) -AC_INIT([Bitcoin Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_REVISION, m4_if(_CLIENT_VERSION_BUILD, [0], [], _CLIENT_VERSION_BUILD))m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/]) +AC_INIT([Bitcoin Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_BUILD)m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/]) AC_CONFIG_SRCDIR([src/validation.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) AC_CONFIG_AUX_DIR([build-aux]) @@ -68,18 +67,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 +96,8 @@ AC_PATH_TOOL(STRIP, strip) AC_PATH_TOOL(GCOV, gcov) AC_PATH_TOOL(LLVM_COV, llvm-cov) AC_PATH_PROG(LCOV, lcov) -dnl Python 3.5 is specified in .python-version and should be used if available, see doc/dependencies.md -AC_PATH_PROGS([PYTHON], [python3.5 python3.6 python3.7 python3.8 python3 python]) +dnl Python 3.6 is specified in .python-version and should be used if available, see doc/dependencies.md +AC_PATH_PROGS([PYTHON], [python3.6 python3.7 python3.8 python3.9 python3 python]) AC_PATH_PROG(GENHTML, genhtml) AC_PATH_PROG([GIT], [git]) AC_PATH_PROG(CCACHE,ccache) @@ -126,7 +115,7 @@ AC_ARG_ENABLE([wallet], [AS_HELP_STRING([--disable-wallet], [disable wallet (enabled by default)])], [enable_wallet=$enableval], - [enable_wallet=yes]) + [enable_wallet=auto]) AC_ARG_WITH([sqlite], [AS_HELP_STRING([--with-sqlite=yes|no|auto], @@ -134,6 +123,12 @@ AC_ARG_WITH([sqlite], [use_sqlite=$withval], [use_sqlite=auto]) +AC_ARG_WITH([bdb], + [AS_HELP_STRING([--without-bdb], + [disable bdb wallet support (default is enabled if wallet is enabled)])], + [use_bdb=$withval], + [use_bdb=auto]) + AC_ARG_WITH([miniupnpc], [AS_HELP_STRING([--with-miniupnpc], [enable UPNP (default is yes if libminiupnpc is found)])], @@ -648,7 +643,7 @@ case $host in bdb_prefix=$($BREW --prefix berkeley-db4 2>/dev/null) qt5_prefix=$($BREW --prefix qt5 2>/dev/null) - if test x$bdb_prefix != x && test "x$BDB_CFLAGS" = "x" && test "x$BDB_LIBS" = "x"; then + if test x$bdb_prefix != x && test "x$BDB_CFLAGS" = "x" && test "x$BDB_LIBS" = "x" && test "$use_bdb" != "no"; then dnl This must precede the call to BITCOIN_FIND_BDB48 below. BDB_CFLAGS="-I$bdb_prefix/include" BDB_LIBS="-L$bdb_prefix/lib -ldb_cxx-4.8" @@ -1248,6 +1243,14 @@ if test x$enable_wallet != xno; then fi fi AC_MSG_RESULT([$use_sqlite]) + + dnl Disable wallet if both --without-bdb and --without-sqlite + if test "x$use_bdb$use_sqlite" = "xnono"; then + if test "x$enable_wallet" = "xyes"; then + AC_MSG_ERROR([wallet functionality requested but no BDB or SQLite support available.]) + fi + enable_wallet=no + fi fi dnl Check for libminiupnpc (optional) @@ -1503,6 +1506,7 @@ AC_MSG_CHECKING([if wallet should be enabled]) if test x$enable_wallet != xno; then AC_MSG_RESULT(yes) AC_DEFINE_UNQUOTED([ENABLE_WALLET],[1],[Define to 1 to enable wallet functions]) + enable_wallet=yes else AC_MSG_RESULT(no) @@ -1602,6 +1606,7 @@ AM_CONDITIONAL([TARGET_LINUX], [test x$TARGET_OS = xlinux]) AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows]) AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes]) AM_CONDITIONAL([USE_SQLITE], [test "x$use_sqlite" = "xyes"]) +AM_CONDITIONAL([USE_BDB], [test "x$use_bdb" = "xyes"]) AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes]) AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes]) AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes]) @@ -1622,7 +1627,6 @@ AM_CONDITIONAL([WORDS_BIGENDIAN],[test x$ac_cv_c_bigendian = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) -AC_DEFINE(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION, [Build revision]) AC_DEFINE(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD, [Version Build]) AC_DEFINE(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE, [Version is release]) AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Copyright year]) @@ -1632,7 +1636,6 @@ define(_COPYRIGHT_HOLDERS_FINAL, [patsubst(_COPYRIGHT_HOLDERS, [%s], [_COPYRIGHT AC_DEFINE(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL", [Copyright holder(s)]) AC_SUBST(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR) AC_SUBST(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR) -AC_SUBST(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION) AC_SUBST(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD) AC_SUBST(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE) AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR) @@ -1668,6 +1671,7 @@ AC_SUBST(SHANI_CXXFLAGS) AC_SUBST(ARM_CRC_CXXFLAGS) AC_SUBST(LIBTOOL_APP_LDFLAGS) AC_SUBST(USE_SQLITE) +AC_SUBST(USE_BDB) AC_SUBST(USE_UPNP) AC_SUBST(USE_QRCODE) AC_SUBST(BOOST_LIBS) @@ -1745,6 +1749,7 @@ echo " multiprocess = $build_multiprocess" echo " with wallet = $enable_wallet" if test "x$enable_wallet" != "xno"; then echo " with sqlite = $use_sqlite" + echo " with bdb = $use_bdb" fi echo " with gui / qt = $bitcoin_enable_qt" if test x$bitcoin_enable_qt != xno; then diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index ec716cf2f3..0e2c5be0fa 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-linux-0.21" +name: "bitcoin-core-linux-22" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index df50f45188..4119e88003 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-osx-0.21" +name: "bitcoin-core-osx-22" enable_cache: true distro: "ubuntu" suites: @@ -37,7 +37,7 @@ script: | set -e -o pipefail WRAP_DIR=$HOME/wrapped - HOSTS="x86_64-apple-darwin16" + HOSTS="x86_64-apple-darwin18" CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage" FAKETIME_HOST_PROGS="" FAKETIME_PROGS="ar ranlib date dmg genisoimage" diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 4d61cded74..fc79745e69 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-win-0.21" +name: "bitcoin-core-win-22" enable_cache: true distro: "ubuntu" suites: 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/README.md b/depends/README.md index 5225a6d5c4..bf8f829848 100644 --- a/depends/README.md +++ b/depends/README.md @@ -25,7 +25,7 @@ Common `host-platform-triplets` for cross compilation are: - `i686-pc-linux-gnu` for Linux 32 bit - `x86_64-pc-linux-gnu` for x86 Linux - `x86_64-w64-mingw32` for Win64 -- `x86_64-apple-darwin16` for macOS +- `x86_64-apple-darwin18` for macOS - `arm-linux-gnueabihf` for Linux ARM 32 bit - `aarch64-linux-gnu` for Linux ARM 64 bit - `powerpc64-linux-gnu` for Linux POWER 64-bit (big endian) 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/hosts/darwin.mk b/depends/hosts/darwin.mk index 6099fd4c71..e9faeba336 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -1,4 +1,4 @@ -OSX_MIN_VERSION=10.12 +OSX_MIN_VERSION=10.14 OSX_SDK_VERSION=10.15.1 XCODE_VERSION=11.3.1 XCODE_BUILD_ID=11C505 diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index 5953341d9f..9e533cc61b 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -11,7 +11,7 @@ $(package)_config_opts=--disable-shared --enable-cxx --disable-replication --ena $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_linux=--with-pic $(package)_cflags+=-Wno-error=implicit-function-declaration -$(package)_cxxflags=-std=c++11 +$(package)_cxxflags=-std=c++17 $(package)_cppflags_mingw32=-DUNICODE -D_UNICODE endef diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index d8bce108b1..ff8a252db9 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,50 +1,45 @@ package=boost -$(package)_version=1_70_0 -$(package)_download_path=https://dl.bintray.com/boostorg/release/1.70.0/source/ +$(package)_version=1_71_0 +$(package)_download_path=https://dl.bintray.com/boostorg/release/$(subst _,.,$($(package)_version))/source/ $(package)_file_name=boost_$($(package)_version).tar.bz2 -$(package)_sha256_hash=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 -$(package)_patches=unused_var_in_process.patch +$(package)_sha256_hash=d73a8da01e8bf8c7eda40b4c84915071a8c8a0df4a6734537ddde4a8580524ee +$(package)_dependencies=native_b2 define $(package)_set_vars $(package)_config_opts_release=variant=release $(package)_config_opts_debug=variant=debug $(package)_config_opts=--layout=tagged --build-type=complete --user-config=user-config.jam -$(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1 +$(package)_config_opts+=threading=multi link=static -sNO_COMPRESSION=1 $(package)_config_opts_linux=target-os=linux threadapi=pthread runtime-link=shared $(package)_config_opts_darwin=target-os=darwin runtime-link=shared $(package)_config_opts_mingw32=target-os=windows binary-format=pe threadapi=win32 runtime-link=static -$(package)_config_opts_x86_64_mingw32=address-model=64 -$(package)_config_opts_i686_mingw32=address-model=32 -$(package)_config_opts_i686_linux=address-model=32 architecture=x86 -$(package)_config_opts_i686_android=address-model=32 -$(package)_config_opts_aarch64_android=address-model=64 -$(package)_config_opts_x86_64_android=address-model=64 -$(package)_config_opts_armv7a_android=address-model=32 -$(package)_toolset_$(host_os)=gcc -$(package)_toolset_darwin=clang +$(package)_config_opts_x86_64=architecture=x86 address-model=64 +$(package)_config_opts_i686=architecture=x86 address-model=32 +$(package)_config_opts_aarch64=address-model=64 +$(package)_config_opts_armv7a=address-model=32 ifneq (,$(findstring clang,$($(package)_cxx))) - $(package)_toolset_$(host_os)=clang +$(package)_toolset_$(host_os)=clang +else +$(package)_toolset_$(host_os)=gcc endif -$(package)_archiver_$(host_os)=$($(package)_ar) $(package)_config_libraries=filesystem,system,thread,test -$(package)_cxxflags=-std=c++11 -fvisibility=hidden +$(package)_cxxflags=-std=c++17 -fvisibility=hidden $(package)_cxxflags_linux=-fPIC $(package)_cxxflags_android=-fPIC endef define $(package)_preprocess_cmds - patch -p1 < $($(package)_patch_dir)/unused_var_in_process.patch && \ - echo "using $($(package)_toolset_$(host_os)) : : $($(package)_cxx) : <cxxflags>\"$($(package)_cxxflags) $($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$($(package)_archiver_$(host_os))\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam + echo "using $($(package)_toolset_$(host_os)) : : $($(package)_cxx) : <cflags>\"$($(package)_cflags)\" <cxxflags>\"$($(package)_cxxflags)\" <compileflags>\"$($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$($(package)_ar)\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam endef define $(package)_config_cmds - ./bootstrap.sh --without-icu --with-libraries=$($(package)_config_libraries) --with-toolset=$($(package)_toolset_$(host_os)) + ./bootstrap.sh --without-icu --with-libraries=$($(package)_config_libraries) --with-toolset=$($(package)_toolset_$(host_os)) --with-bjam=b2 endef define $(package)_build_cmds - ./b2 -d2 -j2 -d1 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) stage + b2 -d2 -j2 -d1 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) stage endef define $(package)_stage_cmds - ./b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) install + b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) install endef diff --git a/depends/packages/native_b2.mk b/depends/packages/native_b2.mk new file mode 100644 index 0000000000..aaa37cdcfa --- /dev/null +++ b/depends/packages/native_b2.mk @@ -0,0 +1,20 @@ +package=native_b2 +$(package)_version=$(boost_version) +$(package)_download_path=$(boost_download_path) +$(package)_file_name=$(boost_file_name) +$(package)_sha256_hash=$(boost_sha256_hash) +$(package)_build_subdir=tools/build/src/engine +ifneq (,$(findstring clang,$($(package)_cxx))) +$(package)_toolset_$(host_os)=clang +else +$(package)_toolset_$(host_os)=gcc +endif + +define $(package)_build_cmds + CXX="$($(package)_cxx)" CXXFLAGS="$($(package)_cxxflags)" ./build.sh "$($(package)_toolset_$(host_os))" +endef + +define $(package)_stage_cmds + mkdir -p "$($(package)_staging_prefix_dir)"/bin/ && \ + cp b2 "$($(package)_staging_prefix_dir)"/bin/ +endef diff --git a/depends/packages/native_biplist.mk b/depends/packages/native_biplist.mk deleted file mode 100644 index c3054cbd1a..0000000000 --- a/depends/packages/native_biplist.mk +++ /dev/null @@ -1,15 +0,0 @@ -package=native_biplist -$(package)_version=1.0.3 -$(package)_download_path=https://bitbucket.org/wooster/biplist/downloads -$(package)_file_name=biplist-$($(package)_version).tar.gz -$(package)_sha256_hash=4c0549764c5fe50b28042ec21aa2e14fe1a2224e239a1dae77d9e7f3932aa4c6 -$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages - -define $(package)_build_cmds - python3 setup.py build -endef - -define $(package)_stage_cmds - mkdir -p $($(package)_install_libdir) && \ - python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir) -endef diff --git a/depends/packages/native_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..4b4cc7d9ff 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -20,7 +20,9 @@ upnp_packages=miniupnpc multiprocess_packages = libmultiprocess capnp multiprocess_native_packages = native_libmultiprocess native_capnp -darwin_native_packages = native_biplist native_ds_store native_mac_alias +darwin_native_packages = native_ds_store native_mac_alias + +$(host_arch)_$(host_os)_native_packages += native_b2 ifneq ($(build_os),darwin) darwin_native_packages += native_cctools native_cdrkit native_libdmg-hfsplus diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 083bc68d66..dd755efcbc 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -12,6 +12,7 @@ $(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch $(package)_patches+= fix_rcc_determinism.patch fix_riscv64_arch.patch xkb-default.patch no-xlib.patch $(package)_patches+= fix_android_qmake_conf.patch fix_android_jni_static.patch dont_hardcode_pwd.patch $(package)_patches+= freetype_back_compat.patch drop_lrelease_dependency.patch fix_powerpc_libpng.patch +$(package)_patches+= fix_mingw_cross_compile.patch fix_qpainter_non_determinism.patch # Update OSX_QT_TRANSLATIONS when this is updated $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) @@ -25,9 +26,10 @@ $(package)_extra_sources += $($(package)_qttools_file_name) define $(package)_set_vars $(package)_config_opts_release = -release +$(package)_config_opts_release += -silent $(package)_config_opts_debug = -debug $(package)_config_opts += -bindir $(build_prefix)/bin -$(package)_config_opts += -c++std c++11 +$(package)_config_opts += -c++std c++1z $(package)_config_opts += -confirm-license $(package)_config_opts += -hostprefix $(build_prefix) $(package)_config_opts += -no-compile-examples @@ -76,7 +78,6 @@ $(package)_config_opts += -qt-pcre $(package)_config_opts += -qt-harfbuzz $(package)_config_opts += -system-zlib $(package)_config_opts += -static -$(package)_config_opts += -silent $(package)_config_opts += -v $(package)_config_opts += -no-feature-bearermanagement $(package)_config_opts += -no-feature-colordialog @@ -124,6 +125,7 @@ $(package)_config_opts_darwin += -device-option MAC_SDK_VERSION=$(OSX_SDK_VERSIO $(package)_config_opts_darwin += -device-option CROSS_COMPILE="$(host)-" $(package)_config_opts_darwin += -device-option MAC_MIN_VERSION=$(OSX_MIN_VERSION) $(package)_config_opts_darwin += -device-option MAC_TARGET=$(host) +$(package)_config_opts_darwin += -device-option XCODE_VERSION=$(XCODE_VERSION) endif $(package)_config_opts_linux = -qt-xkbcommon-x11 @@ -192,33 +194,53 @@ define $(package)_extract_cmds tar --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools endef +# Preprocessing steps work as follows: +# +# 1. Apply our patches to the extracted source. See each patch for more info. +# +# 2. Point to lrelease in qttools/bin/lrelease; otherwise Qt will look for it in +# $(host)/native/bin/lrelease and not find it. +# +# 3. Create a macOS-Clang-Linux mkspec using our mac-qmake.conf. +# +# 4. After making a copy of the mkspec for the linux-arm-gnueabi host, named +# bitcoin-linux-g++, replace instances of linux-arm-gnueabi with $(host). This +# way we can generically support hosts like riscv64-linux-gnu, which Qt doesn't +# ship a mkspec for. See it's usage in config_opts_* above. +# +# 5. Put our C, CXX and LD FLAGS into gcc-base.conf. Only used for non-host builds. +# +# 6. Do similar for the win32-g++ mkspec. +# +# 7. In clang.conf, swap out clang & clang++, for our compiler + flags. See #17466. +# +# 8. Adjust a regex in toolchain.prf, to accomodate Guix's usage of +# CROSS_LIBRARY_PATH. See #15277. define $(package)_preprocess_cmds patch -p1 -i $($(package)_patch_dir)/freetype_back_compat.patch && \ patch -p1 -i $($(package)_patch_dir)/fix_powerpc_libpng.patch && \ - sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \ patch -p1 -i $($(package)_patch_dir)/drop_lrelease_dependency.patch && \ - patch -p1 -i $($(package)_patch_dir)/dont_hardcode_pwd.patch &&\ + patch -p1 -i $($(package)_patch_dir)/dont_hardcode_pwd.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_configure_mac.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_rcc_determinism.patch && \ + patch -p1 -i $($(package)_patch_dir)/xkb-default.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_riscv64_arch.patch && \ + patch -p1 -i $($(package)_patch_dir)/no-xlib.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_mingw_cross_compile.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_qpainter_non_determinism.patch &&\ + sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \ mkdir -p qtbase/mkspecs/macx-clang-linux &&\ - cp -f qtbase/mkspecs/macx-clang/Info.plist.lib qtbase/mkspecs/macx-clang-linux/ &&\ - cp -f qtbase/mkspecs/macx-clang/Info.plist.app qtbase/mkspecs/macx-clang-linux/ &&\ cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\ cp -f $($(package)_patch_dir)/mac-qmake.conf qtbase/mkspecs/macx-clang-linux/qmake.conf && \ cp -r qtbase/mkspecs/linux-arm-gnueabi-g++ qtbase/mkspecs/bitcoin-linux-g++ && \ sed -i.old "s/arm-linux-gnueabi-/$(host)-/g" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \ - patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_configure_mac.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_rcc_determinism.patch &&\ - patch -p1 -i $($(package)_patch_dir)/xkb-default.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch &&\ echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ - patch -p1 -i $($(package)_patch_dir)/fix_riscv64_arch.patch &&\ - patch -p1 -i $($(package)_patch_dir)/no-xlib.patch &&\ - echo "QMAKE_LINK_OBJECT_MAX = 10" >> qtbase/mkspecs/win32-g++/qmake.conf &&\ - echo "QMAKE_LINK_OBJECT_SCRIPT = object_script" >> qtbase/mkspecs/win32-g++/qmake.conf &&\ sed -i.old "s|QMAKE_CFLAGS += |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ sed -i.old "s|QMAKE_CXXFLAGS += |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ sed -i.old "0,/^QMAKE_LFLAGS_/s|^QMAKE_LFLAGS_|!host_build: QMAKE_LFLAGS = $($(package)_ldflags)\n&|" qtbase/mkspecs/win32-g++/qmake.conf && \ diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index c93aa1a74d..3b7f3690a4 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -12,7 +12,7 @@ define $(package)_set_vars $(package)_config_opts += --disable-Werror --disable-drafts --enable-option-checking $(package)_config_opts_linux=--with-pic $(package)_config_opts_android=--with-pic - $(package)_cxxflags=-std=c++11 + $(package)_cxxflags=-std=c++17 endef define $(package)_preprocess_cmds diff --git a/depends/patches/boost/unused_var_in_process.patch b/depends/patches/boost/unused_var_in_process.patch deleted file mode 100644 index 722f7bb5ea..0000000000 --- a/depends/patches/boost/unused_var_in_process.patch +++ /dev/null @@ -1,22 +0,0 @@ -commit dbd95cdaefdea95307d004f019a1c394cf9389f0 -Author: fanquake <fanquake@gmail.com> -Date: Mon Aug 17 20:15:17 2020 +0800 - - Remove unused variable in Boost Process - - This causes issues with our linters / CI. - - Can be removed once depends Boost is 1.71.0 or later. - -diff --git a/boost/process/detail/posix/wait_group.hpp b/boost/process/detail/posix/wait_group.hpp -index 9dc249803..2502d9772 100644 ---- a/boost/process/detail/posix/wait_group.hpp -+++ b/boost/process/detail/posix/wait_group.hpp -@@ -137,7 +137,6 @@ inline bool wait_until( - - do - { -- int ret_sig = 0; - int status; - if ((::waitpid(timeout_pid, &status, WNOHANG) != 0) - && (WIFEXITED(status) || WIFSIGNALED(status))) diff --git a/depends/patches/qt/fix_mingw_cross_compile.patch b/depends/patches/qt/fix_mingw_cross_compile.patch new file mode 100644 index 0000000000..67f76f1d85 --- /dev/null +++ b/depends/patches/qt/fix_mingw_cross_compile.patch @@ -0,0 +1,25 @@ +commit 5a992a549adfe5a587bbcd6cd2b2cee47d236e27 +Author: fanquake <fanquake@gmail.com> +Date: Fri Sep 4 08:13:44 2020 +0800 + + Work around broken mingw cross-compilation + + See upstream issues: + https://bugreports.qt.io/browse/QTBUG-63637 + https://bugreports.qt.io/browse/QTBUG-63659 + https://codereview.qt-project.org/q/8bebded9 + + We should be able to drop this once we are building qt 5.10.1 or later. + + Added in #12971. + +diff --git a/qtbase/mkspecs/win32-g++/qmake.conf b/qtbase/mkspecs/win32-g++/qmake.conf +index e071a0d1..ad229b10 100644 +--- a/qtbase/mkspecs/win32-g++/qmake.conf ++++ b/qtbase/mkspecs/win32-g++/qmake.conf +@@ -87,3 +87,5 @@ QMAKE_NM = $${CROSS_COMPILE}nm -P + include(../common/angle.conf) + + load(qt_config) ++QMAKE_LINK_OBJECT_MAX = 10 ++QMAKE_LINK_OBJECT_SCRIPT = object_script diff --git a/depends/patches/qt/fix_qpainter_non_determinism.patch b/depends/patches/qt/fix_qpainter_non_determinism.patch new file mode 100644 index 0000000000..3cfcc22f03 --- /dev/null +++ b/depends/patches/qt/fix_qpainter_non_determinism.patch @@ -0,0 +1,63 @@ +commit 2a8f7dc6ddfc414a66491522501c1574a1343ee1 +Author: Andrew Chow <achow101-github@achow101.com> +Date: Sat Nov 21 01:11:04 2020 -0500 + + build: Fix determinism issue when building with Clang 8 + + When building Qt with LLVM/Clang 8 under -O3 (the default), we run into + a determinism issue in `qt_interset_spans`. The issue has been fixed for + LLVM/Clang 9, see + https://github.com/llvm/llvm-project/commit/db101864bdc938deb1d63fe4f7da761bd38e5cae + and https://reviews.llvm.org/D64601, however this fix was not backported + to 8.x. Once LLVM/Clang 9 is used, this patch can be dropped. + + The particular issue appears to be an optimization done by -O3 which + adds a temporary variable for `spans->y` in `qt_intersect_spans`. When + it does this, sometimes it chooses to use a 32-bit movs instruction + (movswl), and other times it chooses a 64-bit movs instruction (movswq). + By patching `qt_intersect_spans` to always make a temporary variable for + `spans->y`, we are able to sidestep this problem. + +diff --git a/qtbase/src/gui/painting/qpaintengine_raster.cpp b/qtbase/src/gui/painting/qpaintengine_raster.cpp +index 92ab6e8375..f018009e0b 100644 +--- a/qtbase/src/gui/painting/qpaintengine_raster.cpp ++++ b/qtbase/src/gui/painting/qpaintengine_raster.cpp +@@ -3971,22 +3971,23 @@ static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip, + const QSpan *clipEnd = clip->m_spans + clip->count; + + while (available && spans < end ) { ++ const short spans_y = spans->y; + if (clipSpans >= clipEnd) { + spans = end; + break; + } +- if (clipSpans->y > spans->y) { ++ if (clipSpans->y > spans_y) { + ++spans; + continue; + } +- if (spans->y != clipSpans->y) { +- if (spans->y < clip->count && clip->m_clipLines[spans->y].spans) +- clipSpans = clip->m_clipLines[spans->y].spans; ++ if (spans_y != clipSpans->y) { ++ if (spans_y < clip->count && clip->m_clipLines[spans_y].spans) ++ clipSpans = clip->m_clipLines[spans_y].spans; + else + ++clipSpans; + continue; + } +- Q_ASSERT(spans->y == clipSpans->y); ++ Q_ASSERT(spans_y == clipSpans->y); + + int sx1 = spans->x; + int sx2 = sx1 + spans->len; +@@ -4005,7 +4006,7 @@ static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip, + if (len) { + out->x = qMax(sx1, cx1); + out->len = qMin(sx2, cx2) - out->x; +- out->y = spans->y; ++ out->y = spans_y; + out->coverage = qt_div_255(spans->coverage * clipSpans->coverage); + ++out; + --available; + diff --git a/depends/patches/qt/mac-qmake.conf b/depends/patches/qt/mac-qmake.conf index 4cd96df29f..0142667547 100644 --- a/depends/patches/qt/mac-qmake.conf +++ b/depends/patches/qt/mac-qmake.conf @@ -1,12 +1,12 @@ MAKEFILE_GENERATOR = UNIX -CONFIG += app_bundle incremental global_init_link_order lib_version_first plugin_no_soname absolute_library_soname +CONFIG += app_bundle incremental lib_version_first absolute_library_soname QMAKE_INCREMENTAL_STYLE = sublib include(../common/macx.conf) include(../common/gcc-base-mac.conf) include(../common/clang.conf) include(../common/clang-mac.conf) QMAKE_MAC_SDK_PATH=$${MAC_SDK_PATH} -QMAKE_XCODE_VERSION=4.3 +QMAKE_XCODE_VERSION = $${XCODE_VERSION} QMAKE_XCODE_DEVELOPER_PATH=/Developer QMAKE_MACOSX_DEPLOYMENT_TARGET = $${MAC_MIN_VERSION} QMAKE_MAC_SDK=macosx diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md index 2b051c078c..dccd7b1335 100644 --- a/doc/build-openbsd.md +++ b/doc/build-openbsd.md @@ -15,6 +15,7 @@ pkg_add qt5 # (optional for enabling the GUI) pkg_add autoconf # (select highest version, e.g. 2.69) pkg_add automake # (select highest version, e.g. 1.16) pkg_add python # (select highest version, e.g. 3.8) +pkg_add bash git clone https://github.com/bitcoin/bitcoin.git ``` diff --git a/doc/build-osx.md b/doc/build-osx.md index 2a7d71eea6..0a091f6afd 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -111,6 +111,6 @@ tail -f $HOME/Library/Application\ Support/Bitcoin/debug.log ``` ## Notes -* Tested on OS X 10.12 Sierra through macOS 10.15 Catalina on 64-bit Intel +* Tested on OS X 10.14 Mojave through macOS 11 Big Sur on 64-bit Intel processors only. * Building with downloaded Qt binaries is not officially supported. See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714). diff --git a/doc/build-unix.md b/doc/build-unix.md index ab83ceff3d..cfe3328b45 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -41,7 +41,7 @@ Optional dependencies: Library | Purpose | Description ------------|------------------|---------------------- miniupnpc | UPnP Support | Firewall-jumping support - libdb4.8 | Berkeley DB | Wallet storage (only needed when wallet enabled) + libdb4.8 | Berkeley DB | Optional, wallet storage (only needed when wallet enabled) qt | GUI | GUI toolkit (only needed when GUI enabled) libqrencode | QR codes in GUI | Optional for generating QR codes (only needed when GUI enabled) univalue | Utility | JSON parsing and encoding (bundled version will be used unless --with-system-univalue passed to configure) diff --git a/doc/dependencies.md b/doc/dependencies.md index d1bf4b3a87..76e8910871 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -6,19 +6,19 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct | Dependency | Version used | Minimum required | CVEs | Shared | [Bundled Qt library](https://doc.qt.io/qt-5/configure-options.html#third-party-libraries) | | --- | --- | --- | --- | --- | --- | | Berkeley DB | [4.8.30](https://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html) | 4.8.x | No | | | -| Boost | [1.70.0](https://www.boost.org/users/download/) | [1.58.0](https://github.com/bitcoin/bitcoin/pull/19667) | No | | | -| Clang | | [3.3+](https://releases.llvm.org/download.html) (C++11 support) | | | | +| Boost | [1.71.0](https://www.boost.org/users/download/) | [1.58.0](https://github.com/bitcoin/bitcoin/pull/19667) | No | | | +| Clang | | [5.0+](https://releases.llvm.org/download.html) (C++17 support) | | | | | Expat | [2.2.7](https://libexpat.github.io/) | | No | Yes | | | fontconfig | [2.12.1](https://www.freedesktop.org/software/fontconfig/release/) | | No | Yes | | | FreeType | [2.7.1](https://download.savannah.gnu.org/releases/freetype) | | No | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) (Android only) | -| GCC | | [4.8+](https://gcc.gnu.org/) (C++11 support) | | | | +| GCC | | [7+](https://gcc.gnu.org/) (C++17 support) | | | | | HarfBuzz-NG | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | | libevent | [2.1.11-stable](https://github.com/libevent/libevent/releases) | [2.0.21](https://github.com/bitcoin/bitcoin/pull/18676) | No | | | | libpng | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | | librsvg | | | | | | | MiniUPnPc | [2.0.20180203](https://miniupnp.tuxfamily.org/files) | | No | | | | PCRE | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | -| Python (tests) | | [3.5](https://www.python.org/downloads) | | | | +| Python (tests) | | [3.6](https://www.python.org/downloads) | | | | | qrencode | [3.4.4](https://fukuchi.org/works/qrencode) | | No | | | | Qt | [5.9.8](https://download.qt.io/official_releases/qt/) | [5.5.1](https://github.com/bitcoin/bitcoin/issues/13478) | No | | | | SQLite | [3.32.1](https://sqlite.org/download.html) | [3.7.17](https://github.com/bitcoin/bitcoin/pull/19077) | | | | @@ -33,7 +33,7 @@ Some dependencies are not needed in all configurations. The following are some f #### Options passed to `./configure` * MiniUPnPc is not needed with `--with-miniupnpc=no`. -* Berkeley DB is not needed with `--disable-wallet`. +* Berkeley DB is not needed with `--disable-wallet` or `--without-bdb`. * SQLite is not needed with `--disable-wallet` or `--without-sqlite`. * Qt is not needed with `--without-gui`. * If the qrencode dependency is absent, QR support won't be added. To force an error when that happens, pass `--with-qrencode`. diff --git a/doc/descriptors.md b/doc/descriptors.md index 181ff77e50..63acb9167f 100644 --- a/doc/descriptors.md +++ b/doc/descriptors.md @@ -50,7 +50,7 @@ Output descriptors currently support: - `wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))` describes a P2WSH *2-of-3* multisig output with keys in the specified order. - `sh(wsh(multi(1,03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8,03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)))` describes a P2SH-P2WSH *1-of-3* multisig output with keys in the specified order. - `pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8)` describes a P2PK output with the public key of the specified xpub. -- `pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1'/2)` describes a P2PKH output with child key *1'/2* of the specified xpub. +- `pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1/2)` describes a P2PKH output with child key *1/2* of the specified xpub. - `pkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*)` describes a set of P2PKH outputs, but additionally specifies that the specified xpub is a child of a master with fingerprint `d34db33f`, and derived using path `44'/0'/0'`. - `wsh(multi(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where the first multisig key is the *1/0/`i`* child of the first specified xpub and the second multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default). - `wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where one multisig key is the *1/0/`i`* child of the first specified xpub and the other multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default). The order of public keys in the resulting witnessScripts is determined by the lexicographic order of the public keys at that index. diff --git a/doc/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 0331328ff5..22015fd7a1 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -45,437 +45,59 @@ wallet versions of Bitcoin Core are generally supported. Compatibility ============== -During this release cycle, work has been done to ensure that the codebase is fully -compatible with C++17. The intention is to begin using C++17 features starting -with the 0.22.0 release. This means that a compiler that supports C++17 will be -required to compile 0.22.0. - Bitcoin Core is supported and extensively tested on operating systems -using the Linux kernel, macOS 10.12+, and Windows 7 and newer. Bitcoin +using the Linux kernel, macOS 10.14+, and Windows 7 and newer. Bitcoin Core should also work on most other Unix-like systems but is not as frequently tested on them. It is not recommended to use Bitcoin Core on unsupported systems. -From Bitcoin Core 0.20.0 onwards, macOS versions earlier than 10.12 are no +From Bitcoin Core 0.22.0 onwards, macOS versions earlier than 10.14 are no longer supported. Additionally, Bitcoin Core does not yet change appearance when macOS "dark mode" is activated. -The node's known peers are persisted to disk in a file called `peers.dat`. The -format of this file has been changed in a backwards-incompatible way in order to -accommodate the storage of Tor v3 and other BIP155 addresses. This means that if -the file is modified by 0.21.0 or newer then older versions will not be able to -read it. Those old versions, in the event of a downgrade, will log an error -message "Incorrect keysize in addrman deserialization" 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/doc/release-process.md b/doc/release-process.md index 8191c3034d..cedb36d51d 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -18,10 +18,11 @@ Release Process ### Before every major release * On both the master branch and the new release branch: - - update `CLIENT_VERSION_MINOR` in [`configure.ac`](../configure.ac) - - update `CLIENT_VERSION_MINOR`, `PACKAGE_VERSION`, and `PACKAGE_STRING` in [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h) + - update `CLIENT_VERSION_MAJOR` in [`configure.ac`](../configure.ac) + - update `CLIENT_VERSION_MAJOR`, `PACKAGE_VERSION`, and `PACKAGE_STRING` in [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h) * On the new release branch in [`configure.ac`](../configure.ac) and [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h) (see [this commit](https://github.com/bitcoin/bitcoin/commit/742f7dd)): - - set `CLIENT_VERSION_REVISION` to `0` + - set `CLIENT_VERSION_MINOR` to `0` + - set `CLIENT_VERSION_BUILD` to `0` - set `CLIENT_VERSION_IS_RELEASE` to `true` #### Before branch-off diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in index 3befba3425..207d60aca3 100644 --- a/share/qt/Info.plist.in +++ b/share/qt/Info.plist.in @@ -3,7 +3,7 @@ <plist version="0.9"> <dict> <key>LSMinimumSystemVersion</key> - <string>10.12.0</string> + <string>10.14.0</string> <key>LSArchitecturePriority</key> <array> @@ -17,13 +17,13 @@ <string>APPL</string> <key>NSHumanReadableCopyright</key> - <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@, Copyright © 2009-@COPYRIGHT_YEAR@ @COPYRIGHT_HOLDERS_FINAL@</string> + <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@, Copyright © 2009-@COPYRIGHT_YEAR@ @COPYRIGHT_HOLDERS_FINAL@</string> <key>CFBundleShortVersionString</key> - <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@</string> + <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@</string> <key>CFBundleVersion</key> - <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@</string> + <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@</string> <key>CFBundleSignature</key> <string>????</string> diff --git a/share/setup.nsi.in b/share/setup.nsi.in index 5431909bb2..681f243d04 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -56,7 +56,7 @@ CRCCheck on XPStyle on BrandingText " " ShowInstDetails show -VIProductVersion @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@ +VIProductVersion @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@.0 VIAddVersionKey ProductName "@PACKAGE_NAME@" VIAddVersionKey ProductVersion "@PACKAGE_VERSION@" VIAddVersionKey CompanyName "${COMPANY}" diff --git a/src/Makefile.am b/src/Makefile.am index 67fd402603..4a080ef1fb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,9 +20,8 @@ else LIBUNIVALUE = $(UNIVALUE_LIBS) endif -BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) +BITCOIN_INCLUDES=-I$(builddir) -I$(srcdir)/secp256k1/include $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) -BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS) LIBBITCOIN_SERVER=libbitcoin_server.a @@ -299,14 +298,13 @@ libbitcoin_server_a_SOURCES = \ index/blockfilterindex.cpp \ index/txindex.cpp \ init.cpp \ - interfaces/chain.cpp \ - interfaces/node.cpp \ miner.cpp \ net.cpp \ net_processing.cpp \ node/coin.cpp \ node/coinstats.cpp \ node/context.cpp \ + node/interfaces.cpp \ node/psbt.cpp \ node/transaction.cpp \ node/ui_interface.cpp \ @@ -359,18 +357,16 @@ endif libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(SQLITE_CFLAGS) libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ - interfaces/wallet.cpp \ - wallet/bdb.cpp \ wallet/coincontrol.cpp \ wallet/context.cpp \ wallet/crypter.cpp \ wallet/db.cpp \ wallet/feebumper.cpp \ wallet/fees.cpp \ + wallet/interfaces.cpp \ wallet/load.cpp \ wallet/rpcdump.cpp \ wallet/rpcwallet.cpp \ - wallet/salvage.cpp \ wallet/scriptpubkeyman.cpp \ wallet/wallet.cpp \ wallet/walletdb.cpp \ @@ -381,6 +377,9 @@ libbitcoin_wallet_a_SOURCES = \ if USE_SQLITE libbitcoin_wallet_a_SOURCES += wallet/sqlite.cpp endif +if USE_BDB +libbitcoin_wallet_a_SOURCES += wallet/bdb.cpp wallet/salvage.cpp +endif libbitcoin_wallet_tool_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_wallet_tool_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 9cc383c240..87166ecb79 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -292,15 +292,19 @@ BITCOIN_TESTS =\ if ENABLE_WALLET BITCOIN_TESTS += \ - wallet/test/db_tests.cpp \ wallet/test/psbt_wallet_tests.cpp \ wallet/test/wallet_tests.cpp \ + wallet/test/walletdb_tests.cpp \ wallet/test/wallet_crypto_tests.cpp \ wallet/test/coinselector_tests.cpp \ wallet/test/init_tests.cpp \ wallet/test/ismine_tests.cpp \ wallet/test/scriptpubkeyman_tests.cpp +if USE_BDB +BITCOIN_TESTS += wallet/test/db_tests.cpp +endif + BITCOIN_TEST_SUITE += \ wallet/test/wallet_test_fixture.cpp \ wallet/test/wallet_test_fixture.h \ diff --git a/src/addrman.h b/src/addrman.h index 04dd30b375..9ac67b7af6 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -281,8 +281,18 @@ 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); @@ -704,7 +714,7 @@ public: return vAddr; } - //! Mark an entry as currently-connected-to. + //! Outer function for Connected_() void Connected(const CService &addr, int64_t nTime = GetAdjustedTime()) { LOCK(cs); diff --git a/src/attributes.h b/src/attributes.h index 45099bd8b8..995c24e13f 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -6,17 +6,14 @@ #ifndef BITCOIN_ATTRIBUTES_H #define BITCOIN_ATTRIBUTES_H -#if defined(__has_cpp_attribute) -# if __has_cpp_attribute(nodiscard) -# define NODISCARD [[nodiscard]] -# endif -#endif -#ifndef NODISCARD -# if defined(_MSC_VER) && _MSC_VER >= 1700 -# define NODISCARD _Check_return_ +#if defined(__clang__) +# if __has_attribute(lifetimebound) +# define LIFETIMEBOUND [[clang::lifetimebound]] # else -# define NODISCARD __attribute__((warn_unused_result)) +# define LIFETIMEBOUND # endif +#else +# define LIFETIMEBOUND #endif #endif // BITCOIN_ATTRIBUTES_H diff --git a/src/base58.cpp b/src/base58.cpp index 0dc6044145..780846c6c5 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -35,7 +35,7 @@ static const int8_t mapBase58[256] = { -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, }; -NODISCARD static bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len) +[[nodiscard]] static bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len) { // Skip leading spaces. while (*psz && IsSpace(*psz)) @@ -141,7 +141,7 @@ std::string EncodeBase58Check(Span<const unsigned char> input) return EncodeBase58(vch); } -NODISCARD static bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len) +[[nodiscard]] static bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len) { if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) || (vchRet.size() < 4)) { diff --git a/src/base58.h b/src/base58.h index 468c3e2589..60551a12ae 100644 --- a/src/base58.h +++ b/src/base58.h @@ -29,7 +29,7 @@ std::string EncodeBase58(Span<const unsigned char> input); * Decode a base58-encoded string (str) into a byte vector (vchRet). * return true if decoding is successful. */ -NODISCARD bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len); +[[nodiscard]] bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len); /** * Encode a byte span into a base58-encoded string, including checksum @@ -40,6 +40,6 @@ std::string EncodeBase58Check(Span<const unsigned char> input); * Decode a base58-encoded string (str) that includes a checksum into a byte * vector (vchRet), return true if decoding is successful */ -NODISCARD bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len); +[[nodiscard]] bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len); #endif // BITCOIN_BASE58_H diff --git a/src/bench/prevector.cpp b/src/bench/prevector.cpp index a2dbefa54a..73af244ce0 100644 --- a/src/bench/prevector.cpp +++ b/src/bench/prevector.cpp @@ -9,24 +9,16 @@ #include <bench/bench.h> -// GCC 4.8 is missing some C++11 type_traits, -// https://www.gnu.org/software/gcc/gcc-5/changes.html -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 -#define IS_TRIVIALLY_CONSTRUCTIBLE std::has_trivial_default_constructor -#else -#define IS_TRIVIALLY_CONSTRUCTIBLE std::is_trivially_default_constructible -#endif - struct nontrivial_t { int x; nontrivial_t() :x(-1) {} SERIALIZE_METHODS(nontrivial_t, obj) { READWRITE(obj.x); } }; -static_assert(!IS_TRIVIALLY_CONSTRUCTIBLE<nontrivial_t>::value, +static_assert(!std::is_trivially_default_constructible<nontrivial_t>::value, "expected nontrivial_t to not be trivially constructible"); typedef unsigned char trivial_t; -static_assert(IS_TRIVIALLY_CONSTRUCTIBLE<trivial_t>::value, +static_assert(std::is_trivially_default_constructible<trivial_t>::value, "expected trivial_t to be trivially constructible"); template <typename T> diff --git a/src/bitcoin-cli-res.rc b/src/bitcoin-cli-res.rc index 58f8f1e8a2..405a302261 100644 --- a/src/bitcoin-cli-res.rc +++ b/src/bitcoin-cli-res.rc @@ -1,8 +1,8 @@ #include <windows.h> // needed for VERSIONINFO #include "clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/bitcoin-tx-res.rc b/src/bitcoin-tx-res.rc index 3e49b820bc..b545ce9dbe 100644 --- a/src/bitcoin-tx-res.rc +++ b/src/bitcoin-tx-res.rc @@ -1,8 +1,8 @@ #include <windows.h> // needed for VERSIONINFO #include "clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/bitcoin-wallet-res.rc b/src/bitcoin-wallet-res.rc index e9fa2dbb40..59346ab8f6 100644 --- a/src/bitcoin-wallet-res.rc +++ b/src/bitcoin-wallet-res.rc @@ -1,8 +1,8 @@ #include <windows.h> // needed for VERSIONINFO #include "clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/bitcoind-res.rc b/src/bitcoind-res.rc index 3a64acd5d1..a98b50c899 100644 --- a/src/bitcoind-res.rc +++ b/src/bitcoind-res.rc @@ -1,8 +1,8 @@ #include <windows.h> // needed for VERSIONINFO #include "clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/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/clientversion.cpp b/src/clientversion.cpp index 993967a180..aaf041602b 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -30,8 +30,7 @@ const std::string CLIENT_NAME("Satoshi"); #define BUILD_DESC BUILD_GIT_TAG #define BUILD_SUFFIX "" #else - #define BUILD_DESC "v" STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) \ - "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) + #define BUILD_DESC "v" STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #ifdef BUILD_GIT_COMMIT #define BUILD_SUFFIX "-" BUILD_GIT_COMMIT #elif defined(GIT_COMMIT_ID) @@ -45,10 +44,7 @@ const std::string CLIENT_BUILD(BUILD_DESC BUILD_SUFFIX); static std::string FormatVersion(int nVersion) { - if (nVersion % 100 == 0) - return strprintf("%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100); - else - return strprintf("%d.%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, nVersion % 100); + return strprintf("%d.%d.%d", nVersion / 10000, (nVersion / 100) % 100, nVersion % 100); } std::string FormatFullVersion() diff --git a/src/clientversion.h b/src/clientversion.h index 363094b696..c925b8f084 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -10,7 +10,7 @@ #endif //HAVE_CONFIG_H // Check that required client information is defined -#if !defined(CLIENT_VERSION_MAJOR) || !defined(CLIENT_VERSION_MINOR) || !defined(CLIENT_VERSION_REVISION) || !defined(CLIENT_VERSION_BUILD) || !defined(CLIENT_VERSION_IS_RELEASE) || !defined(COPYRIGHT_YEAR) +#if !defined(CLIENT_VERSION_MAJOR) || !defined(CLIENT_VERSION_MINOR) || !defined(CLIENT_VERSION_BUILD) || !defined(CLIENT_VERSION_IS_RELEASE) || !defined(COPYRIGHT_YEAR) #error Client version information missing: version is not defined by bitcoin-config.h or in any other way #endif @@ -36,9 +36,8 @@ #include <vector> static const int CLIENT_VERSION = - 1000000 * CLIENT_VERSION_MAJOR - + 10000 * CLIENT_VERSION_MINOR - + 100 * CLIENT_VERSION_REVISION + 10000 * CLIENT_VERSION_MAJOR + + 100 * CLIENT_VERSION_MINOR + 1 * CLIENT_VERSION_BUILD; extern const std::string CLIENT_NAME; diff --git a/src/core_io.h b/src/core_io.h index 80ec80cd50..aaee9c445d 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -22,8 +22,8 @@ class UniValue; // core_read.cpp CScript ParseScript(const std::string& s); std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false); -NODISCARD bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true); -NODISCARD bool DecodeHexBlk(CBlock&, const std::string& strHexBlk); +[[nodiscard]] bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true); +[[nodiscard]] bool DecodeHexBlk(CBlock&, const std::string& strHexBlk); bool DecodeHexBlockHeader(CBlockHeader&, const std::string& hex_header); /** diff --git a/src/core_read.cpp b/src/core_read.cpp index 121e62457c..a2eebbd528 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -15,16 +15,15 @@ #include <version.h> #include <boost/algorithm/string/classification.hpp> -#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> #include <algorithm> #include <string> -CScript ParseScript(const std::string& s) -{ - CScript result; +namespace { +opcodetype ParseOpCode(const std::string& s) +{ static std::map<std::string, opcodetype> mapOpNames; if (mapOpNames.empty()) @@ -40,11 +39,23 @@ CScript ParseScript(const std::string& s) continue; mapOpNames[strName] = static_cast<opcodetype>(op); // Convenience: OP_ADD and just ADD are both recognized: - boost::algorithm::replace_first(strName, "OP_", ""); - mapOpNames[strName] = static_cast<opcodetype>(op); + if (strName.compare(0, 3, "OP_") == 0) { // strName starts with "OP_" + mapOpNames[strName.substr(3)] = static_cast<opcodetype>(op); + } } } + auto it = mapOpNames.find(s); + if (it == mapOpNames.end()) throw std::runtime_error("script parse error: unknown opcode"); + return it->second; +} + +} // namespace + +CScript ParseScript(const std::string& s) +{ + CScript result; + std::vector<std::string> words; boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on); @@ -82,14 +93,10 @@ CScript ParseScript(const std::string& s) std::vector<unsigned char> value(w->begin()+1, w->end()-1); result << value; } - else if (mapOpNames.count(*w)) - { - // opcode, e.g. OP_ADD or ADD: - result << mapOpNames[*w]; - } else { - throw std::runtime_error("script parse error"); + // opcode, e.g. OP_ADD or ADD: + result << ParseOpCode(*w); } } diff --git a/src/hash.h b/src/hash.h index 6d876076ee..083ac12523 100644 --- a/src/hash.h +++ b/src/hash.h @@ -197,7 +197,7 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL } /** Single-SHA256 a 32-byte input (represented as uint256). */ -NODISCARD uint256 SHA256Uint256(const uint256& input); +[[nodiscard]] uint256 SHA256Uint256(const uint256& input); unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vDataToHash); diff --git a/src/init.cpp b/src/init.cpp index 495d96f938..9137050323 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -113,7 +113,7 @@ static fs::path GetPidFile(const ArgsManager& args) return AbsPathForConfigVal(fs::path(args.GetArg("-pid", BITCOIN_PID_FILENAME))); } -NODISCARD static bool CreatePidFile(const ArgsManager& args) +[[nodiscard]] static bool CreatePidFile(const ArgsManager& args) { fsbridge::ofstream file{GetPidFile(args)}; if (file) { @@ -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 @@ -1389,16 +1389,9 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA assert(!node.connman); node.connman = MakeUnique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()), args.GetBoolArg("-networkactive", true)); - // Make mempool generally available in the node context. For example the connection manager, wallet, or RPC threads, - // which are all started after this, may use it from the node context. assert(!node.mempool); - node.mempool = MakeUnique<CTxMemPool>(&::feeEstimator); - if (node.mempool) { - int ratio = std::min<int>(std::max<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); - if (ratio != 0) { - node.mempool->setSanityCheck(1.0 / ratio); - } - } + int check_ratio = std::min<int>(std::max<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); + node.mempool = MakeUnique<CTxMemPool>(&::feeEstimator, check_ratio); assert(!node.chainman); node.chainman = &g_chainman; diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp deleted file mode 100644 index 2c5f8627e6..0000000000 --- a/src/interfaces/node.cpp +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (c) 2018-2020 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include <interfaces/node.h> - -#include <addrdb.h> -#include <banman.h> -#include <chain.h> -#include <chainparams.h> -#include <init.h> -#include <interfaces/chain.h> -#include <interfaces/handler.h> -#include <interfaces/wallet.h> -#include <net.h> -#include <net_processing.h> -#include <netaddress.h> -#include <netbase.h> -#include <node/context.h> -#include <node/ui_interface.h> -#include <policy/feerate.h> -#include <policy/fees.h> -#include <policy/settings.h> -#include <primitives/block.h> -#include <rpc/server.h> -#include <shutdown.h> -#include <support/allocators/secure.h> -#include <sync.h> -#include <txmempool.h> -#include <util/check.h> -#include <util/ref.h> -#include <util/system.h> -#include <util/translation.h> -#include <validation.h> -#include <warnings.h> - -#if defined(HAVE_CONFIG_H) -#include <config/bitcoin-config.h> -#endif - -#include <univalue.h> - -#include <boost/signals2/signal.hpp> - -namespace interfaces { -namespace { - -class NodeImpl : public Node -{ -public: - NodeImpl(NodeContext* context) { setContext(context); } - void initLogging() override { InitLogging(*Assert(m_context->args)); } - void initParameterInteraction() override { InitParameterInteraction(*Assert(m_context->args)); } - bilingual_str getWarnings() override { return GetWarnings(true); } - uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); } - bool baseInitialize() override - { - return AppInitBasicSetup(gArgs) && AppInitParameterInteraction(gArgs) && AppInitSanityChecks() && - AppInitLockDataDirectory() && AppInitInterfaces(*m_context); - } - bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override - { - return AppInitMain(m_context_ref, *m_context, tip_info); - } - void appShutdown() override - { - Interrupt(*m_context); - Shutdown(*m_context); - } - void startShutdown() override - { - StartShutdown(); - // Stop RPC for clean shutdown if any of waitfor* commands is executed. - if (gArgs.GetBoolArg("-server", false)) { - InterruptRPC(); - StopRPC(); - } - } - bool shutdownRequested() override { return ShutdownRequested(); } - void mapPort(bool use_upnp) override - { - if (use_upnp) { - StartMapPort(); - } else { - InterruptMapPort(); - StopMapPort(); - } - } - bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); } - size_t getNodeCount(CConnman::NumConnections flags) override - { - return m_context->connman ? m_context->connman->GetNodeCount(flags) : 0; - } - bool getNodesStats(NodesStats& stats) override - { - stats.clear(); - - if (m_context->connman) { - std::vector<CNodeStats> stats_temp; - m_context->connman->GetNodeStats(stats_temp); - - stats.reserve(stats_temp.size()); - for (auto& node_stats_temp : stats_temp) { - stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats()); - } - - // Try to retrieve the CNodeStateStats for each node. - TRY_LOCK(::cs_main, lockMain); - if (lockMain) { - for (auto& node_stats : stats) { - std::get<1>(node_stats) = - GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats)); - } - } - return true; - } - return false; - } - bool getBanned(banmap_t& banmap) override - { - if (m_context->banman) { - m_context->banman->GetBanned(banmap); - return true; - } - return false; - } - bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override - { - if (m_context->banman) { - m_context->banman->Ban(net_addr, ban_time_offset); - return true; - } - return false; - } - bool unban(const CSubNet& ip) override - { - if (m_context->banman) { - m_context->banman->Unban(ip); - return true; - } - return false; - } - bool disconnectByAddress(const CNetAddr& net_addr) override - { - if (m_context->connman) { - return m_context->connman->DisconnectNode(net_addr); - } - return false; - } - bool disconnectById(NodeId id) override - { - if (m_context->connman) { - return m_context->connman->DisconnectNode(id); - } - return false; - } - int64_t getTotalBytesRecv() override { return m_context->connman ? m_context->connman->GetTotalBytesRecv() : 0; } - int64_t getTotalBytesSent() override { return m_context->connman ? m_context->connman->GetTotalBytesSent() : 0; } - size_t getMempoolSize() override { return m_context->mempool ? m_context->mempool->size() : 0; } - size_t getMempoolDynamicUsage() override { return m_context->mempool ? m_context->mempool->DynamicMemoryUsage() : 0; } - bool getHeaderTip(int& height, int64_t& block_time) override - { - LOCK(::cs_main); - if (::pindexBestHeader) { - height = ::pindexBestHeader->nHeight; - block_time = ::pindexBestHeader->GetBlockTime(); - return true; - } - return false; - } - int getNumBlocks() override - { - LOCK(::cs_main); - return ::ChainActive().Height(); - } - uint256 getBestBlockHash() override - { - const CBlockIndex* tip = WITH_LOCK(::cs_main, return ::ChainActive().Tip()); - return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash(); - } - int64_t getLastBlockTime() override - { - LOCK(::cs_main); - if (::ChainActive().Tip()) { - return ::ChainActive().Tip()->GetBlockTime(); - } - return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network - } - double getVerificationProgress() override - { - const CBlockIndex* tip; - { - LOCK(::cs_main); - tip = ::ChainActive().Tip(); - } - return GuessVerificationProgress(Params().TxData(), tip); - } - bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); } - bool getReindex() override { return ::fReindex; } - bool getImporting() override { return ::fImporting; } - void setNetworkActive(bool active) override - { - if (m_context->connman) { - m_context->connman->SetNetworkActive(active); - } - } - bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); } - CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override - { - FeeCalculation fee_calc; - CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative); - if (returned_target) { - *returned_target = fee_calc.returnedTarget; - } - return result; - } - CFeeRate getDustRelayFee() override { return ::dustRelayFee; } - UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override - { - JSONRPCRequest req(m_context_ref); - req.params = params; - req.strMethod = command; - req.URI = uri; - return ::tableRPC.execute(req); - } - std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); } - void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); } - void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); } - bool getUnspentOutput(const COutPoint& output, Coin& coin) override - { - LOCK(::cs_main); - return ::ChainstateActive().CoinsTip().GetCoin(output, coin); - } - WalletClient& walletClient() override - { - return *Assert(m_context->wallet_client); - } - std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override - { - return MakeHandler(::uiInterface.InitMessage_connect(fn)); - } - std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override - { - return MakeHandler(::uiInterface.ThreadSafeMessageBox_connect(fn)); - } - std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override - { - return MakeHandler(::uiInterface.ThreadSafeQuestion_connect(fn)); - } - std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override - { - return MakeHandler(::uiInterface.ShowProgress_connect(fn)); - } - std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override - { - return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn)); - } - std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override - { - return MakeHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn)); - } - std::unique_ptr<Handler> handleNotifyAlertChanged(NotifyAlertChangedFn fn) override - { - return MakeHandler(::uiInterface.NotifyAlertChanged_connect(fn)); - } - std::unique_ptr<Handler> handleBannedListChanged(BannedListChangedFn fn) override - { - return MakeHandler(::uiInterface.BannedListChanged_connect(fn)); - } - std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override - { - return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) { - fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()}, - GuessVerificationProgress(Params().TxData(), block)); - })); - } - std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override - { - return MakeHandler( - ::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) { - fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()}, - /* verification progress is unused when a header was received */ 0); - })); - } - NodeContext* context() override { return m_context; } - void setContext(NodeContext* context) override - { - m_context = context; - if (context) { - m_context_ref.Set(*context); - } else { - m_context_ref.Clear(); - } - } - NodeContext* m_context{nullptr}; - util::Ref m_context_ref; -}; - -} // namespace - -std::unique_ptr<Node> MakeNode(NodeContext* context) { return MakeUnique<NodeImpl>(context); } - -} // namespace interfaces diff --git a/src/net.cpp b/src/net.cpp index cf987b6995..9c6d7b6375 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -629,34 +629,21 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap) } #undef X -/** - * Receive bytes from the buffer and deserialize them into messages. - * - * @param[in] pch A pointer to the raw data - * @param[in] nBytes Size of the data - * @param[out] complete Set True if at least one message has been - * deserialized and is ready to be processed - * @return True if the peer should stay connected, - * False if the peer should be disconnected from. - */ -bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete) +bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete) { complete = false; const auto time = GetTime<std::chrono::microseconds>(); LOCK(cs_vRecv); nLastRecv = std::chrono::duration_cast<std::chrono::seconds>(time).count(); - nRecvBytes += nBytes; - while (nBytes > 0) { + nRecvBytes += msg_bytes.size(); + while (msg_bytes.size() > 0) { // absorb network data - int handled = m_deserializer->Read(pch, nBytes); + int handled = m_deserializer->Read(msg_bytes); if (handled < 0) { // Serious header problem, disconnect from the peer. return false; } - pch += handled; - nBytes -= handled; - if (m_deserializer->Complete()) { // decompose a transport agnostic CNetMessage from the deserializer uint32_t out_err_raw_size{0}; @@ -686,13 +673,13 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete return true; } -int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes) +int V1TransportDeserializer::readHeader(Span<const uint8_t> msg_bytes) { // copy data to temporary parsing buffer unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos; - unsigned int nCopy = std::min(nRemaining, nBytes); + unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size()); - memcpy(&hdrbuf[nHdrPos], pch, nCopy); + memcpy(&hdrbuf[nHdrPos], msg_bytes.data(), nCopy); nHdrPos += nCopy; // if header incomplete, exit @@ -726,18 +713,18 @@ int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes) return nCopy; } -int V1TransportDeserializer::readData(const char *pch, unsigned int nBytes) +int V1TransportDeserializer::readData(Span<const uint8_t> msg_bytes) { unsigned int nRemaining = hdr.nMessageSize - nDataPos; - unsigned int nCopy = std::min(nRemaining, nBytes); + unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size()); if (vRecv.size() < nDataPos + nCopy) { // Allocate up to 256 KiB ahead, but never more than the total message size. vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024)); } - hasher.Write({(const unsigned char*)pch, nCopy}); - memcpy(&vRecv[nDataPos], pch, nCopy); + hasher.Write(msg_bytes.first(nCopy)); + memcpy(&vRecv[nDataPos], msg_bytes.data(), nCopy); nDataPos += nCopy; return nCopy; @@ -1476,18 +1463,18 @@ void CConnman::SocketHandler() if (recvSet || errorSet) { // typical socket buffer is 8K-64K - char pchBuf[0x10000]; + uint8_t pchBuf[0x10000]; int nBytes = 0; { LOCK(pnode->cs_hSocket); if (pnode->hSocket == INVALID_SOCKET) continue; - nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT); + nBytes = recv(pnode->hSocket, (char*)pchBuf, sizeof(pchBuf), MSG_DONTWAIT); } if (nBytes > 0) { bool notify = false; - if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify)) + if (!pnode->ReceiveMsgBytes(Span<const uint8_t>(pchBuf, nBytes), notify)) pnode->CloseSocketDisconnect(); RecordBytesRecv(nBytes); if (notify) { @@ -2445,17 +2432,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); @@ -757,8 +757,8 @@ public: virtual bool Complete() const = 0; // set the serialization context version virtual void SetVersion(int version) = 0; - // read and deserialize data - virtual int Read(const char *data, unsigned int bytes) = 0; + /** read and deserialize data, advances msg_bytes data pointer */ + virtual int Read(Span<const uint8_t>& msg_bytes) = 0; // decomposes a message from the context virtual Optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err) = 0; virtual ~TransportDeserializer() {} @@ -779,8 +779,8 @@ private: unsigned int nDataPos; const uint256& GetMessageHash() const; - int readHeader(const char *pch, unsigned int nBytes); - int readData(const char *pch, unsigned int nBytes); + int readHeader(Span<const uint8_t> msg_bytes); + int readData(Span<const uint8_t> msg_bytes); void Reset() { vRecv.clear(); @@ -814,9 +814,14 @@ public: hdrbuf.SetVersion(nVersionIn); vRecv.SetVersion(nVersionIn); } - int Read(const char *pch, unsigned int nBytes) override { - int ret = in_data ? readData(pch, nBytes) : readHeader(pch, nBytes); - if (ret < 0) Reset(); + int Read(Span<const uint8_t>& msg_bytes) override + { + int ret = in_data ? readData(msg_bytes) : readHeader(msg_bytes); + if (ret < 0) { + Reset(); + } else { + msg_bytes = msg_bytes.subspan(ret); + } return ret; } Optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err_raw_size) override; @@ -1118,7 +1123,16 @@ public: return nRefCount; } - bool ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete); + /** + * Receive bytes from the buffer and deserialize them into messages. + * + * @param[in] msg_bytes The raw data + * @param[out] complete Set True if at least one message has been + * deserialized and is ready to be processed + * @return True if the peer should stay connected, + * False if the peer should be disconnected from. + */ + bool ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete); void SetCommonVersion(int greatest_common_version) { 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/interfaces/chain.cpp b/src/node/interfaces.cpp index 4c5ebe66fc..77a5957a56 100644 --- a/src/interfaces/chain.cpp +++ b/src/node/interfaces.cpp @@ -2,18 +2,25 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <interfaces/chain.h> - +#include <addrdb.h> +#include <banman.h> +#include <boost/signals2/signal.hpp> #include <chain.h> #include <chainparams.h> +#include <init.h> +#include <interfaces/chain.h> #include <interfaces/handler.h> +#include <interfaces/node.h> #include <interfaces/wallet.h> #include <net.h> #include <net_processing.h> +#include <netaddress.h> +#include <netbase.h> #include <node/coin.h> #include <node/context.h> #include <node/transaction.h> #include <node/ui_interface.h> +#include <policy/feerate.h> #include <policy/fees.h> #include <policy/policy.h> #include <policy/rbf.h> @@ -23,20 +30,287 @@ #include <rpc/protocol.h> #include <rpc/server.h> #include <shutdown.h> +#include <support/allocators/secure.h> #include <sync.h> #include <timedata.h> #include <txmempool.h> #include <uint256.h> #include <univalue.h> +#include <util/check.h> +#include <util/ref.h> #include <util/system.h> +#include <util/translation.h> #include <validation.h> #include <validationinterface.h> +#include <warnings.h> + +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif #include <memory> #include <utility> -namespace interfaces { +using interfaces::BlockTip; +using interfaces::Chain; +using interfaces::FoundBlock; +using interfaces::Handler; +using interfaces::MakeHandler; +using interfaces::Node; +using interfaces::WalletClient; + +namespace node { namespace { +class NodeImpl : public Node +{ +public: + NodeImpl(NodeContext* context) { setContext(context); } + void initLogging() override { InitLogging(*Assert(m_context->args)); } + void initParameterInteraction() override { InitParameterInteraction(*Assert(m_context->args)); } + bilingual_str getWarnings() override { return GetWarnings(true); } + uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); } + bool baseInitialize() override + { + return AppInitBasicSetup(gArgs) && AppInitParameterInteraction(gArgs) && AppInitSanityChecks() && + AppInitLockDataDirectory() && AppInitInterfaces(*m_context); + } + bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override + { + return AppInitMain(m_context_ref, *m_context, tip_info); + } + void appShutdown() override + { + Interrupt(*m_context); + Shutdown(*m_context); + } + void startShutdown() override + { + StartShutdown(); + // Stop RPC for clean shutdown if any of waitfor* commands is executed. + if (gArgs.GetBoolArg("-server", false)) { + InterruptRPC(); + StopRPC(); + } + } + bool shutdownRequested() override { return ShutdownRequested(); } + void mapPort(bool use_upnp) override + { + if (use_upnp) { + StartMapPort(); + } else { + InterruptMapPort(); + StopMapPort(); + } + } + bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); } + size_t getNodeCount(CConnman::NumConnections flags) override + { + return m_context->connman ? m_context->connman->GetNodeCount(flags) : 0; + } + bool getNodesStats(NodesStats& stats) override + { + stats.clear(); + + if (m_context->connman) { + std::vector<CNodeStats> stats_temp; + m_context->connman->GetNodeStats(stats_temp); + + stats.reserve(stats_temp.size()); + for (auto& node_stats_temp : stats_temp) { + stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats()); + } + + // Try to retrieve the CNodeStateStats for each node. + TRY_LOCK(::cs_main, lockMain); + if (lockMain) { + for (auto& node_stats : stats) { + std::get<1>(node_stats) = + GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats)); + } + } + return true; + } + return false; + } + bool getBanned(banmap_t& banmap) override + { + if (m_context->banman) { + m_context->banman->GetBanned(banmap); + return true; + } + return false; + } + bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override + { + if (m_context->banman) { + m_context->banman->Ban(net_addr, ban_time_offset); + return true; + } + return false; + } + bool unban(const CSubNet& ip) override + { + if (m_context->banman) { + m_context->banman->Unban(ip); + return true; + } + return false; + } + bool disconnectByAddress(const CNetAddr& net_addr) override + { + if (m_context->connman) { + return m_context->connman->DisconnectNode(net_addr); + } + return false; + } + bool disconnectById(NodeId id) override + { + if (m_context->connman) { + return m_context->connman->DisconnectNode(id); + } + return false; + } + int64_t getTotalBytesRecv() override { return m_context->connman ? m_context->connman->GetTotalBytesRecv() : 0; } + int64_t getTotalBytesSent() override { return m_context->connman ? m_context->connman->GetTotalBytesSent() : 0; } + size_t getMempoolSize() override { return m_context->mempool ? m_context->mempool->size() : 0; } + size_t getMempoolDynamicUsage() override { return m_context->mempool ? m_context->mempool->DynamicMemoryUsage() : 0; } + bool getHeaderTip(int& height, int64_t& block_time) override + { + LOCK(::cs_main); + if (::pindexBestHeader) { + height = ::pindexBestHeader->nHeight; + block_time = ::pindexBestHeader->GetBlockTime(); + return true; + } + return false; + } + int getNumBlocks() override + { + LOCK(::cs_main); + return ::ChainActive().Height(); + } + uint256 getBestBlockHash() override + { + const CBlockIndex* tip = WITH_LOCK(::cs_main, return ::ChainActive().Tip()); + return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash(); + } + int64_t getLastBlockTime() override + { + LOCK(::cs_main); + if (::ChainActive().Tip()) { + return ::ChainActive().Tip()->GetBlockTime(); + } + return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network + } + double getVerificationProgress() override + { + const CBlockIndex* tip; + { + LOCK(::cs_main); + tip = ::ChainActive().Tip(); + } + return GuessVerificationProgress(Params().TxData(), tip); + } + bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); } + bool getReindex() override { return ::fReindex; } + bool getImporting() override { return ::fImporting; } + void setNetworkActive(bool active) override + { + if (m_context->connman) { + m_context->connman->SetNetworkActive(active); + } + } + bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); } + CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override + { + FeeCalculation fee_calc; + CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative); + if (returned_target) { + *returned_target = fee_calc.returnedTarget; + } + return result; + } + CFeeRate getDustRelayFee() override { return ::dustRelayFee; } + UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override + { + JSONRPCRequest req(m_context_ref); + req.params = params; + req.strMethod = command; + req.URI = uri; + return ::tableRPC.execute(req); + } + std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); } + void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); } + void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); } + bool getUnspentOutput(const COutPoint& output, Coin& coin) override + { + LOCK(::cs_main); + return ::ChainstateActive().CoinsTip().GetCoin(output, coin); + } + WalletClient& walletClient() override + { + return *Assert(m_context->wallet_client); + } + std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override + { + return MakeHandler(::uiInterface.InitMessage_connect(fn)); + } + std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override + { + return MakeHandler(::uiInterface.ThreadSafeMessageBox_connect(fn)); + } + std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override + { + return MakeHandler(::uiInterface.ThreadSafeQuestion_connect(fn)); + } + std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override + { + return MakeHandler(::uiInterface.ShowProgress_connect(fn)); + } + std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override + { + return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn)); + } + std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override + { + return MakeHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn)); + } + std::unique_ptr<Handler> handleNotifyAlertChanged(NotifyAlertChangedFn fn) override + { + return MakeHandler(::uiInterface.NotifyAlertChanged_connect(fn)); + } + std::unique_ptr<Handler> handleBannedListChanged(BannedListChangedFn fn) override + { + return MakeHandler(::uiInterface.BannedListChanged_connect(fn)); + } + std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override + { + return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) { + fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()}, + GuessVerificationProgress(Params().TxData(), block)); + })); + } + std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override + { + return MakeHandler( + ::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) { + fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()}, + /* verification progress is unused when a header was received */ 0); + })); + } + NodeContext* context() override { return m_context; } + void setContext(NodeContext* context) override + { + m_context = context; + if (context) { + m_context_ref.Set(*context); + } else { + m_context_ref.Clear(); + } + } + NodeContext* m_context{nullptr}; + util::Ref m_context_ref; +}; bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock) { @@ -411,7 +685,9 @@ public: NodeContext& m_node; }; } // namespace +} // namespace node -std::unique_ptr<Chain> MakeChain(NodeContext& node) { return MakeUnique<ChainImpl>(node); } - +namespace interfaces { +std::unique_ptr<Node> MakeNode(NodeContext* context) { return MakeUnique<node::NodeImpl>(context); } +std::unique_ptr<Chain> MakeChain(NodeContext& context) { return MakeUnique<node::ChainImpl>(context); } } // namespace interfaces diff --git a/src/node/transaction.h b/src/node/transaction.h index 6491700d44..0c016ff04e 100644 --- a/src/node/transaction.h +++ b/src/node/transaction.h @@ -36,6 +36,6 @@ static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE{COIN / 10}; * @param[in] wait_callback wait until callbacks have been processed to avoid stale result due to a sequentially RPC. * return error */ -NODISCARD TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback); +[[nodiscard]] TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback); #endif // BITCOIN_NODE_TRANSACTION_H diff --git a/src/outputtype.h b/src/outputtype.h index 77a16b1d05..bb7f39323b 100644 --- a/src/outputtype.h +++ b/src/outputtype.h @@ -22,7 +22,7 @@ enum class OutputType { extern const std::array<OutputType, 3> OUTPUT_TYPES; -NODISCARD bool ParseOutputType(const std::string& str, OutputType& output_type); +[[nodiscard]] bool ParseOutputType(const std::string& str, OutputType& output_type); const std::string& FormatOutputType(OutputType type); /** diff --git a/src/policy/feerate.cpp b/src/policy/feerate.cpp index a01e259731..04e0e117a5 100644 --- a/src/policy/feerate.cpp +++ b/src/policy/feerate.cpp @@ -38,7 +38,7 @@ CAmount CFeeRate::GetFee(size_t nBytes_) const std::string CFeeRate::ToString(const FeeEstimateMode& fee_estimate_mode) const { switch (fee_estimate_mode) { - case FeeEstimateMode::SAT_B: return strprintf("%d.%03d %s/B", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM); - default: return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT); + case FeeEstimateMode::SAT_VB: return strprintf("%d.%03d %s/vB", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM); + default: return strprintf("%d.%08d %s/kvB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT); } } diff --git a/src/policy/feerate.h b/src/policy/feerate.h index 883940f73c..7c5660ac8a 100644 --- a/src/policy/feerate.h +++ b/src/policy/feerate.h @@ -19,8 +19,8 @@ enum class FeeEstimateMode { UNSET, //!< Use default settings based on other criteria ECONOMICAL, //!< Force estimateSmartFee to use non-conservative estimates CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates - BTC_KB, //!< Use explicit BTC/kB fee given in coin control - SAT_B, //!< Use explicit sat/B fee given in coin control + BTC_KVB, //!< Use BTC/kvB fee rate unit + SAT_VB, //!< Use sat/vB fee rate unit }; /** @@ -39,7 +39,16 @@ public: // We've previously had bugs creep in from silent double->int conversion... static_assert(std::is_integral<I>::value, "CFeeRate should be used without floats"); } - /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/ + /** Constructor for a fee rate in satoshis per kvB (sat/kvB). The size in bytes must not exceed (2^63 - 1). + * + * Passing an nBytes value of COIN (1e8) returns a fee rate in satoshis per vB (sat/vB), + * e.g. (nFeePaid * 1e8 / 1e3) == (nFeePaid / 1e5), + * where 1e5 is the ratio to convert from BTC/kvB to sat/vB. + * + * @param[in] nFeePaid CAmount fee rate to construct with + * @param[in] nBytes size_t bytes (units) to construct with + * @returns fee rate + */ CFeeRate(const CAmount& nFeePaid, size_t nBytes); /** * Return the fee in satoshis for the given size in bytes. @@ -56,7 +65,7 @@ public: friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } friend bool operator!=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK != b.nSatoshisPerK; } CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; } - std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BTC_KB) const; + std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BTC_KVB) const; SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); } }; diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 91997aa883..4e33fd6cb5 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -92,14 +92,15 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR for (const CTxIn& txin : tx.vin) { - // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed - // keys (remember the 520 byte limit on redeemScript size). That works - // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627 - // bytes of scriptSig, which we round off to 1650 bytes for some minor - // future-proofing. That's also enough to spend a 20-of-20 - // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not - // considered standard. - if (txin.scriptSig.size() > 1650) { + // Biggest 'standard' txin involving only keys is a 15-of-15 P2SH + // multisig with compressed keys (remember the 520 byte limit on + // redeemScript size). That works out to a (15*(33+1))+3=513 byte + // redeemScript, 513+1+15*(73+1)+3=1627 bytes of scriptSig, which + // we round off to 1650(MAX_STANDARD_SCRIPTSIG_SIZE) bytes for + // some minor future-proofing. That's also enough to spend a + // 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey + // is not considered standard. + if (txin.scriptSig.size() > MAX_STANDARD_SCRIPTSIG_SIZE) { reason = "scriptsig-size"; return false; } diff --git a/src/policy/policy.h b/src/policy/policy.h index 8090dff4c6..fdbf45a66c 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -44,6 +44,8 @@ static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80; static const unsigned int MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE = 80; /** The maximum size of a standard witnessScript */ static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600; +/** The maximum size of a standard ScriptSig */ +static const unsigned int MAX_STANDARD_SCRIPTSIG_SIZE = 1650; /** Min feerate for defining dust. Historically this has been based on the * minRelayTxFee, however changing the dust limit changes which transactions are * standard and should be done with care and ideally rarely. It makes sense to diff --git a/src/psbt.h b/src/psbt.h index 0951b76f83..b566726ee3 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -398,7 +398,7 @@ struct PartiallySignedTransaction /** Merge psbt into this. The two psbts must have the same underlying CTransaction (i.e. the * same actual Bitcoin transaction.) Returns true if the merge succeeded, false otherwise. */ - NODISCARD bool Merge(const PartiallySignedTransaction& psbt); + [[nodiscard]] bool Merge(const PartiallySignedTransaction& psbt); bool AddInput(const CTxIn& txin, PSBTInput& psbtin); bool AddOutput(const CTxOut& txout, const PSBTOutput& psbtout); PartiallySignedTransaction() {} @@ -605,11 +605,11 @@ bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransacti * @param[in] psbtxs the PSBTs to combine * @return error (OK if we successfully combined the transactions, other error if they were not compatible) */ -NODISCARD TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs); +[[nodiscard]] TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs); //! Decode a base64ed PSBT into a PartiallySignedTransaction -NODISCARD bool DecodeBase64PSBT(PartiallySignedTransaction& decoded_psbt, const std::string& base64_psbt, std::string& error); +[[nodiscard]] bool DecodeBase64PSBT(PartiallySignedTransaction& decoded_psbt, const std::string& base64_psbt, std::string& error); //! Decode a raw (binary blob) PSBT into a PartiallySignedTransaction -NODISCARD bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, const std::string& raw_psbt, std::string& error); +[[nodiscard]] bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, const std::string& raw_psbt, std::string& error); #endif // BITCOIN_PSBT_H diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 3d1963b6e6..3be8b664dd 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -58,14 +58,6 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent, SecureStri ui->passEdit3->hide(); setWindowTitle(tr("Unlock wallet")); break; - case Decrypt: // Ask passphrase - ui->warningLabel->setText(tr("This operation needs your wallet passphrase to decrypt the wallet.")); - ui->passLabel2->hide(); - ui->passEdit2->hide(); - ui->passLabel3->hide(); - ui->passEdit3->hide(); - setWindowTitle(tr("Decrypt wallet")); - break; case ChangePass: // Ask old passphrase + new passphrase x2 setWindowTitle(tr("Change passphrase")); ui->warningLabel->setText(tr("Enter the old passphrase and new passphrase for the wallet.")); @@ -133,8 +125,7 @@ void AskPassphraseDialog::accept() "</b></qt>"); } else { assert(model != nullptr); - if(model->setWalletEncrypted(true, newpass1)) - { + if (model->setWalletEncrypted(newpass1)) { QMessageBox::warning(this, tr("Wallet encrypted"), "<qt>" + tr("Your wallet is now encrypted. ") + encryption_reminder + @@ -144,9 +135,7 @@ void AskPassphraseDialog::accept() "For security reasons, previous backups of the unencrypted wallet file " "will become useless as soon as you start using the new, encrypted wallet.") + "</b></qt>"); - } - else - { + } else { QMessageBox::critical(this, tr("Wallet encryption failed"), tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted.")); } @@ -176,17 +165,6 @@ void AskPassphraseDialog::accept() QMessageBox::critical(this, tr("Wallet unlock failed"), e.what()); } break; - case Decrypt: - if(!model->setWalletEncrypted(false, oldpass)) - { - QMessageBox::critical(this, tr("Wallet decryption failed"), - tr("The passphrase entered for the wallet decryption was incorrect.")); - } - else - { - QDialog::accept(); // Success - } - break; case ChangePass: if(newpass1 == newpass2) { @@ -221,7 +199,6 @@ void AskPassphraseDialog::textChanged() acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); break; case Unlock: // Old passphrase x1 - case Decrypt: acceptable = !ui->passEdit1->text().isEmpty(); break; case ChangePass: // Old passphrase x1, new passphrase x2 diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h index 9557e72936..f3ba882277 100644 --- a/src/qt/askpassphrasedialog.h +++ b/src/qt/askpassphrasedialog.h @@ -26,7 +26,6 @@ public: Encrypt, /**< Ask passphrase twice and encrypt */ Unlock, /**< Ask passphrase and unlock */ ChangePass, /**< Ask old passphrase + new passphrase twice */ - Decrypt /**< Ask passphrase and decrypt wallet */ }; explicit AskPassphraseDialog(Mode mode, QWidget *parent, SecureString* passphrase_out = nullptr); diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 2739b21a9d..2676de96d7 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -11,6 +11,7 @@ #include <QDateTime> #include <QList> +#include <QLocale> #include <QModelIndex> #include <QVariant> @@ -122,7 +123,7 @@ QVariant BanTableModel::data(const QModelIndex &index, int role) const case Bantime: QDateTime date = QDateTime::fromMSecsSinceEpoch(0); date = date.addSecs(rec->banEntry.nBanUntil); - return date.toString(Qt::SystemLocaleLongDate); + return QLocale::system().toString(date, QLocale::LongFormat); } } diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 63b4107f7e..4e1b239bc7 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -263,7 +263,7 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle) void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) { assert(!m_splash); - m_splash = new SplashScreen(nullptr, networkStyle); + m_splash = new SplashScreen(networkStyle); // We don't hold a direct pointer to the splash screen after creation, but the splash // screen will take care of deleting itself when finish() happens. m_splash->show(); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 23370e6ad3..20120285d8 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1311,7 +1311,7 @@ void BitcoinGUI::updateProxyIcon() bool proxy_enabled = clientModel->getProxyInfo(ip_port); if (proxy_enabled) { - if (labelProxyIcon->pixmap() == nullptr) { + if (!GUIUtil::HasPixmap(labelProxyIcon)) { QString ip_port_q = QString::fromStdString(ip_port); labelProxyIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/proxy").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q)); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 912297a74e..17458c5777 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -49,6 +49,7 @@ struct BlockAndHeaderTipInfo; QT_BEGIN_NAMESPACE class QAction; class QComboBox; +class QDateTime; class QMenu; class QProgressBar; class QProgressDialog; 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..3945159c26 100644 --- a/src/qt/createwalletdialog.cpp +++ b/src/qt/createwalletdialog.cpp @@ -35,10 +35,30 @@ CreateWalletDialog::CreateWalletDialog(QWidget* parent) : } }); + 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); + ui->descriptor_checkbox->setToolTip(tr("Compiled without sqlite support (required for descriptor wallets)")); + ui->descriptor_checkbox->setEnabled(false); + ui->descriptor_checkbox->setChecked(false); +#endif +#ifndef USE_BDB + ui->descriptor_checkbox->setEnabled(false); + ui->descriptor_checkbox->setChecked(true); #endif } diff --git a/src/qt/forms/createwalletdialog.ui b/src/qt/forms/createwalletdialog.ui index b592140dd7..ea713e1abd 100644 --- a/src/qt/forms/createwalletdialog.ui +++ b/src/qt/forms/createwalletdialog.ui @@ -38,6 +38,9 @@ <height>24</height> </rect> </property> + <property name="placeholderText"> + <string>Wallet</string> + </property> </widget> <widget class="QLabel" name="label"> <property name="geometry"> @@ -68,17 +71,33 @@ <string>Encrypt Wallet</string> </property> <property name="checked"> - <bool>true</bool> + <bool>false</bool> + </property> + </widget> + <widget class="QLabel" name="advanced_options_label"> + <property name="geometry"> + <rect> + <x>20</x> + <y>90</y> + <width>130</width> + <height>21</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">font-weight:bold;</string> + </property> + <property name="text"> + <string>Advanced options</string> </property> </widget> <widget class="QCheckBox" name="disable_privkeys_checkbox"> <property name="enabled"> - <bool>false</bool> + <bool>true</bool> </property> <property name="geometry"> <rect> <x>20</x> - <y>80</y> + <y>115</y> <width>171</width> <height>22</height> </rect> @@ -94,8 +113,8 @@ <property name="geometry"> <rect> <x>20</x> - <y>110</y> - <width>171</width> + <y>135</y> + <width>220</width> <height>22</height> </rect> </property> @@ -110,7 +129,7 @@ <property name="geometry"> <rect> <x>20</x> - <y>140</y> + <y>155</y> <width>171</width> <height>22</height> </rect> @@ -128,6 +147,7 @@ <tabstop>encrypt_wallet_checkbox</tabstop> <tabstop>disable_privkeys_checkbox</tabstop> <tabstop>blank_wallet_checkbox</tabstop> + <tabstop>descriptor_checkbox</tabstop> </tabstops> <resources/> <connections> diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index d210faec03..139c8e161e 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -109,39 +109,13 @@ </widget> </item> <item row="3" column="0"> - <widget class="QLabel" name="label_berkeleyDBVersion"> - <property name="text"> - <string>Using BerkeleyDB version</string> - </property> - <property name="indent"> - <number>10</number> - </property> - </widget> - </item> - <item row="3" column="1" colspan="2"> - <widget class="QLabel" name="berkeleyDBVersion"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="4" column="0"> <widget class="QLabel" name="label_12"> <property name="text"> <string>Datadir</string> </property> </widget> </item> - <item row="4" column="1" colspan="2"> + <item row="3" column="1" colspan="2"> <widget class="QLabel" name="dataDir"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -163,14 +137,14 @@ </property> </widget> </item> - <item row="5" column="0"> + <item row="4" column="0"> <widget class="QLabel" name="label_11"> <property name="text"> <string>Blocksdir</string> </property> </widget> </item> - <item row="5" column="1" colspan="2"> + <item row="4" column="1" colspan="2"> <widget class="QLabel" name="blocksDir"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -192,14 +166,14 @@ </property> </widget> </item> - <item row="6" column="0"> + <item row="5" column="0"> <widget class="QLabel" name="label_13"> <property name="text"> <string>Startup time</string> </property> </widget> </item> - <item row="6" column="1" colspan="2"> + <item row="5" column="1" colspan="2"> <widget class="QLabel" name="startupTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -215,7 +189,7 @@ </property> </widget> </item> - <item row="7" column="0"> + <item row="6" column="0"> <widget class="QLabel" name="labelNetwork"> <property name="font"> <font> @@ -228,14 +202,14 @@ </property> </widget> </item> - <item row="8" column="0"> + <item row="7" column="0"> <widget class="QLabel" name="label_8"> <property name="text"> <string>Name</string> </property> </widget> </item> - <item row="8" column="1" colspan="2"> + <item row="7" column="1" colspan="2"> <widget class="QLabel" name="networkName"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -251,14 +225,14 @@ </property> </widget> </item> - <item row="9" column="0"> + <item row="8" column="0"> <widget class="QLabel" name="label_7"> <property name="text"> <string>Number of connections</string> </property> </widget> </item> - <item row="9" column="1" colspan="2"> + <item row="8" column="1" colspan="2"> <widget class="QLabel" name="numberOfConnections"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -274,7 +248,7 @@ </property> </widget> </item> - <item row="10" column="0"> + <item row="9" column="0"> <widget class="QLabel" name="label_10"> <property name="font"> <font> @@ -287,14 +261,14 @@ </property> </widget> </item> - <item row="11" column="0"> + <item row="10" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>Current block height</string> </property> </widget> </item> - <item row="11" column="1" colspan="2"> + <item row="10" column="1" colspan="2"> <widget class="QLabel" name="numberOfBlocks"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -310,14 +284,14 @@ </property> </widget> </item> - <item row="12" column="0"> + <item row="11" column="0"> <widget class="QLabel" name="labelLastBlockTime"> <property name="text"> <string>Last block time</string> </property> </widget> </item> - <item row="12" column="1" colspan="2"> + <item row="11" column="1" colspan="2"> <widget class="QLabel" name="lastBlockTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -333,7 +307,7 @@ </property> </widget> </item> - <item row="13" column="0"> + <item row="12" column="0"> <widget class="QLabel" name="labelMempoolTitle"> <property name="font"> <font> @@ -346,14 +320,14 @@ </property> </widget> </item> - <item row="14" column="0"> + <item row="13" column="0"> <widget class="QLabel" name="labelNumberOfTransactions"> <property name="text"> <string>Current number of transactions</string> </property> </widget> </item> - <item row="14" column="1"> + <item row="13" column="1"> <widget class="QLabel" name="mempoolNumberTxs"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -369,14 +343,14 @@ </property> </widget> </item> - <item row="15" column="0"> + <item row="14" column="0"> <widget class="QLabel" name="labelMemoryUsage"> <property name="text"> <string>Memory usage</string> </property> </widget> </item> - <item row="15" column="1"> + <item row="14" column="1"> <widget class="QLabel" name="mempoolSize"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -392,7 +366,7 @@ </property> </widget> </item> - <item row="13" column="2" rowspan="3"> + <item row="12" column="2" rowspan="3"> <layout class="QVBoxLayout" name="verticalLayoutDebugButton"> <property name="spacing"> <number>3</number> @@ -432,7 +406,7 @@ </item> </layout> </item> - <item row="16" column="0"> + <item row="15" column="0"> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 0016fb9739..045c2d3539 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -55,7 +55,7 @@ <item> <widget class="QCheckBox" name="prune"> <property name="toolTip"> - <string>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</string> + <string>Enabling pruning significantly reduces the disk space required to store transactions. All blocks are still fully validated. Reverting this setting requires re-downloading the entire blockchain.</string> </property> <property name="text"> <string>Prune &block storage to</string> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index bab17562a6..53ffb27f50 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -43,6 +43,7 @@ #include <QKeyEvent> #include <QLineEdit> #include <QList> +#include <QLocale> #include <QMenu> #include <QMouseEvent> #include <QProgressDialog> @@ -67,7 +68,7 @@ namespace GUIUtil { QString dateTimeStr(const QDateTime &date) { - return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm"); + return QLocale::system().toString(date.date(), QLocale::ShortFormat) + QString(" ") + date.toString("hh:mm"); } QString dateTimeStr(qint64 nTime) @@ -920,4 +921,35 @@ void PopupMenu(QMenu* menu, const QPoint& point, QAction* at_action) menu->popup(point, at_action); } +QDateTime StartOfDay(const QDate& date) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + return date.startOfDay(); +#else + return QDateTime(date); +#endif +} + +bool HasPixmap(const QLabel* label) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + return !label->pixmap(Qt::ReturnByValue).isNull(); +#else + return label->pixmap() != nullptr; +#endif +} + +QImage GetImage(const QLabel* label) +{ + if (!HasPixmap(label)) { + return QImage(); + } + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + return label->pixmap(Qt::ReturnByValue).toImage(); +#else + return label->pixmap()->toImage(); +#endif +} + } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 2bd94b5eb3..c976b4b4bb 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -289,7 +289,7 @@ namespace GUIUtil /** * Returns the distance in pixels appropriate for drawing a subsequent character after text. * - * In Qt 5.12 and before the QFontMetrics::width() is used and it is deprecated since Qt 13.0. + * In Qt 5.12 and before the QFontMetrics::width() is used and it is deprecated since Qt 5.13. * In Qt 5.11 the QFontMetrics::horizontalAdvance() was introduced. */ int TextWidth(const QFontMetrics& fm, const QString& text); @@ -303,6 +303,44 @@ namespace GUIUtil * Call QMenu::popup() only on supported QT_QPA_PLATFORM. */ void PopupMenu(QMenu* menu, const QPoint& point, QAction* at_action = nullptr); + + /** + * Returns the start-moment of the day in local time. + * + * QDateTime::QDateTime(const QDate& date) is deprecated since Qt 5.15. + * QDate::startOfDay() was introduced in Qt 5.14. + */ + QDateTime StartOfDay(const QDate& date); + + /** + * Returns true if pixmap has been set. + * + * QPixmap* QLabel::pixmap() is deprecated since Qt 5.15. + */ + bool HasPixmap(const QLabel* label); + QImage GetImage(const QLabel* label); + + /** + * Splits the string into substrings wherever separator occurs, and returns + * the list of those strings. Empty strings do not appear in the result. + * + * QString::split() signature differs in different Qt versions: + * - QString::SplitBehavior is deprecated since Qt 5.15 + * - Qt::SplitBehavior was introduced in Qt 5.14 + * If {QString|Qt}::SkipEmptyParts behavior is required, use this + * function instead of QString::split(). + */ + template <typename SeparatorType> + QStringList SplitSkipEmptyParts(const QString& string, const SeparatorType& separator) + { + #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + return string.split(separator, Qt::SkipEmptyParts); + #else + return string.split(separator, QString::SkipEmptyParts); + #endif + } + + } // namespace GUIUtil #endif // BITCOIN_QT_GUIUTIL_H 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/notificator.cpp b/src/qt/notificator.cpp index 4b91c19761..d518a2065c 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -17,12 +17,7 @@ #include <stdint.h> #include <QtDBus> #endif -// Include ApplicationServices.h after QtDbus to avoid redefinition of check(). -// This affects at least OSX 10.6. See /usr/include/AssertMacros.h for details. -// Note: This could also be worked around using: -// #define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 #ifdef Q_OS_MAC -#include <ApplicationServices/ApplicationServices.h> #include <qt/macnotificationhandler.h> #endif diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 7e089b4f95..1603b12a73 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -219,7 +219,7 @@ static ProxySetting GetProxySetting(QSettings &settings, const QString &name) return default_val; } // contains IP at index 0 and port at index 1 - QStringList ip_port = settings.value(name).toString().split(":", QString::SkipEmptyParts); + QStringList ip_port = GUIUtil::SplitSkipEmptyParts(settings.value(name).toString(), ":"); if (ip_port.size() == 2) { return {true, ip_port.at(0), ip_port.at(1)}; } else { // Invalid: return default diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index b536567c8b..1297eb8b75 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -17,6 +17,7 @@ #include <QAbstractItemDelegate> #include <QApplication> +#include <QDateTime> #include <QPainter> #include <QStatusTipEvent> diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 6c2db52f63..86d681aa6f 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -26,7 +26,6 @@ #include <QApplication> #include <QByteArray> #include <QDataStream> -#include <QDateTime> #include <QDebug> #include <QFile> #include <QFileOpenEvent> diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp index 52f1e60957..141f4abb3b 100644 --- a/src/qt/qrimagewidget.cpp +++ b/src/qt/qrimagewidget.cpp @@ -98,15 +98,12 @@ bool QRImageWidget::setQR(const QString& data, const QString& text) QImage QRImageWidget::exportImage() { - if(!pixmap()) - return QImage(); - return pixmap()->toImage(); + return GUIUtil::GetImage(this); } void QRImageWidget::mousePressEvent(QMouseEvent *event) { - if(event->button() == Qt::LeftButton && pixmap()) - { + if (event->button() == Qt::LeftButton && GUIUtil::HasPixmap(this)) { event->accept(); QMimeData *mimeData = new QMimeData; mimeData->setImageData(exportImage()); @@ -121,7 +118,7 @@ void QRImageWidget::mousePressEvent(QMouseEvent *event) void QRImageWidget::saveImage() { - if(!pixmap()) + if (!GUIUtil::HasPixmap(this)) return; QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr); if (!fn.isEmpty()) @@ -132,14 +129,14 @@ void QRImageWidget::saveImage() void QRImageWidget::copyImage() { - if(!pixmap()) + if (!GUIUtil::HasPixmap(this)) return; QApplication::clipboard()->setImage(exportImage()); } void QRImageWidget::contextMenuEvent(QContextMenuEvent *event) { - if(!pixmap()) + if (!GUIUtil::HasPixmap(this)) return; contextMenu->exec(event->globalPos()); } diff --git a/src/qt/res/bitcoin-qt-res.rc b/src/qt/res/bitcoin-qt-res.rc index 94ae256477..e590b407b0 100644 --- a/src/qt/res/bitcoin-qt-res.rc +++ b/src/qt/res/bitcoin-qt-res.rc @@ -4,8 +4,8 @@ IDI_ICON2 ICON DISCARDABLE "icons/bitcoin_testnet.ico" #include <windows.h> // needed for VERSIONINFO #include "../../clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 4c5601242e..236c6e13d5 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -25,10 +25,14 @@ #include <univalue.h> #ifdef ENABLE_WALLET +#ifdef USE_BDB +#include <wallet/bdb.h> +#endif #include <wallet/db.h> #include <wallet/wallet.h> #endif +#include <QDateTime> #include <QFont> #include <QKeyEvent> #include <QMenu> @@ -479,13 +483,6 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty ui->WalletSelector->setVisible(false); ui->WalletSelectorLabel->setVisible(false); - // set library version labels -#ifdef ENABLE_WALLET - ui->berkeleyDBVersion->setText(QString::fromStdString(BerkeleyDatabaseVersion())); -#else - ui->label_berkeleyDBVersion->hide(); - ui->berkeleyDBVersion->hide(); -#endif // Register RPC timer interface rpcTimerInterface = new QtRPCTimerInterface(); // avoid accidentally overwriting an existing, non QTThread @@ -493,9 +490,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty m_node.rpcSetTimerInterfaceIfUnset(rpcTimerInterface); setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS); - - ui->detailWidget->hide(); - ui->peerHeading->setText(tr("Select a peer to view detailed information.")); + updateDetailWidget(); consoleFontSize = settings.value(fontSizeSettingsKey, QFont().pointSize()).toInt(); clear(); @@ -626,7 +621,7 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ connect(disconnectAction, &QAction::triggered, this, &RPCConsole::disconnectSelectedNode); // peer table signal handling - update peer details when selecting new node - connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::peerSelected); + connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::updateDetailWidget); // peer table signal handling - update peer details when new nodes are added to the model connect(model->getPeerTableModel(), &PeerTableModel::layoutChanged, this, &RPCConsole::peerLayoutChanged); // peer table signal handling - cache selected node ids @@ -1021,18 +1016,6 @@ void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut) ui->lblBytesOut->setText(GUIUtil::formatBytes(totalBytesOut)); } -void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelection &deselected) -{ - Q_UNUSED(deselected); - - if (!clientModel || !clientModel->getPeerTableModel() || selected.indexes().isEmpty()) - return; - - const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row()); - if (stats) - updateNodeDetail(stats); -} - void RPCConsole::peerLayoutAboutToChange() { QModelIndexList selected = ui->peerWidget->selectionModel()->selectedIndexes(); @@ -1049,7 +1032,6 @@ void RPCConsole::peerLayoutChanged() if (!clientModel || !clientModel->getPeerTableModel()) return; - const CNodeCombinedStats *stats = nullptr; bool fUnselect = false; bool fReselect = false; @@ -1080,9 +1062,6 @@ void RPCConsole::peerLayoutChanged() fUnselect = true; fReselect = true; } - - // get fresh stats on the detail node. - stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow); } if (fUnselect && selectedRow >= 0) { @@ -1097,12 +1076,20 @@ void RPCConsole::peerLayoutChanged() } } - if (stats) - updateNodeDetail(stats); + updateDetailWidget(); } -void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats) +void RPCConsole::updateDetailWidget() { + QModelIndexList selected_rows; + auto selection_model = ui->peerWidget->selectionModel(); + if (selection_model) selected_rows = selection_model->selectedRows(); + if (!clientModel || !clientModel->getPeerTableModel() || selected_rows.size() != 1) { + ui->detailWidget->hide(); + ui->peerHeading->setText(tr("Select a peer to view detailed information.")); + return; + } + const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected_rows.first().row()); // update the detail ui with latest node information QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " "); peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid)); @@ -1260,8 +1247,7 @@ void RPCConsole::clearSelectedNode() { ui->peerWidget->selectionModel()->clearSelection(); cachedNodeids.clear(); - ui->detailWidget->hide(); - ui->peerHeading->setText(tr("Select a peer to view detailed information.")); + updateDetailWidget(); } void RPCConsole::showOrHideBanTableIfRequired() diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 280c5bd71a..8fea08ab5c 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -28,6 +28,7 @@ namespace Ui { } QT_BEGIN_NAMESPACE +class QDateTime; class QMenu; class QItemSelection; QT_END_NAMESPACE @@ -94,6 +95,8 @@ private Q_SLOTS: void showOrHideBanTableIfRequired(); /** clear the selected node */ void clearSelectedNode(); + /** show detailed information on ui about selected node */ + void updateDetailWidget(); public Q_SLOTS: void clear(bool clearHistory = true); @@ -115,8 +118,6 @@ public Q_SLOTS: void browseHistory(int offset); /** Scroll console view to end */ void scrollToEnd(); - /** Handle selection of peer in peers list */ - void peerSelected(const QItemSelection &selected, const QItemSelection &deselected); /** Handle selection caching before update */ void peerLayoutAboutToChange(); /** Handle updated peer information */ @@ -137,8 +138,6 @@ Q_SIGNALS: private: void startExecutor(); void setTrafficGraphRange(int mins); - /** show detailed information on ui about selected node */ - void updateNodeDetail(const CNodeCombinedStats *stats); enum ColumnWidths { diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 50a1ea6936..8a62c64d79 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -173,8 +173,15 @@ void SendCoinsDialog::setModel(WalletModel *_model) } connect(ui->confTargetSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::updateSmartFeeLabel); connect(ui->confTargetSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::coinControlUpdateLabels); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + connect(ui->groupFee, &QButtonGroup::idClicked, this, &SendCoinsDialog::updateFeeSectionControls); + connect(ui->groupFee, &QButtonGroup::idClicked, this, &SendCoinsDialog::coinControlUpdateLabels); +#else connect(ui->groupFee, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::updateFeeSectionControls); connect(ui->groupFee, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::coinControlUpdateLabels); +#endif + connect(ui->customFee, &BitcoinAmountField::valueChanged, this, &SendCoinsDialog::coinControlUpdateLabels); connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::updateSmartFeeLabel); connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::coinControlUpdateLabels); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index f00f086d1e..5796a6ef56 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -25,8 +25,8 @@ #include <QScreen> -SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) : - QWidget(nullptr, f), curAlignment(0) +SplashScreen::SplashScreen(const NetworkStyle* networkStyle) + : QWidget(), curAlignment(0) { // set reference point, paddings int paddingRight = 50; diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index a0cd677d3d..d49fd87055 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -28,7 +28,7 @@ class SplashScreen : public QWidget Q_OBJECT public: - explicit SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle); + explicit SplashScreen(const NetworkStyle *networkStyle); ~SplashScreen(); void setNode(interfaces::Node& node); diff --git a/src/qt/test/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/transactionview.cpp b/src/qt/transactionview.cpp index 54ecfc38ec..e14e22e9de 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -237,7 +237,7 @@ void TransactionView::setModel(WalletModel *_model) if (_model->getOptionsModel()) { // Add third party transaction URLs to context menu - QStringList listUrls = _model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts); + QStringList listUrls = GUIUtil::SplitSkipEmptyParts(_model->getOptionsModel()->getThirdPartyTxUrls(), "|"); for (int i = 0; i < listUrls.size(); ++i) { QString url = listUrls[i].trimmed(); @@ -275,30 +275,30 @@ void TransactionView::chooseDate(int idx) break; case Today: transactionProxyModel->setDateRange( - QDateTime(current), + GUIUtil::StartOfDay(current), TransactionFilterProxy::MAX_DATE); break; case ThisWeek: { // Find last Monday QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1)); transactionProxyModel->setDateRange( - QDateTime(startOfWeek), + GUIUtil::StartOfDay(startOfWeek), TransactionFilterProxy::MAX_DATE); } break; case ThisMonth: transactionProxyModel->setDateRange( - QDateTime(QDate(current.year(), current.month(), 1)), + GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1)), TransactionFilterProxy::MAX_DATE); break; case LastMonth: transactionProxyModel->setDateRange( - QDateTime(QDate(current.year(), current.month(), 1).addMonths(-1)), - QDateTime(QDate(current.year(), current.month(), 1))); + GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1).addMonths(-1)), + GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1))); break; case ThisYear: transactionProxyModel->setDateRange( - QDateTime(QDate(current.year(), 1, 1)), + GUIUtil::StartOfDay(QDate(current.year(), 1, 1)), TransactionFilterProxy::MAX_DATE); break; case Range: @@ -583,8 +583,8 @@ void TransactionView::dateRangeChanged() if(!transactionProxyModel) return; transactionProxyModel->setDateRange( - QDateTime(dateFrom->date()), - QDateTime(dateTo->date()).addDays(1)); + GUIUtil::StartOfDay(dateFrom->date()), + GUIUtil::StartOfDay(dateTo->date()).addDays(1)); } void TransactionView::focusTransaction(const QModelIndex &idx) diff --git a/src/qt/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/script/descriptor.cpp b/src/script/descriptor.cpp index 6c0a98cca2..8d8fa185ba 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -731,7 +731,7 @@ enum class ParseScriptContext { }; /** Parse a key path, being passed a split list of elements (the first element is ignored). */ -NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error) +[[nodiscard]] bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error) { for (size_t i = 1; i < split.size(); ++i) { Span<const char> elem = split[i]; diff --git a/src/span.h b/src/span.h index 4afb383a59..830164514b 100644 --- a/src/span.h +++ b/src/span.h @@ -18,6 +18,16 @@ #define ASSERT_IF_DEBUG(x) #endif +#if defined(__clang__) +#if __has_attribute(lifetimebound) +#define SPAN_ATTR_LIFETIMEBOUND [[clang::lifetimebound]] +#else +#define SPAN_ATTR_LIFETIMEBOUND +#endif +#else +#define SPAN_ATTR_LIFETIMEBOUND +#endif + /** A Span is an object that can refer to a contiguous sequence of objects. * * It implements a subset of C++20's std::span. @@ -84,6 +94,14 @@ class Span C* m_data; std::size_t m_size; + template <class T> + struct is_Span_int : public std::false_type {}; + template <class T> + struct is_Span_int<Span<T>> : public std::true_type {}; + template <class T> + struct is_Span : public is_Span_int<typename std::remove_cv<T>::type>{}; + + public: constexpr Span() noexcept : m_data(nullptr), m_size(0) {} @@ -134,8 +152,19 @@ public: * To prevent surprises, only Spans for constant value types are supported when passing in temporaries. * Note that this restriction does not exist when converting arrays or other Spans (see above). */ - template <typename V, typename std::enable_if<(std::is_const<C>::value || std::is_lvalue_reference<V>::value) && std::is_convertible<typename std::remove_pointer<decltype(std::declval<V&>().data())>::type (*)[], C (*)[]>::value && std::is_convertible<decltype(std::declval<V&>().size()), std::size_t>::value, int>::type = 0> - constexpr Span(V&& v) noexcept : m_data(v.data()), m_size(v.size()) {} + template <typename V> + constexpr Span(V& other SPAN_ATTR_LIFETIMEBOUND, + typename std::enable_if<!is_Span<V>::value && + std::is_convertible<typename std::remove_pointer<decltype(std::declval<V&>().data())>::type (*)[], C (*)[]>::value && + std::is_convertible<decltype(std::declval<V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr) + : m_data(other.data()), m_size(other.size()){} + + template <typename V> + constexpr Span(const V& other SPAN_ATTR_LIFETIMEBOUND, + typename std::enable_if<!is_Span<V>::value && + std::is_convertible<typename std::remove_pointer<decltype(std::declval<const V&>().data())>::type (*)[], C (*)[]>::value && + std::is_convertible<decltype(std::declval<const V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr) + : m_data(other.data()), m_size(other.size()){} constexpr C* data() const noexcept { return m_data; } constexpr C* begin() const noexcept { return m_data; } @@ -192,9 +221,9 @@ public: /** MakeSpan for arrays: */ template <typename A, int N> Span<A> constexpr MakeSpan(A (&a)[N]) { return Span<A>(a, N); } /** MakeSpan for temporaries / rvalue references, only supporting const output. */ -template <typename V> constexpr auto MakeSpan(V&& v) -> typename std::enable_if<!std::is_lvalue_reference<V>::value, Span<const typename std::remove_pointer<decltype(v.data())>::type>>::type { return std::forward<V>(v); } +template <typename V> constexpr auto MakeSpan(V&& v SPAN_ATTR_LIFETIMEBOUND) -> typename std::enable_if<!std::is_lvalue_reference<V>::value, Span<const typename std::remove_pointer<decltype(v.data())>::type>>::type { return std::forward<V>(v); } /** MakeSpan for (lvalue) references, supporting mutable output. */ -template <typename V> constexpr auto MakeSpan(V& v) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; } +template <typename V> constexpr auto MakeSpan(V& v SPAN_ATTR_LIFETIMEBOUND) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; } /** Pop the last element off a span, and return a reference to that element. */ template <typename T> diff --git a/src/sync.cpp b/src/sync.cpp index 322198a852..2e431720e6 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -13,10 +13,14 @@ #include <util/strencodings.h> #include <util/threadnames.h> +#include <boost/thread/mutex.hpp> + #include <map> +#include <mutex> #include <set> #include <system_error> #include <thread> +#include <type_traits> #include <unordered_map> #include <utility> #include <vector> @@ -135,16 +139,50 @@ static void potential_deadlock_detected(const LockPair& mismatch, const LockStac throw std::logic_error(strprintf("potential deadlock detected: %s -> %s -> %s", mutex_b, mutex_a, mutex_b)); } -static void push_lock(void* c, const CLockLocation& locklocation) +static void double_lock_detected(const void* mutex, LockStack& lock_stack) { + LogPrintf("DOUBLE LOCK DETECTED\n"); + LogPrintf("Lock order:\n"); + for (const LockStackItem& i : lock_stack) { + if (i.first == mutex) { + LogPrintf(" (*)"); /* Continued */ + } + LogPrintf(" %s\n", i.second.ToString()); + } + if (g_debug_lockorder_abort) { + tfm::format(std::cerr, "Assertion failed: detected double lock at %s:%i, details in debug log.\n", __FILE__, __LINE__); + abort(); + } + throw std::logic_error("double lock detected"); +} + +template <typename MutexType> +static void push_lock(MutexType* c, const CLockLocation& locklocation) +{ + constexpr bool is_recursive_mutex = + std::is_base_of<RecursiveMutex, MutexType>::value || + std::is_base_of<std::recursive_mutex, MutexType>::value; + LockData& lockdata = GetLockData(); std::lock_guard<std::mutex> lock(lockdata.dd_mutex); LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()]; lock_stack.emplace_back(c, locklocation); - for (const LockStackItem& i : lock_stack) { - if (i.first == c) - break; + for (size_t j = 0; j < lock_stack.size() - 1; ++j) { + const LockStackItem& i = lock_stack[j]; + if (i.first == c) { + if (is_recursive_mutex) { + break; + } + // It is not a recursive mutex and it appears in the stack two times: + // at position `j` and at the end (which we added just before this loop). + // Can't allow locking the same (non-recursive) mutex two times from the + // same thread as that results in an undefined behavior. + auto lock_stack_copy = lock_stack; + lock_stack.pop_back(); + double_lock_detected(c, lock_stack_copy); + // double_lock_detected() does not return. + } const LockPair p1 = std::make_pair(i.first, c); if (lockdata.lockorders.count(p1)) @@ -175,10 +213,16 @@ static void pop_lock() } } -void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry) +template <typename MutexType> +void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry) { push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry, util::ThreadGetInternalName())); } +template void EnterCritical(const char*, const char*, int, Mutex*, bool); +template void EnterCritical(const char*, const char*, int, RecursiveMutex*, bool); +template void EnterCritical(const char*, const char*, int, std::mutex*, bool); +template void EnterCritical(const char*, const char*, int, std::recursive_mutex*, bool); +template void EnterCritical(const char*, const char*, int, boost::mutex*, bool); void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) { diff --git a/src/sync.h b/src/sync.h index 41f4e43bdd..0948083c7f 100644 --- a/src/sync.h +++ b/src/sync.h @@ -48,7 +48,8 @@ LEAVE_CRITICAL_SECTION(mutex); // no RAII /////////////////////////////// #ifdef DEBUG_LOCKORDER -void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false); +template <typename MutexType> +void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false); void LeaveCritical(); void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line); std::string LocksHeld(); @@ -66,7 +67,8 @@ bool LockStackEmpty(); */ extern bool g_debug_lockorder_abort; #else -inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {} +template <typename MutexType> +inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {} inline void LeaveCritical() {} inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {} template <typename MutexType> @@ -135,7 +137,7 @@ class SCOPED_LOCKABLE UniqueLock : public Base private: void Enter(const char* pszName, const char* pszFile, int nLine) { - EnterCritical(pszName, pszFile, nLine, (void*)(Base::mutex())); + EnterCritical(pszName, pszFile, nLine, Base::mutex()); #ifdef DEBUG_LOCKCONTENTION if (!Base::try_lock()) { PrintLockContention(pszName, pszFile, nLine); @@ -148,7 +150,7 @@ private: bool TryEnter(const char* pszName, const char* pszFile, int nLine) { - EnterCritical(pszName, pszFile, nLine, (void*)(Base::mutex()), true); + EnterCritical(pszName, pszFile, nLine, Base::mutex(), true); Base::try_lock(); if (!Base::owns_lock()) LeaveCritical(); @@ -205,7 +207,7 @@ public: ~reverse_lock() { templock.swap(lock); - EnterCritical(lockname.c_str(), file.c_str(), line, (void*)lock.mutex()); + EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex()); lock.lock(); } @@ -236,7 +238,7 @@ using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove #define ENTER_CRITICAL_SECTION(cs) \ { \ - EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \ + EnterCritical(#cs, __FILE__, __LINE__, &cs); \ (cs).lock(); \ } diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index e20900ed13..c16519a6b1 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(BinaryOperatorTest) BOOST_CHECK(a <= a); BOOST_CHECK(b >= a); BOOST_CHECK(b >= b); - // a should be 0.00000002 BTC/kB now + // a should be 0.00000002 BTC/kvB now a += a; BOOST_CHECK(a == b); } @@ -107,7 +107,9 @@ BOOST_AUTO_TEST_CASE(ToStringTest) { CFeeRate feeRate; feeRate = CFeeRate(1); - BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kB"); + BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeEstimateMode::BTC_KVB), "0.00000001 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeEstimateMode::SAT_VB), "0.001 sat/vB"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index d519eca859..3f7c5e99ee 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -6,6 +6,9 @@ #include <util/strencodings.h> #include <boost/test/unit_test.hpp> +#include <string> + +using namespace std::literals; BOOST_FIXTURE_TEST_SUITE(base32_tests, BasicTestingSetup) @@ -26,14 +29,14 @@ BOOST_AUTO_TEST_CASE(base32_testvectors) // Decoding strings with embedded NUL characters should fail bool failure; - (void)DecodeBase32(std::string("invalid", 7), &failure); - BOOST_CHECK_EQUAL(failure, true); - (void)DecodeBase32(std::string("AWSX3VPP", 8), &failure); - BOOST_CHECK_EQUAL(failure, false); - (void)DecodeBase32(std::string("AWSX3VPP\0invalid", 16), &failure); - BOOST_CHECK_EQUAL(failure, true); - (void)DecodeBase32(std::string("AWSX3VPPinvalid", 15), &failure); - BOOST_CHECK_EQUAL(failure, true); + (void)DecodeBase32("invalid\0"s, &failure); // correct size, invalid due to \0 + BOOST_CHECK(failure); + (void)DecodeBase32("AWSX3VPP"s, &failure); // valid + BOOST_CHECK(!failure); + (void)DecodeBase32("AWSX3VPP\0invalid"s, &failure); // correct size, invalid due to \0 + BOOST_CHECK(failure); + (void)DecodeBase32("AWSX3VPPinvalid"s, &failure); // invalid size + BOOST_CHECK(failure); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 6a636f2574..e55d6b3b19 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -12,7 +12,9 @@ #include <univalue.h> #include <boost/test/unit_test.hpp> +#include <string> +using namespace std::literals; extern UniValue read_json(const std::string& jsondata); @@ -58,14 +60,14 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58) BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest); } - BOOST_CHECK(!DecodeBase58("invalid", result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("invalid"), result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("\0invalid", 8), result, 100)); + BOOST_CHECK(!DecodeBase58("invalid"s, result, 100)); + BOOST_CHECK(!DecodeBase58("invalid\0"s, result, 100)); + BOOST_CHECK(!DecodeBase58("\0invalid"s, result, 100)); - BOOST_CHECK(DecodeBase58(std::string("good", 4), result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("bad0IOl", 7), result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("goodbad0IOl", 11), result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("good\0bad0IOl", 12), result, 100)); + BOOST_CHECK(DecodeBase58("good"s, result, 100)); + BOOST_CHECK(!DecodeBase58("bad0IOl"s, result, 100)); + BOOST_CHECK(!DecodeBase58("goodbad0IOl"s, result, 100)); + BOOST_CHECK(!DecodeBase58("good\0bad0IOl"s, result, 100)); // check that DecodeBase58 skips whitespace, but still fails with unexpected non-whitespace at the end. BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result, 3)); @@ -73,10 +75,10 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58) std::vector<unsigned char> expected = ParseHex("971a55"); BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end()); - BOOST_CHECK(DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh", 21), result, 100)); - BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oi", 21), result, 100)); - BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh0IOl", 25), result, 100)); - BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh\00IOl", 26), result, 100)); + BOOST_CHECK(DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh"s, result, 100)); + BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oi"s, result, 100)); + BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh0IOl"s, result, 100)); + BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh\0" "0IOl"s, result, 100)); } BOOST_AUTO_TEST_CASE(base58_random_encode_decode) diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 5927eab6cf..bb8d102bd0 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -6,6 +6,9 @@ #include <util/strencodings.h> #include <boost/test/unit_test.hpp> +#include <string> + +using namespace std::literals; BOOST_FIXTURE_TEST_SUITE(base64_tests, BasicTestingSetup) @@ -23,14 +26,14 @@ BOOST_AUTO_TEST_CASE(base64_testvectors) // Decoding strings with embedded NUL characters should fail bool failure; - (void)DecodeBase64(std::string("invalid", 7), &failure); - BOOST_CHECK_EQUAL(failure, true); - (void)DecodeBase64(std::string("nQB/pZw=", 8), &failure); - BOOST_CHECK_EQUAL(failure, false); - (void)DecodeBase64(std::string("nQB/pZw=\0invalid", 16), &failure); - BOOST_CHECK_EQUAL(failure, true); - (void)DecodeBase64(std::string("nQB/pZw=invalid", 15), &failure); - BOOST_CHECK_EQUAL(failure, true); + (void)DecodeBase64("invalid\0"s, &failure); + BOOST_CHECK(failure); + (void)DecodeBase64("nQB/pZw="s, &failure); + BOOST_CHECK(!failure); + (void)DecodeBase64("nQB/pZw=\0invalid"s, &failure); + BOOST_CHECK(failure); + (void)DecodeBase64("nQB/pZw=invalid\0"s, &failure); + BOOST_CHECK(failure); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 173ec5e3d9..6bfcf242d0 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -38,7 +38,7 @@ class CCoinsViewTest : public CCoinsView std::map<COutPoint, Coin> map_; public: - NODISCARD bool GetCoin(const COutPoint& outpoint, Coin& coin) const override + [[nodiscard]] bool GetCoin(const COutPoint& outpoint, Coin& coin) const override { std::map<COutPoint, Coin>::const_iterator it = map_.find(outpoint); if (it == map_.end()) { diff --git a/src/test/fuzz/addition_overflow.cpp b/src/test/fuzz/addition_overflow.cpp index a455992b13..7350ec7838 100644 --- a/src/test/fuzz/addition_overflow.cpp +++ b/src/test/fuzz/addition_overflow.cpp @@ -14,7 +14,7 @@ #if __has_builtin(__builtin_add_overflow) #define HAVE_BUILTIN_ADD_OVERFLOW #endif -#elif defined(__GNUC__) && (__GNUC__ >= 5) +#elif defined(__GNUC__) #define HAVE_BUILTIN_ADD_OVERFLOW #endif diff --git a/src/test/fuzz/multiplication_overflow.cpp b/src/test/fuzz/multiplication_overflow.cpp index a4b158c18b..08dc660a19 100644 --- a/src/test/fuzz/multiplication_overflow.cpp +++ b/src/test/fuzz/multiplication_overflow.cpp @@ -14,7 +14,7 @@ #if __has_builtin(__builtin_mul_overflow) #define HAVE_BUILTIN_MUL_OVERFLOW #endif -#elif defined(__GNUC__) && (__GNUC__ >= 5) +#elif defined(__GNUC__) #define HAVE_BUILTIN_MUL_OVERFLOW #endif diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index c61d406291..a0c8b7aac5 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -128,7 +128,7 @@ void test_one_input(const std::vector<uint8_t>& buffer) case 11: { const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider); bool complete; - node.ReceiveMsgBytes((const char*)b.data(), b.size(), complete); + node.ReceiveMsgBytes(b, complete); break; } } diff --git a/src/test/fuzz/p2p_transport_deserializer.cpp b/src/test/fuzz/p2p_transport_deserializer.cpp index 7e216e16fe..7a6236efac 100644 --- a/src/test/fuzz/p2p_transport_deserializer.cpp +++ b/src/test/fuzz/p2p_transport_deserializer.cpp @@ -21,15 +21,12 @@ void test_one_input(const std::vector<uint8_t>& buffer) { // Construct deserializer, with a dummy NodeId V1TransportDeserializer deserializer{Params(), (NodeId)0, SER_NETWORK, INIT_PROTO_VERSION}; - const char* pch = (const char*)buffer.data(); - size_t n_bytes = buffer.size(); - while (n_bytes > 0) { - const int handled = deserializer.Read(pch, n_bytes); + Span<const uint8_t> msg_bytes{buffer}; + while (msg_bytes.size() > 0) { + const int handled = deserializer.Read(msg_bytes); if (handled < 0) { break; } - pch += handled; - n_bytes -= handled; if (deserializer.Complete()) { const std::chrono::microseconds m_time{std::numeric_limits<int64_t>::max()}; uint32_t out_err_raw_size{0}; diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index 452651d93f..cf666a8b93 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -35,23 +35,23 @@ #include <string> #include <vector> -NODISCARD inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept +[[nodiscard]] inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept { const std::string s = fuzzed_data_provider.ConsumeRandomLengthString(max_length); return {s.begin(), s.end()}; } -NODISCARD inline std::vector<bool> ConsumeRandomLengthBitVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept +[[nodiscard]] inline std::vector<bool> ConsumeRandomLengthBitVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept { return BytesToBits(ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length)); } -NODISCARD inline CDataStream ConsumeDataStream(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept +[[nodiscard]] inline CDataStream ConsumeDataStream(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept { return {ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length), SER_NETWORK, INIT_PROTO_VERSION}; } -NODISCARD inline std::vector<std::string> ConsumeRandomLengthStringVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16, const size_t max_string_length = 16) noexcept +[[nodiscard]] inline std::vector<std::string> ConsumeRandomLengthStringVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16, const size_t max_string_length = 16) noexcept { const size_t n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size); std::vector<std::string> r; @@ -62,7 +62,7 @@ NODISCARD inline std::vector<std::string> ConsumeRandomLengthStringVector(Fuzzed } template <typename T> -NODISCARD inline std::vector<T> ConsumeRandomLengthIntegralVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16) noexcept +[[nodiscard]] inline std::vector<T> ConsumeRandomLengthIntegralVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16) noexcept { const size_t n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size); std::vector<T> r; @@ -73,7 +73,7 @@ NODISCARD inline std::vector<T> ConsumeRandomLengthIntegralVector(FuzzedDataProv } template <typename T> -NODISCARD inline std::optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept +[[nodiscard]] inline std::optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept { const std::vector<uint8_t> buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length); CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION}; @@ -86,17 +86,17 @@ NODISCARD inline std::optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzz return obj; } -NODISCARD inline opcodetype ConsumeOpcodeType(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline opcodetype ConsumeOpcodeType(FuzzedDataProvider& fuzzed_data_provider) noexcept { return static_cast<opcodetype>(fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, MAX_OPCODE)); } -NODISCARD inline CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider) noexcept { return fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, MAX_MONEY); } -NODISCARD inline int64_t ConsumeTime(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline int64_t ConsumeTime(FuzzedDataProvider& fuzzed_data_provider) noexcept { // Avoid t=0 (1970-01-01T00:00:00Z) since SetMockTime(0) is a no-op. static const int64_t time_min = ParseISO8601DateTime("1970-01-01T00:00:01Z"); @@ -104,18 +104,18 @@ NODISCARD inline int64_t ConsumeTime(FuzzedDataProvider& fuzzed_data_provider) n return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(time_min, time_max); } -NODISCARD inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept { const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider); return {b.begin(), b.end()}; } -NODISCARD inline CScriptNum ConsumeScriptNum(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline CScriptNum ConsumeScriptNum(FuzzedDataProvider& fuzzed_data_provider) noexcept { return CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()}; } -NODISCARD inline uint160 ConsumeUInt160(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline uint160 ConsumeUInt160(FuzzedDataProvider& fuzzed_data_provider) noexcept { const std::vector<uint8_t> v160 = fuzzed_data_provider.ConsumeBytes<uint8_t>(160 / 8); if (v160.size() != 160 / 8) { @@ -124,7 +124,7 @@ NODISCARD inline uint160 ConsumeUInt160(FuzzedDataProvider& fuzzed_data_provider return uint160{v160}; } -NODISCARD inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept { const std::vector<uint8_t> v256 = fuzzed_data_provider.ConsumeBytes<uint8_t>(256 / 8); if (v256.size() != 256 / 8) { @@ -133,12 +133,12 @@ NODISCARD inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider return uint256{v256}; } -NODISCARD inline arith_uint256 ConsumeArithUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline arith_uint256 ConsumeArithUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept { return UintToArith256(ConsumeUInt256(fuzzed_data_provider)); } -NODISCARD inline CTxMemPoolEntry ConsumeTxMemPoolEntry(FuzzedDataProvider& fuzzed_data_provider, const CTransaction& tx) noexcept +[[nodiscard]] inline CTxMemPoolEntry ConsumeTxMemPoolEntry(FuzzedDataProvider& fuzzed_data_provider, const CTransaction& tx) noexcept { // Avoid: // policy/feerate.cpp:28:34: runtime error: signed integer overflow: 34873208148477500 * 1000 cannot be represented in type 'long' @@ -153,7 +153,7 @@ NODISCARD inline CTxMemPoolEntry ConsumeTxMemPoolEntry(FuzzedDataProvider& fuzze return CTxMemPoolEntry{MakeTransactionRef(tx), fee, time, entry_height, spends_coinbase, sig_op_cost, {}}; } -NODISCARD inline CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_data_provider) noexcept { CTxDestination tx_destination; switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 5)) { @@ -191,7 +191,7 @@ NODISCARD inline CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_ } template <typename T> -NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept +[[nodiscard]] bool MultiplicationOverflow(const T i, const T j) noexcept { static_assert(std::is_integral<T>::value, "Integral required."); if (std::numeric_limits<T>::is_signed) { @@ -214,7 +214,7 @@ NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept } template <class T> -NODISCARD bool AdditionOverflow(const T i, const T j) noexcept +[[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept { static_assert(std::is_integral<T>::value, "Integral required."); if (std::numeric_limits<T>::is_signed) { @@ -224,7 +224,7 @@ NODISCARD bool AdditionOverflow(const T i, const T j) noexcept return std::numeric_limits<T>::max() - i < j; } -NODISCARD inline bool ContainsSpentInput(const CTransaction& tx, const CCoinsViewCache& inputs) noexcept +[[nodiscard]] inline bool ContainsSpentInput(const CTransaction& tx, const CCoinsViewCache& inputs) noexcept { for (const CTxIn& tx_in : tx.vin) { const Coin& coin = inputs.AccessCoin(tx_in.prevout); @@ -239,7 +239,7 @@ NODISCARD inline bool ContainsSpentInput(const CTransaction& tx, const CCoinsVie * Returns a byte vector of specified size regardless of the number of remaining bytes available * from the fuzzer. Pads with zero value bytes if needed to achieve the specified size. */ -NODISCARD inline std::vector<uint8_t> ConsumeFixedLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t length) noexcept +[[nodiscard]] inline std::vector<uint8_t> ConsumeFixedLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t length) noexcept { std::vector<uint8_t> result(length); const std::vector<uint8_t> random_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(length); @@ -420,7 +420,7 @@ public: } }; -NODISCARD inline FuzzedFileProvider ConsumeFile(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline FuzzedFileProvider ConsumeFile(FuzzedDataProvider& fuzzed_data_provider) noexcept { return {fuzzed_data_provider}; } @@ -441,7 +441,7 @@ public: } }; -NODISCARD inline FuzzedAutoFileProvider ConsumeAutoFile(FuzzedDataProvider& fuzzed_data_provider) noexcept +[[nodiscard]] inline FuzzedAutoFileProvider ConsumeAutoFile(FuzzedDataProvider& fuzzed_data_provider) noexcept { return {fuzzed_data_provider}; } diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 37eca8b7ef..b23fec9b95 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -25,6 +25,8 @@ #include <memory> #include <string> +using namespace std::literals; + class CAddrManSerializationMock : public CAddrMan { public: @@ -106,8 +108,8 @@ BOOST_AUTO_TEST_CASE(caddrdb_read) BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false)); BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false)); BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false)); - BOOST_CHECK(Lookup(std::string("250.7.3.3", 9), addr3, 9999, false)); - BOOST_CHECK(!Lookup(std::string("250.7.3.3\0example.com", 21), addr3, 9999, false)); + BOOST_CHECK(Lookup("250.7.3.3"s, addr3, 9999, false)); + BOOST_CHECK(!Lookup("250.7.3.3\0example.com"s, addr3, 9999, false)); // Add three addresses to new table. CService source; diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index f5d26fafef..ac4db3a5b6 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -16,6 +16,8 @@ #include <boost/test/unit_test.hpp> +using namespace std::literals; + BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup) static CNetAddr ResolveIP(const std::string& ip) @@ -431,20 +433,20 @@ BOOST_AUTO_TEST_CASE(netpermissions_test) BOOST_AUTO_TEST_CASE(netbase_dont_resolve_strings_with_embedded_nul_characters) { CNetAddr addr; - BOOST_CHECK(LookupHost(std::string("127.0.0.1", 9), addr, false)); - BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0", 10), addr, false)); - BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0example.com", 21), addr, false)); - BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0example.com\0", 22), addr, false)); + BOOST_CHECK(LookupHost("127.0.0.1"s, addr, false)); + BOOST_CHECK(!LookupHost("127.0.0.1\0"s, addr, false)); + BOOST_CHECK(!LookupHost("127.0.0.1\0example.com"s, addr, false)); + BOOST_CHECK(!LookupHost("127.0.0.1\0example.com\0"s, addr, false)); CSubNet ret; - BOOST_CHECK(LookupSubNet(std::string("1.2.3.0/24", 10), ret)); - BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0", 11), ret)); - BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0example.com", 22), ret)); - BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0example.com\0", 23), ret)); + BOOST_CHECK(LookupSubNet("1.2.3.0/24"s, ret)); + BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0"s, ret)); + BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com"s, ret)); + BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com\0"s, ret)); // We only do subnetting for IPv4 and IPv6 - BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion", 22), ret)); - BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0", 23), ret)); - BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0example.com", 34), ret)); - BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0example.com\0", 35), ret)); + BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion"s, ret)); + BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0"s, ret)); + BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com"s, ret)); + BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com\0"s, ret)); } // Since CNetAddr (un)ser is tested separately in net_tests.cpp here we only diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp index 19029ebd3c..6c14867211 100644 --- a/src/test/sync_tests.cpp +++ b/src/test/sync_tests.cpp @@ -6,6 +6,9 @@ #include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> + +#include <mutex> namespace { template <typename MutexType> @@ -29,6 +32,38 @@ void TestPotentialDeadLockDetected(MutexType& mutex1, MutexType& mutex2) BOOST_CHECK(!error_thrown); #endif } + +#ifdef DEBUG_LOCKORDER +template <typename MutexType> +void TestDoubleLock2(MutexType& m) +{ + ENTER_CRITICAL_SECTION(m); + LEAVE_CRITICAL_SECTION(m); +} + +template <typename MutexType> +void TestDoubleLock(bool should_throw) +{ + const bool prev = g_debug_lockorder_abort; + g_debug_lockorder_abort = false; + + MutexType m; + ENTER_CRITICAL_SECTION(m); + if (should_throw) { + BOOST_CHECK_EXCEPTION( + TestDoubleLock2(m), std::logic_error, [](const std::logic_error& e) { + return strcmp(e.what(), "double lock detected") == 0; + }); + } else { + BOOST_CHECK_NO_THROW(TestDoubleLock2(m)); + } + LEAVE_CRITICAL_SECTION(m); + + BOOST_CHECK(LockStackEmpty()); + + g_debug_lockorder_abort = prev; +} +#endif /* DEBUG_LOCKORDER */ } // namespace BOOST_FIXTURE_TEST_SUITE(sync_tests, BasicTestingSetup) @@ -55,4 +90,24 @@ BOOST_AUTO_TEST_CASE(potential_deadlock_detected) #endif } +/* Double lock would produce an undefined behavior. Thus, we only do that if + * DEBUG_LOCKORDER is activated to detect it. We don't want non-DEBUG_LOCKORDER + * build to produce tests that exhibit known undefined behavior. */ +#ifdef DEBUG_LOCKORDER +BOOST_AUTO_TEST_CASE(double_lock_mutex) +{ + TestDoubleLock<Mutex>(true /* should throw */); +} + +BOOST_AUTO_TEST_CASE(double_lock_boost_mutex) +{ + TestDoubleLock<boost::mutex>(true /* should throw */); +} + +BOOST_AUTO_TEST_CASE(double_lock_recursive_mutex) +{ + TestDoubleLock<RecursiveMutex>(false /* should not throw */); +} +#endif /* DEBUG_LOCKORDER */ + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp index 09f2f1807f..847a490e03 100644 --- a/src/test/util/net.cpp +++ b/src/test/util/net.cpp @@ -7,9 +7,9 @@ #include <chainparams.h> #include <net.h> -void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const +void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const { - assert(node.ReceiveMsgBytes(pch, nBytes, complete)); + assert(node.ReceiveMsgBytes(msg_bytes, complete)); if (complete) { size_t nSizeAdded = 0; auto it(node.vRecvMsg.begin()); @@ -29,11 +29,11 @@ void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const { - std::vector<unsigned char> ser_msg_header; + std::vector<uint8_t> ser_msg_header; node.m_serializer->prepareForTransport(ser_msg, ser_msg_header); bool complete; - NodeReceiveMsgBytes(node, (const char*)ser_msg_header.data(), ser_msg_header.size(), complete); - NodeReceiveMsgBytes(node, (const char*)ser_msg.data.data(), ser_msg.data.size(), complete); + NodeReceiveMsgBytes(node, ser_msg_header, complete); + NodeReceiveMsgBytes(node, ser_msg.data, complete); return complete; } diff --git a/src/test/util/net.h b/src/test/util/net.h index ca8cb7fad5..1208e92762 100644 --- a/src/test/util/net.h +++ b/src/test/util/net.h @@ -25,7 +25,7 @@ struct ConnmanTestMsg : public CConnman { void ProcessMessagesOnce(CNode& node) { m_msgproc->ProcessMessages(&node, flagInterruptMsgProc); } - void NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const; + void NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const; bool ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const; }; diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 2d3137e1e2..adf5970206 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -141,8 +141,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const pblocktree.reset(new CBlockTreeDB(1 << 20, true)); - m_node.mempool = MakeUnique<CTxMemPool>(&::feeEstimator); - m_node.mempool->setSanityCheck(1.0); + m_node.mempool = MakeUnique<CTxMemPool>(&::feeEstimator, 1); m_node.chainman = &::g_chainman; m_node.chainman->InitializeChainstate(*m_node.mempool); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 010b6adf1f..36fa1a0299 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -23,6 +23,7 @@ #include <array> #include <stdint.h> +#include <string.h> #include <thread> #include <univalue.h> #include <utility> @@ -35,6 +36,8 @@ #include <boost/test/unit_test.hpp> +using namespace std::literals; + /* defined in logging.cpp */ namespace BCLog { std::string LogEscapeMessage(const std::string& str); @@ -1257,9 +1260,9 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney) BOOST_CHECK(!ParseMoney("-1", ret)); // Parsing strings with embedded NUL characters should fail - BOOST_CHECK(!ParseMoney(std::string("\0-1", 3), ret)); - BOOST_CHECK(!ParseMoney(std::string("\01", 2), ret)); - BOOST_CHECK(!ParseMoney(std::string("1\0", 2), ret)); + BOOST_CHECK(!ParseMoney("\0-1"s, ret)); + BOOST_CHECK(!ParseMoney("\0" "1"s, ret)); + BOOST_CHECK(!ParseMoney("1\0"s, ret)); } BOOST_AUTO_TEST_CASE(util_IsHex) @@ -1420,10 +1423,18 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32) BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647); BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234); + BOOST_CHECK(ParseInt32("00000000000000001234", &n) && n == 1234); + BOOST_CHECK(ParseInt32("-00000000000000001234", &n) && n == -1234); + BOOST_CHECK(ParseInt32("00000000000000000000", &n) && n == 0); + BOOST_CHECK(ParseInt32("-00000000000000000000", &n) && n == 0); // Invalid values BOOST_CHECK(!ParseInt32("", &n)); BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside BOOST_CHECK(!ParseInt32("1 ", &n)); + BOOST_CHECK(!ParseInt32("++1", &n)); + BOOST_CHECK(!ParseInt32("+-1", &n)); + BOOST_CHECK(!ParseInt32("-+1", &n)); + BOOST_CHECK(!ParseInt32("--1", &n)); BOOST_CHECK(!ParseInt32("1a", &n)); BOOST_CHECK(!ParseInt32("aap", &n)); BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex @@ -1479,10 +1490,19 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt32) BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647); BOOST_CHECK(ParseUInt32("2147483648", &n) && n == (uint32_t)2147483648); BOOST_CHECK(ParseUInt32("4294967295", &n) && n == (uint32_t)4294967295); + BOOST_CHECK(ParseUInt32("+1234", &n) && n == 1234); + BOOST_CHECK(ParseUInt32("00000000000000001234", &n) && n == 1234); + BOOST_CHECK(ParseUInt32("00000000000000000000", &n) && n == 0); // Invalid values + BOOST_CHECK(!ParseUInt32("-00000000000000000000", &n)); BOOST_CHECK(!ParseUInt32("", &n)); BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside BOOST_CHECK(!ParseUInt32(" -1", &n)); + BOOST_CHECK(!ParseUInt32("++1", &n)); + BOOST_CHECK(!ParseUInt32("+-1", &n)); + BOOST_CHECK(!ParseUInt32("-+1", &n)); + BOOST_CHECK(!ParseUInt32("--1", &n)); + BOOST_CHECK(!ParseUInt32("-1", &n)); BOOST_CHECK(!ParseUInt32("1 ", &n)); BOOST_CHECK(!ParseUInt32("1a", &n)); BOOST_CHECK(!ParseUInt32("aap", &n)); @@ -1593,9 +1613,9 @@ BOOST_AUTO_TEST_CASE(test_FormatSubVersion) std::vector<std::string> comments2; comments2.push_back(std::string("comment1")); comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014 - BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:0.9.99/")); - BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/")); - BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; Comment2; .,_?@-; )/")); + BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:9.99.0/")); + BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:9.99.0(comment1)/")); + BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:9.99.0(comment1; Comment2; .,_?@-; )/")); } BOOST_AUTO_TEST_CASE(test_ParseFixedPoint) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 0c2b731967..d18182c07d 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -331,15 +331,10 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, assert(int(nSigOpCostWithAncestors) >= 0); } -CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator) - : nTransactionsUpdated(0), minerPolicyEstimator(estimator), m_epoch(0), m_has_epoch_guard(false) +CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator, int check_ratio) + : m_check_ratio(check_ratio), minerPolicyEstimator(estimator) { _clear(); //lock free clear - - // Sanity checks off by default for performance, because otherwise - // accepting transactions becomes O(N^2) where N is the number - // of transactions in the pool - nCheckFrequency = 0; } bool CTxMemPool::isSpent(const COutPoint& outpoint) const @@ -523,7 +518,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem if (it2 != mapTx.end()) continue; const Coin &coin = pcoins->AccessCoin(txin.prevout); - if (nCheckFrequency != 0) assert(!coin.IsSpent()); + if (m_check_ratio != 0) assert(!coin.IsSpent()); if (coin.IsSpent() || (coin.IsCoinBase() && ((signed long)nMemPoolHeight) - coin.nHeight < COINBASE_MATURITY)) { txToRemove.insert(it); break; @@ -619,13 +614,11 @@ static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& m void CTxMemPool::check(const CCoinsViewCache *pcoins) const { - LOCK(cs); - if (nCheckFrequency == 0) - return; + if (m_check_ratio == 0) return; - if (GetRand(std::numeric_limits<uint32_t>::max()) >= nCheckFrequency) - return; + if (GetRand(m_check_ratio) >= 1) return; + LOCK(cs); LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size()); uint64_t checkTotal = 0; diff --git a/src/txmempool.h b/src/txmempool.h index f513f14af6..78ad62aae6 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -488,8 +488,8 @@ public: class CTxMemPool { private: - uint32_t nCheckFrequency GUARDED_BY(cs); //!< Value n means that n times in 2^32 we check. - std::atomic<unsigned int> nTransactionsUpdated; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation + const int m_check_ratio; //!< Value n means that 1 times in n we check. + std::atomic<unsigned int> nTransactionsUpdated{0}; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation CBlockPolicyEstimator* minerPolicyEstimator; uint64_t totalTxSize; //!< sum of all mempool tx's virtual sizes. Differs from serialized tx size since witness data is discounted. Defined in BIP 141. @@ -498,8 +498,8 @@ private: mutable int64_t lastRollingFeeUpdate; mutable bool blockSinceLastRollingFeeBump; mutable double rollingMinimumFeeRate; //!< minimum fee to get into the pool, decreases exponentially - mutable uint64_t m_epoch; - mutable bool m_has_epoch_guard; + mutable uint64_t m_epoch{0}; + mutable bool m_has_epoch_guard{false}; // In-memory counter for external mempool tracking purposes. // This number is incremented once every time a transaction @@ -601,8 +601,14 @@ public: std::map<uint256, CAmount> mapDeltas; /** Create a new CTxMemPool. + * Sanity checks will be off by default for performance, because otherwise + * accepting transactions becomes O(N^2) where N is the number of transactions + * in the pool. + * + * @param[in] estimator is used to estimate appropriate transaction fees. + * @param[in] check_ratio is the ratio used to determine how often sanity checks will run. */ - explicit CTxMemPool(CBlockPolicyEstimator* estimator = nullptr); + explicit CTxMemPool(CBlockPolicyEstimator* estimator = nullptr, int check_ratio = 0); /** * If sanity-checking is turned on, check makes sure the pool is @@ -611,7 +617,6 @@ public: * check does nothing. */ void check(const CCoinsViewCache *pcoins) const; - void setSanityCheck(double dFrequency = 1.0) { LOCK(cs); nCheckFrequency = static_cast<uint32_t>(dFrequency * 4294967295.0); } // addUnchecked must updated state for all ancestors of a given transaction, // to track size/count of descendant transactions. First version of diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h index 6080516353..048e162f7d 100644 --- a/src/univalue/include/univalue.h +++ b/src/univalue/include/univalue.h @@ -100,6 +100,10 @@ public: UniValue tmpVal(val_); return push_back(tmpVal); } + bool push_back(bool val_) { + UniValue tmpVal(val_); + return push_back(tmpVal); + } bool push_back(int val_) { UniValue tmpVal(val_); return push_back(tmpVal); @@ -129,7 +133,7 @@ public: return pushKV(key, tmpVal); } bool pushKV(const std::string& key, bool val_) { - UniValue tmpVal((bool)val_); + UniValue tmpVal(val_); return pushKV(key, tmpVal); } bool pushKV(const std::string& key, int val_) { diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp index 70ccc0d08a..ccc1344836 100644 --- a/src/univalue/test/object.cpp +++ b/src/univalue/test/object.cpp @@ -210,19 +210,31 @@ BOOST_AUTO_TEST_CASE(univalue_array) BOOST_CHECK(arr.push_back((int64_t) -400LL)); BOOST_CHECK(arr.push_back((int) -401)); BOOST_CHECK(arr.push_back(-40.1)); + BOOST_CHECK(arr.push_back(true)); BOOST_CHECK_EQUAL(arr.empty(), false); - BOOST_CHECK_EQUAL(arr.size(), 9); + BOOST_CHECK_EQUAL(arr.size(), 10); BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023"); + BOOST_CHECK_EQUAL(arr[0].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy"); + BOOST_CHECK_EQUAL(arr[1].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy"); + BOOST_CHECK_EQUAL(arr[2].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing"); + BOOST_CHECK_EQUAL(arr[3].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[4].getValStr(), "going"); + BOOST_CHECK_EQUAL(arr[4].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[5].getValStr(), "400"); + BOOST_CHECK_EQUAL(arr[5].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[6].getValStr(), "-400"); + BOOST_CHECK_EQUAL(arr[6].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[7].getValStr(), "-401"); + BOOST_CHECK_EQUAL(arr[7].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[8].getValStr(), "-40.1"); + BOOST_CHECK_EQUAL(arr[8].getType(), UniValue::VNUM); + BOOST_CHECK_EQUAL(arr[9].getValStr(), "1"); + BOOST_CHECK_EQUAL(arr[9].getType(), UniValue::VBOOL); BOOST_CHECK_EQUAL(arr[999].getValStr(), ""); diff --git a/src/util/bip32.h b/src/util/bip32.h index 347e83db9e..8f86f2aaa6 100644 --- a/src/util/bip32.h +++ b/src/util/bip32.h @@ -10,7 +10,7 @@ #include <vector> /** Parse an HD keypaths like "m/7/0'/2000". */ -NODISCARD bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath); +[[nodiscard]] bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath); /** Write HD keypaths as strings */ std::string WriteHDKeypath(const std::vector<uint32_t>& keypath); diff --git a/src/util/fees.cpp b/src/util/fees.cpp index 6208a20a97..1855c0bc90 100644 --- a/src/util/fees.cpp +++ b/src/util/fees.cpp @@ -40,8 +40,6 @@ const std::vector<std::pair<std::string, FeeEstimateMode>>& FeeModeMap() {"unset", FeeEstimateMode::UNSET}, {"economical", FeeEstimateMode::ECONOMICAL}, {"conservative", FeeEstimateMode::CONSERVATIVE}, - {(CURRENCY_UNIT + "/kB"), FeeEstimateMode::BTC_KB}, - {(CURRENCY_ATOM + "/B"), FeeEstimateMode::SAT_B}, }; return FEE_MODES; } @@ -51,6 +49,11 @@ std::string FeeModes(const std::string& delimiter) return Join(FeeModeMap(), delimiter, [&](const std::pair<std::string, FeeEstimateMode>& i) { return i.first; }); } +const std::string InvalidEstimateModeErrorMessage() +{ + return "Invalid estimate_mode parameter, must be one of: \"" + FeeModes("\", \"") + "\""; +} + bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) { auto searchkey = ToUpper(mode_string); diff --git a/src/util/fees.h b/src/util/fees.h index d52046a44c..3f1c33ad9c 100644 --- a/src/util/fees.h +++ b/src/util/fees.h @@ -13,5 +13,6 @@ enum class FeeReason; bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode); std::string StringForFeeReason(FeeReason reason); std::string FeeModes(const std::string& delimiter); +const std::string InvalidEstimateModeErrorMessage(); #endif // BITCOIN_UTIL_FEES_H diff --git a/src/util/memory.h b/src/util/memory.h index 15ecf8f80d..4d73b32869 100644 --- a/src/util/memory.h +++ b/src/util/memory.h @@ -10,10 +10,11 @@ #include <utility> //! Substitute for C++14 std::make_unique. +//! DEPRECATED use std::make_unique in new code. template <typename T, typename... Args> std::unique_ptr<T> MakeUnique(Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); + return std::make_unique<T>(std::forward<Args>(args)...); } #endif diff --git a/src/util/moneystr.h b/src/util/moneystr.h index 9d2b6da0fc..da7f673cda 100644 --- a/src/util/moneystr.h +++ b/src/util/moneystr.h @@ -19,6 +19,6 @@ */ std::string FormatMoney(const CAmount& n); /** Parse an amount denoted in full coins. E.g. "0.0034" supplied on the command line. **/ -NODISCARD bool ParseMoney(const std::string& str, CAmount& nRet); +[[nodiscard]] bool ParseMoney(const std::string& str, CAmount& nRet); #endif // BITCOIN_UTIL_MONEYSTR_H diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 3236184b0b..f3d54a2ac9 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -280,7 +280,7 @@ std::string DecodeBase32(const std::string& str, bool* pf_invalid) return std::string((const char*)vchRet.data(), vchRet.size()); } -NODISCARD static bool ParsePrechecks(const std::string& str) +[[nodiscard]] static bool ParsePrechecks(const std::string& str) { if (str.empty()) // No empty string allowed return false; diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 1a217dd12d..8ee43c620b 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -101,42 +101,42 @@ constexpr inline bool IsSpace(char c) noexcept { * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -NODISCARD bool ParseInt32(const std::string& str, int32_t *out); +[[nodiscard]] bool ParseInt32(const std::string& str, int32_t *out); /** * Convert string to signed 64-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -NODISCARD bool ParseInt64(const std::string& str, int64_t *out); +[[nodiscard]] bool ParseInt64(const std::string& str, int64_t *out); /** * Convert decimal string to unsigned 8-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -NODISCARD bool ParseUInt8(const std::string& str, uint8_t *out); +[[nodiscard]] bool ParseUInt8(const std::string& str, uint8_t *out); /** * Convert decimal string to unsigned 32-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -NODISCARD bool ParseUInt32(const std::string& str, uint32_t *out); +[[nodiscard]] bool ParseUInt32(const std::string& str, uint32_t *out); /** * Convert decimal string to unsigned 64-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -NODISCARD bool ParseUInt64(const std::string& str, uint64_t *out); +[[nodiscard]] bool ParseUInt64(const std::string& str, uint64_t *out); /** * Convert string to double with strict parse error feedback. * @returns true if the entire string could be parsed as valid double, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -NODISCARD bool ParseDouble(const std::string& str, double *out); +[[nodiscard]] bool ParseDouble(const std::string& str, double *out); /** * Convert a span of bytes to a lower-case hexadecimal string. @@ -170,7 +170,7 @@ bool TimingResistantEqual(const T& a, const T& b) * @returns true on success, false on error. * @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger. */ -NODISCARD bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out); +[[nodiscard]] bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out); /** Convert from one power-of-2 number base to another. */ template<int frombits, int tobits, bool pad, typename O, typename I> diff --git a/src/util/string.h b/src/util/string.h index a0c87bd00c..5ffdc80d88 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -15,7 +15,7 @@ #include <string> #include <vector> -NODISCARD inline std::string TrimString(const std::string& str, const std::string& pattern = " \f\n\r\t\v") +[[nodiscard]] inline std::string TrimString(const std::string& str, const std::string& pattern = " \f\n\r\t\v") { std::string::size_type front = str.find_first_not_of(pattern); if (front == std::string::npos) { @@ -59,7 +59,7 @@ inline std::string Join(const std::vector<std::string>& list, const std::string& /** * Check if a string does not contain any embedded NUL (\0) characters */ -NODISCARD inline bool ValidAsCString(const std::string& str) noexcept +[[nodiscard]] inline bool ValidAsCString(const std::string& str) noexcept { return str.size() == strlen(str.c_str()); } @@ -80,7 +80,7 @@ std::string ToString(const T& t) * Check whether a container begins with the given prefix. */ template <typename T1, size_t PREFIX_LEN> -NODISCARD inline bool HasPrefix(const T1& obj, +[[nodiscard]] inline bool HasPrefix(const T1& obj, const std::array<uint8_t, PREFIX_LEN>& prefix) { return obj.size() >= PREFIX_LEN && diff --git a/src/util/system.h b/src/util/system.h index 1df194ca84..2be8bb754b 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -60,7 +60,7 @@ bool FileCommit(FILE *file); bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); -bool RenameOver(fs::path src, fs::path dest); +[[nodiscard]] bool RenameOver(fs::path src, fs::path dest); bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false); void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name); bool DirIsWritable(const fs::path& directory); @@ -188,7 +188,7 @@ protected: std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args); std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args); - NODISCARD bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false); + [[nodiscard]] bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false); /** * Returns true if settings values from the default section should be used, @@ -220,8 +220,8 @@ public: */ void SelectConfigNetwork(const std::string& network); - NODISCARD bool ParseParameters(int argc, const char* const argv[], std::string& error); - NODISCARD bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false); + [[nodiscard]] bool ParseParameters(int argc, const char* const argv[], std::string& error); + [[nodiscard]] bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false); /** * Log warnings for options in m_section_only_args when diff --git a/src/validation.cpp b/src/validation.cpp index feb7502a0f..9197daec80 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; } @@ -5187,7 +5110,9 @@ bool DumpMempool(const CTxMemPool& pool) if (!FileCommit(file.Get())) throw std::runtime_error("FileCommit failed"); file.fclose(); - RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat"); + if (!RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat")) { + throw std::runtime_error("Rename failed"); + } int64_t last = GetTimeMicros(); LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*MICRO, (last-mid)*MICRO); } catch (const std::exception& e) { diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 8b2ef191fb..085dde1026 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -15,6 +15,9 @@ #include <util/moneystr.h> #include <util/system.h> #include <util/translation.h> +#ifdef USE_BDB +#include <wallet/bdb.h> +#endif #include <wallet/coincontrol.h> #include <wallet/wallet.h> #include <walletinitinterface.h> @@ -68,9 +71,14 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const #endif argsman.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); +#ifdef USE_BDB argsman.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST); argsman.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST); argsman.AddArg("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST); +#else + argsman.AddHiddenArgs({"-dblogsize", "-flushwallet", "-privdb"}); +#endif + argsman.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST); argsman.AddHiddenArgs({"-zapwallettxes"}); diff --git a/src/interfaces/wallet.cpp b/src/wallet/interfaces.cpp index f68016b557..3fbba9ab92 100644 --- a/src/interfaces/wallet.cpp +++ b/src/wallet/interfaces.cpp @@ -31,9 +31,22 @@ #include <utility> #include <vector> -namespace interfaces { -namespace { +using interfaces::Chain; +using interfaces::FoundBlock; +using interfaces::Handler; +using interfaces::MakeHandler; +using interfaces::Wallet; +using interfaces::WalletAddress; +using interfaces::WalletBalances; +using interfaces::WalletClient; +using interfaces::WalletOrderForm; +using interfaces::WalletTx; +using interfaces::WalletTxOut; +using interfaces::WalletTxStatus; +using interfaces::WalletValueMap; +namespace wallet { +namespace { //! Construct wallet tx struct. WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) { @@ -561,14 +574,14 @@ public: std::vector<std::unique_ptr<Handler>> m_rpc_handlers; std::list<CRPCCommand> m_rpc_commands; }; - } // namespace +} // namespace wallet -std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? MakeUnique<WalletImpl>(wallet) : nullptr; } +namespace interfaces { +std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? MakeUnique<wallet::WalletImpl>(wallet) : nullptr; } std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args) { - return MakeUnique<WalletClientImpl>(chain, args); + return MakeUnique<wallet::WalletClientImpl>(chain, args); } - } // namespace interfaces diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0fbb212732..7ea6a214b2 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -48,8 +48,6 @@ using interfaces::FoundBlock; static const std::string WALLET_ENDPOINT_BASE = "/wallet/"; static const std::string HELP_REQUIRING_PASSPHRASE{"\nRequires wallet passphrase to be set with walletpassphrase call if wallet is encrypted.\n"}; -static const uint32_t WALLET_BTC_KB_TO_SAT_B = COIN / 1000; // 1 sat / B = 0.00001 BTC / kB - static inline bool GetAvoidReuseFlag(const CWallet* const pwallet, const UniValue& param) { bool can_avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE); bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool(); @@ -199,36 +197,36 @@ static std::string LabelFromValue(const UniValue& value) /** * Update coin control with fee estimation based on the given parameters * - * @param[in] pwallet Wallet pointer - * @param[in,out] cc Coin control which is to be updated - * @param[in] estimate_mode String value (e.g. "ECONOMICAL") - * @param[in] estimate_param Parameter (blocks to confirm, explicit fee rate, etc) - * @throws a JSONRPCError if estimate_mode is unknown, or if estimate_param is missing when required + * @param[in] wallet Wallet reference + * @param[in,out] cc Coin control to be updated + * @param[in] conf_target UniValue integer; confirmation target in blocks, values between 1 and 1008 are valid per policy/fees.h; + * @param[in] estimate_mode UniValue string; fee estimation mode, valid values are "unset", "economical" or "conservative"; + * @param[in] fee_rate UniValue real; fee rate in sat/vB; + * if present, both conf_target and estimate_mode must either be null, or "unset" + * @param[in] override_min_fee bool; whether to set fOverrideFeeRate to true to disable minimum fee rate checks and instead + * verify only that fee_rate is greater than 0 + * @throws a JSONRPCError if conf_target, estimate_mode, or fee_rate contain invalid values or are in conflict */ -static void SetFeeEstimateMode(const CWallet* pwallet, CCoinControl& cc, const UniValue& estimate_mode, const UniValue& estimate_param) +static void SetFeeEstimateMode(const CWallet& wallet, CCoinControl& cc, const UniValue& conf_target, const UniValue& estimate_mode, const UniValue& fee_rate, bool override_min_fee) { - if (!estimate_mode.isNull()) { - if (!FeeModeFromString(estimate_mode.get_str(), cc.m_fee_mode)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); + if (!fee_rate.isNull()) { + if (!conf_target.isNull()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate."); } - } - - 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() != "unset") { + 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; - } - - cc.m_feerate = CFeeRate(fee_rate); - - // default RBF to true for explicit fee rate modes + cc.m_feerate = CFeeRate(AmountFromValue(fee_rate), COIN); + if (override_min_fee) cc.fOverrideFeeRate = true; + // Default RBF to true for explicit fee_rate, if unset. if (cc.m_signal_bip125_rbf == nullopt) cc.m_signal_bip125_rbf = true; - } else if (!estimate_param.isNull()) { - cc.m_confirm_target = ParseConfirmTarget(estimate_param, pwallet->chain().estimateMaxBlocks()); + return; + } + if (!estimate_mode.isNull() && !FeeModeFromString(estimate_mode.get_str(), cc.m_fee_mode)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage()); + } + if (!conf_target.isNull()) { + cc.m_confirm_target = ParseConfirmTarget(conf_target, wallet.chain().estimateMaxBlocks()); } } @@ -441,12 +439,12 @@ static RPCHelpMan sendtoaddress() {"subtractfeefromamount", RPCArg::Type::BOOL, /* default */ "false", "The fee will be deducted from the amount being sent.\n" "The recipient will receive less bitcoins than you enter in the amount field."}, {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"}, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -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."}, }, { @@ -462,12 +460,17 @@ static RPCHelpMan sendtoaddress() }, }, RPCExamples{ - HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1") - + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"seans outpost\"") - + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" true") - + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" false true 0.00002 " + (CURRENCY_UNIT + "/kB")) - + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" false true 2 " + (CURRENCY_ATOM + "/B")) - + HelpExampleRpc("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 0.1, \"donation\", \"seans outpost\"") + "\nSend 0.1 BTC\n" + + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1") + + "\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode using positional arguments\n" + + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"sean's outpost\" false true 6 economical") + + "\nSend 0.1 BTC with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB, subtract fee from amount, BIP125-replaceable, using positional arguments\n" + + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"drinks\" \"room77\" true true null \"unset\" null 1.1") + + "\nSend 0.2 BTC with a confirmation target of 6 blocks in economical fee estimate mode using named arguments\n" + + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.2 conf_target=6 estimate_mode=\"economical\"") + + "\nSend 0.5 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n" + + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25") + + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25 subtractfeefromamount=false replaceable=true avoid_reuse=true comment=\"2 pizzas\" comment_to=\"jeremy\" verbose=true") }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { @@ -502,7 +505,7 @@ static RPCHelpMan sendtoaddress() // We also enable partial spend avoidance if reuse avoidance is set. coin_control.m_avoid_partial_spends |= coin_control.m_avoid_address_reuse; - SetFeeEstimateMode(pwallet, coin_control, request.params[7], request.params[6]); + SetFeeEstimateMode(*pwallet, coin_control, /* conf_target */ request.params[6], /* estimate_mode */ request.params[7], /* fee_rate */ request.params[9], /* override_min_fee */ false); EnsureWalletIsUnlocked(pwallet); @@ -516,7 +519,7 @@ static RPCHelpMan sendtoaddress() std::vector<CRecipient> recipients; ParseRecipients(address_amounts, subtractFeeFromAmount, recipients); - bool verbose = request.params[9].isNull() ? false: request.params[9].get_bool(); + const bool verbose{request.params[10].isNull() ? false : request.params[10].get_bool()}; return SendMoney(pwallet, coin_control, recipients, mapValue, verbose); }, @@ -870,10 +873,10 @@ static RPCHelpMan sendmany() }, }, {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"}, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -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."}, }, { @@ -930,11 +933,11 @@ static RPCHelpMan sendmany() coin_control.m_signal_bip125_rbf = request.params[5].get_bool(); } - SetFeeEstimateMode(pwallet, coin_control, request.params[7], request.params[6]); + SetFeeEstimateMode(*pwallet, coin_control, /* conf_target */ request.params[6], /* estimate_mode */ request.params[7], /* fee_rate */ request.params[8], /* override_min_fee */ false); std::vector<CRecipient> recipients; ParseRecipients(sendTo, subtractFeeFromAmount, recipients); - bool verbose = request.params[8].isNull() ? false : request.params[8].get_bool(); + const bool verbose{request.params[9].isNull() ? false : request.params[9].get_bool()}; return SendMoney(pwallet, coin_control, recipients, std::move(mapValue), verbose); }, @@ -2311,7 +2314,7 @@ static RPCHelpMan settxfee() "\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n" "Can be deactivated by passing 0 as the fee. In that case automatic fee selection will be used by default.\n", { - {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kB"}, + {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kvB"}, }, RPCResult{ RPCResult::Type::BOOL, "", "Returns true if successful" @@ -2434,7 +2437,7 @@ static RPCHelpMan getwalletinfo() {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"}, {RPCResult::Type::NUM, "keypoolsize_hd_internal", "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"}, {RPCResult::Type::NUM_TIME, "unlocked_until", /* optional */ true, "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets)"}, - {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB"}, + {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"}, {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true, "the Hash160 of the HD seed (only present when HD is enabled)"}, {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"}, {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"}, @@ -2752,6 +2755,12 @@ static RPCHelpMan createwallet() warnings.emplace_back(Untranslated("Wallet is an experimental descriptor wallet")); } +#ifndef USE_BDB + if (!(flags & WALLET_FLAG_DESCRIPTORS)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without bdb support (required for legacy wallets)"); + } +#endif + DatabaseOptions options; DatabaseStatus status; options.require_create = true; @@ -2780,7 +2789,7 @@ static RPCHelpMan unloadwallet() "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n" "Specifying the wallet name on a wallet endpoint is invalid.", { - {"wallet_name", RPCArg::Type::STR, /* default */ "the wallet name from the RPC request", "The name of the wallet to unload."}, + {"wallet_name", RPCArg::Type::STR, /* default */ "the wallet name from the RPC endpoint", "The name of the wallet to unload. If provided both here and in the RPC endpoint, the two must be identical."}, {"load_on_startup", RPCArg::Type::BOOL, /* default */ "null", "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."}, }, RPCResult{RPCResult::Type::OBJ, "", "", { @@ -2794,8 +2803,8 @@ static RPCHelpMan unloadwallet() { std::string wallet_name; if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) { - if (!request.params[0].isNull()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot unload the requested wallet"); + if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets"); } } else { wallet_name = request.params[0].get_str(); @@ -3047,7 +3056,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 @@ -3080,7 +3089,8 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f {"lockUnspents", UniValueType(UniValue::VBOOL)}, {"lock_unspents", UniValueType(UniValue::VBOOL)}, {"locktime", UniValueType(UniValue::VNUM)}, - {"feeRate", UniValueType()}, // will be checked below + {"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode() + {"feeRate", UniValueType()}, // will be checked by AmountFromValue() below {"psbt", UniValueType(UniValue::VBOOL)}, {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)}, {"subtract_fee_from_outputs", UniValueType(UniValue::VARR)}, @@ -3127,10 +3137,12 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f lockUnspents = (options.exists("lock_unspents") ? options["lock_unspents"] : options["lockUnspents"]).get_bool(); } - if (options.exists("feeRate")) - { + if (options.exists("feeRate")) { + if (options.exists("fee_rate")) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both fee_rate (" + CURRENCY_ATOM + "/vB) and feeRate (" + CURRENCY_UNIT + "/kvB)"); + } if (options.exists("conf_target")) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate."); } if (options.exists("estimate_mode")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate"); @@ -3145,7 +3157,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f if (options.exists("replaceable")) { coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool(); } - SetFeeEstimateMode(pwallet, coinControl, options["estimate_mode"], options["conf_target"]); + SetFeeEstimateMode(*pwallet, coinControl, options["conf_target"], options["estimate_mode"], options["fee_rate"], override_min_fee); } } else { // if options is null and not a bool @@ -3202,7 +3214,8 @@ static RPCHelpMan fundrawtransaction() "Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n" "e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."}, {"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"}, - {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"}, + {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, + {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."}, {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "The integers.\n" "The fee will be equally deducted from the amount of each specified output.\n" "Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n" @@ -3213,8 +3226,7 @@ static RPCHelpMan fundrawtransaction() }, {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n" "Allows this transaction to be replaced by a transaction with higher fees"}, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -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\"") + "\""}, }, @@ -3266,7 +3278,7 @@ static RPCHelpMan fundrawtransaction() CCoinControl coin_control; // Automatically select (additional) coins. Can be overridden by options.add_inputs. coin_control.m_add_inputs = true; - FundTransaction(pwallet, tx, fee, change_position, request.params[1], coin_control); + FundTransaction(pwallet, tx, fee, change_position, request.params[1], coin_control, /* override_min_fee */ true); UniValue result(UniValue::VOBJ); result.pushKV("hex", EncodeHexTx(CTransaction(tx))); @@ -3374,35 +3386,38 @@ RPCHelpMan signrawtransactionwithwallet() static RPCHelpMan bumpfee_helper(std::string method_name) { bool want_psbt = method_name == "psbtbumpfee"; + const std::string incremental_fee{CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE).ToString(FeeEstimateMode::SAT_VB)}; return RPCHelpMan{method_name, "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n" + std::string(want_psbt ? "Returns a PSBT instead of creating and signing a new transaction.\n" : "") + "An opt-in RBF transaction with the given txid must be in the wallet.\n" - "The command will pay the additional fee by reducing change outputs or adding inputs when necessary. It may add a new change output if one does not already exist.\n" + "The command will pay the additional fee by reducing change outputs or adding inputs when necessary.\n" + "It may add a new change output if one does not already exist.\n" "All inputs in the original transaction will be included in the replacement transaction.\n" "The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n" "By default, the new fee will be calculated automatically using 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 + " 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\"") + "\""}, }, @@ -3455,7 +3470,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name) { {"confTarget", UniValueType(UniValue::VNUM)}, {"conf_target", UniValueType(UniValue::VNUM)}, - {"fee_rate", UniValueType(UniValue::VNUM)}, + {"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode() {"replaceable", UniValueType(UniValue::VBOOL)}, {"estimate_mode", UniValueType(UniValue::VSTR)}, }, @@ -3467,22 +3482,10 @@ static RPCHelpMan bumpfee_helper(std::string method_name) auto conf_target = options.exists("confTarget") ? options["confTarget"] : options["conf_target"]; - if (!conf_target.isNull()) { - if (options.exists("fee_rate")) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "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 @@ -4018,10 +4021,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."}, @@ -4029,10 +4032,10 @@ static RPCHelpMan send() {"change_address", RPCArg::Type::STR_HEX, /* default */ "pool address", "The bitcoin address to receive the change"}, {"change_position", RPCArg::Type::NUM, /* default */ "random", "The index of the change output"}, {"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, - {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -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."}, @@ -4069,18 +4072,25 @@ static RPCHelpMan send() } }, RPCExamples{"" - "\nSend with a fee rate of 1 satoshi per byte\n" - + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 sat/b\n") + - "\nCreate a transaction that should confirm the next block, with a specific input, and return result without adding to wallet or broadcasting to the network\n" + "\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode\n" + + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 6 economical\n") + + "Send 0.2 BTC with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB using positional arguments\n" + + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' null \"unset\" 1.1\n") + + "Send 0.2 BTC with a fee rate of 1 " + CURRENCY_ATOM + "/vB using the options argument\n" + + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' null \"unset\" null '{\"fee_rate\": 1}'\n") + + "Send 0.3 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n" + + HelpExampleCli("-named send", "outputs='{\"" + EXAMPLE_ADDRESS[0] + "\": 0.3}' fee_rate=25\n") + + "Create a transaction that should confirm the next block, with a specific input, and return result without adding to wallet or broadcasting to the network\n" + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 economical '{\"add_to_wallet\": false, \"inputs\": [{\"txid\":\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\", \"vout\":1}]}'") }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { RPCTypeCheck(request.params, { - UniValueType(), // ARR or OBJ, checked later - UniValue::VNUM, - UniValue::VSTR, - UniValue::VOBJ + UniValueType(), // outputs (ARR or OBJ, checked later) + UniValue::VNUM, // conf_target + UniValue::VSTR, // estimate_mode + UniValue::VNUM, // fee_rate + UniValue::VOBJ, // options }, true ); @@ -4088,18 +4098,28 @@ static RPCHelpMan send() if (!wallet) return NullUniValue; CWallet* const pwallet = wallet.get(); - UniValue options = request.params[3]; - if (options.exists("feeRate") || options.exists("fee_rate") || options.exists("estimate_mode") || options.exists("conf_target")) { + UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]}; + if (options.exists("conf_target") || options.exists("estimate_mode")) { if (!request.params[1].isNull() || !request.params[2].isNull()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Use either conf_target and estimate_mode or the options dictionary to control fee rate"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Pass conf_target and estimate_mode either as arguments or in the options object, but not both"); } } else { options.pushKV("conf_target", request.params[1]); options.pushKV("estimate_mode", request.params[2]); } + if (options.exists("fee_rate")) { + if (!request.params[3].isNull()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Pass the fee_rate either as an argument, or in the options object, but not both"); + } + } else { + options.pushKV("fee_rate", request.params[3]); + } if (!options["conf_target"].isNull() && (options["estimate_mode"].isNull() || (options["estimate_mode"].get_str() == "unset"))) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Specify estimate_mode"); } + if (options.exists("feeRate")) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Use fee_rate (" + CURRENCY_ATOM + "/vB) instead of feeRate"); + } if (options.exists("changeAddress")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Use change_address"); } @@ -4129,7 +4149,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")) { @@ -4214,7 +4234,7 @@ static RPCHelpMan sethdseed() // Do not do anything to non-HD wallets if (!pwallet->CanSupportFeature(FEATURE_HD)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD"); + throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set an HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD"); } EnsureWalletIsUnlocked(pwallet); @@ -4357,7 +4377,8 @@ static RPCHelpMan walletcreatefundedpsbt() {"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, {"includeWatching", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Also select inputs which are watch only"}, {"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"}, - {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"}, + {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, + {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."}, {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "The outputs to subtract the fee from.\n" "The fee will be equally deducted from the amount of each specified output.\n" "Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n" @@ -4368,8 +4389,7 @@ static RPCHelpMan walletcreatefundedpsbt() }, {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n" "Allows this transaction to be replaced by a transaction with higher fees"}, - {"conf_target", RPCArg::Type::NUM, /* default */ "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\"") + "\""}, }, @@ -4416,7 +4436,7 @@ static RPCHelpMan walletcreatefundedpsbt() // Automatically select coins, unless at least one is manually selected. Can // be overridden by options.add_inputs. coin_control.m_add_inputs = rawTx.vin.size() == 0; - FundTransaction(pwallet, rawTx, fee, change_position, request.params[3], coin_control); + FundTransaction(pwallet, rawTx, fee, change_position, request.params[3], coin_control, /* override_min_fee */ true); // Make a blank psbt PartiallySignedTransaction psbtx(rawTx); @@ -4445,14 +4465,18 @@ static RPCHelpMan walletcreatefundedpsbt() static RPCHelpMan upgradewallet() { return RPCHelpMan{"upgradewallet", - "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified\n" + "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n" "New keys may be generated and a new wallet backup will need to be made.", { - {"version", RPCArg::Type::NUM, /* default */ strprintf("%d", FEATURE_LATEST), "The version number to upgrade to. Default is the latest wallet version"} + {"version", RPCArg::Type::NUM, /* default */ strprintf("%d", FEATURE_LATEST), "The version number to upgrade to. Default is the latest wallet version."} }, RPCResult{ RPCResult::Type::OBJ, "", "", { + {RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"}, + {RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"}, + {RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"}, + {RPCResult::Type::STR, "result", /* optional */ true, "Description of result, if no error"}, {RPCResult::Type::STR, "error", /* optional */ true, "Error message (if there is one)"} }, }, @@ -4474,14 +4498,28 @@ static RPCHelpMan upgradewallet() if (!request.params[0].isNull()) { version = request.params[0].get_int(); } - bilingual_str error; - std::vector<bilingual_str> warnings; - if (!pwallet->UpgradeWallet(version, error, warnings)) { - throw JSONRPCError(RPC_WALLET_ERROR, error.original); + const int previous_version{pwallet->GetVersion()}; + const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)}; + const int current_version{pwallet->GetVersion()}; + std::string result; + + if (wallet_upgraded) { + if (previous_version == current_version) { + result = "Already at latest version. Wallet version unchanged."; + } else { + result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version); + } } + UniValue obj(UniValue::VOBJ); - if (!error.empty()) { + obj.pushKV("wallet_name", pwallet->GetName()); + obj.pushKV("previous_version", previous_version); + obj.pushKV("current_version", current_version); + if (!result.empty()) { + obj.pushKV("result", result); + } else { + CHECK_NONFATAL(!error.empty()); obj.pushKV("error", error.original); } return obj; @@ -4551,9 +4589,9 @@ static const CRPCCommand commands[] = { "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} }, { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} }, { "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} }, - { "wallet", "send", &send, {"outputs","conf_target","estimate_mode","options"} }, - { "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode","verbose"} }, - { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse","verbose"} }, + { "wallet", "send", &send, {"outputs","conf_target","estimate_mode","fee_rate","options"} }, + { "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode","fee_rate","verbose"} }, + { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse","fee_rate","verbose"} }, { "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} }, { "wallet", "setlabel", &setlabel, {"address","label"} }, { "wallet", "settxfee", &settxfee, {"amount"} }, diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp index 225b975067..da5ca7858f 100644 --- a/src/wallet/salvage.cpp +++ b/src/wallet/salvage.cpp @@ -6,6 +6,7 @@ #include <fs.h> #include <streams.h> #include <util/translation.h> +#include <wallet/bdb.h> #include <wallet/salvage.h> #include <wallet/wallet.h> #include <wallet/walletdb.h> @@ -27,6 +28,7 @@ bool RecoverDatabaseFile(const fs::path& file_path, bilingual_str& error, std::v DatabaseStatus status; options.require_existing = true; options.verify = false; + options.require_format = DatabaseFormat::BERKELEY; std::unique_ptr<WalletDatabase> database = MakeDatabase(file_path, options, status, error); if (!database) return false; diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index d2e1be6402..15972fe7bb 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -3,12 +3,15 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <key_io.h> +#include <logging.h> #include <outputtype.h> #include <script/descriptor.h> #include <script/sign.h> #include <util/bip32.h> #include <util/strencodings.h> #include <util/string.h> +#include <util/system.h> +#include <util/time.h> #include <util/translation.h> #include <wallet/scriptpubkeyman.h> @@ -453,7 +456,7 @@ bool LegacyScriptPubKeyMan::Upgrade(int prev_version, int new_version, bilingual hd_upgrade = true; } // Upgrade to HD chain split if necessary - if (IsFeatureSupported(new_version, FEATURE_HD_SPLIT)) { + if (!IsFeatureSupported(prev_version, FEATURE_HD_SPLIT) && IsFeatureSupported(new_version, FEATURE_HD_SPLIT)) { WalletLogPrintf("Upgrading wallet to use HD chain split\n"); m_storage.SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL); split_upgrade = FEATURE_HD_SPLIT > prev_version; diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index 3bf8f78120..43791acfcf 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -11,6 +11,7 @@ #include <script/standard.h> #include <util/error.h> #include <util/message.h> +#include <util/time.h> #include <wallet/crypter.h> #include <wallet/ismine.h> #include <wallet/walletdb.h> diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp index d83332c194..d278d96476 100644 --- a/src/wallet/sqlite.cpp +++ b/src/wallet/sqlite.cpp @@ -206,7 +206,9 @@ void SQLiteDatabase::Open() } if (m_db == nullptr) { - TryCreateDirectories(m_dir_path); + if (!m_mock) { + TryCreateDirectories(m_dir_path); + } int ret = sqlite3_open_v2(m_file_path.c_str(), &m_db, flags, nullptr); if (ret != SQLITE_OK) { throw std::runtime_error(strprintf("SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(ret))); 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 d414555511..3019d53c6c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2818,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; } @@ -4102,7 +4102,7 @@ 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(); if (version == 0) { @@ -4111,9 +4111,8 @@ bool CWallet::UpgradeWallet(int version, bilingual_str& error, std::vector<bilin } else { WalletLogPrintf("Allowing wallet upgrade up to %i\n", version); } - if (version < prev_version) - { - error = _("Cannot downgrade wallet"); + if (version < prev_version) { + error = strprintf(_("Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version); return false; } @@ -4121,7 +4120,7 @@ bool CWallet::UpgradeWallet(int version, bilingual_str& error, std::vector<bilin // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT 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."); + error = strprintf(_("Cannot upgrade a non HD split wallet from version %i to version %i without upgrading to support pre-split keypool. Please use version %i or no version specified."), prev_version, version, FEATURE_PRE_SPLIT_KEYPOOL); return false; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0934213fc7..69cf6b66a4 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1195,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..45807ae6fd 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -14,7 +14,9 @@ #include <util/system.h> #include <util/time.h> #include <util/translation.h> +#ifdef USE_BDB #include <wallet/bdb.h> +#endif #ifdef USE_SQLITE #include <wallet/sqlite.h> #endif @@ -362,7 +364,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, { ssValue >> hash; } - catch (...) {} + catch (const std::ios_base::failure&) {} bool fSkipCheck = false; @@ -1011,9 +1013,11 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas Optional<DatabaseFormat> format; if (exists) { +#ifdef USE_BDB if (ExistsBerkeleyDatabase(path)) { format = DatabaseFormat::BERKELEY; } +#endif #ifdef USE_SQLITE if (ExistsSQLiteDatabase(path)) { if (format) { @@ -1052,15 +1056,31 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas // Format is not set when a db doesn't already exist, so use the format specified by the options if it is set. if (!format && options.require_format) format = options.require_format; + // If the format is not specified or detected, choose the default format based on what is available. We prefer BDB over SQLite for now. + if (!format) { #ifdef USE_SQLITE - if (format && format == DatabaseFormat::SQLITE) { - return MakeSQLiteDatabase(path, options, status, error); + format = DatabaseFormat::SQLITE; +#endif +#ifdef USE_BDB + format = DatabaseFormat::BERKELEY; +#endif } -#else - assert(format != DatabaseFormat::SQLITE); + + if (format == DatabaseFormat::SQLITE) { +#ifdef USE_SQLITE + return MakeSQLiteDatabase(path, options, status, error); #endif + error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support SQLite database format.", path.string())); + status = DatabaseStatus::FAILED_BAD_FORMAT; + return nullptr; + } +#ifdef USE_BDB return MakeBerkeleyDatabase(path, options, status, error); +#endif + error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support Berkeley DB database format.", path.string())); + status = DatabaseStatus::FAILED_BAD_FORMAT; + return nullptr; } /** Return object for accessing dummy database with no read/write capabilities. */ @@ -1072,5 +1092,9 @@ std::unique_ptr<WalletDatabase> CreateDummyWalletDatabase() /** Return object for accessing temporary in-memory database. */ std::unique_ptr<WalletDatabase> CreateMockWalletDatabase() { +#ifdef USE_BDB return MakeUnique<BerkeleyDatabase>(std::make_shared<BerkeleyEnvironment>(), ""); +#elif USE_SQLITE + return MakeUnique<SQLiteDatabase>("", "", true); +#endif } diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 7f1b86e458..e7b2d7d780 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -8,7 +8,6 @@ #include <amount.h> #include <script/sign.h> -#include <wallet/bdb.h> #include <wallet/db.h> #include <wallet/walletutil.h> #include <key.h> diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index 0e18d6a740..dad1232e10 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -122,6 +122,7 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name) WalletShowInfo(wallet_instance.get()); wallet_instance->Close(); } else if (command == "salvage") { +#ifdef USE_BDB bilingual_str error; std::vector<bilingual_str> warnings; bool ret = RecoverDatabaseFile(path, error, warnings); @@ -134,6 +135,10 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name) } } return ret; +#else + tfm::format(std::cerr, "Salvage command is not available as BDB support is not compiled"); + return false; +#endif } } else { tfm::format(std::cerr, "Invalid command: %s\n", command); diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index 702293e6c7..9be610e8bd 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -7,7 +7,11 @@ #include <logging.h> #include <util/system.h> +#ifdef USE_BDB bool ExistsBerkeleyDatabase(const fs::path& path); +#else +# define ExistsBerkeleyDatabase(path) (false) +#endif #ifdef USE_SQLITE bool ExistsSQLiteDatabase(const fs::path& path); #else @@ -87,13 +91,9 @@ bool IsFeatureSupported(int wallet_version, int 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; + const std::array<WalletFeature, 8> wallet_features{{FEATURE_LATEST, FEATURE_PRE_SPLIT_KEYPOOL, FEATURE_NO_DEFAULT_KEY, FEATURE_HD_SPLIT, FEATURE_HD, FEATURE_COMPRPUBKEY, FEATURE_WALLETCRYPT, FEATURE_BASE}}; + for (const WalletFeature& wf : wallet_features) { + if (version >= wf) return wf; + } return static_cast<WalletFeature>(0); } diff --git a/src/warnings.cpp b/src/warnings.cpp index 501bf7e637..1dec663a73 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -14,7 +14,6 @@ static Mutex g_warnings_mutex; static bilingual_str g_misc_warnings GUARDED_BY(g_warnings_mutex); -static bool fLargeWorkForkFound GUARDED_BY(g_warnings_mutex) = false; static bool fLargeWorkInvalidChainFound GUARDED_BY(g_warnings_mutex) = false; void SetMiscWarning(const bilingual_str& warning) @@ -23,18 +22,6 @@ void SetMiscWarning(const bilingual_str& warning) g_misc_warnings = warning; } -void SetfLargeWorkForkFound(bool flag) -{ - LOCK(g_warnings_mutex); - fLargeWorkForkFound = flag; -} - -bool GetfLargeWorkForkFound() -{ - LOCK(g_warnings_mutex); - return fLargeWorkForkFound; -} - void SetfLargeWorkInvalidChainFound(bool flag) { LOCK(g_warnings_mutex); @@ -60,10 +47,7 @@ bilingual_str GetWarnings(bool verbose) warnings_verbose.emplace_back(warnings_concise); } - if (fLargeWorkForkFound) { - warnings_concise = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); - warnings_verbose.emplace_back(warnings_concise); - } else if (fLargeWorkInvalidChainFound) { + if (fLargeWorkInvalidChainFound) { warnings_concise = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); warnings_verbose.emplace_back(warnings_concise); } diff --git a/src/warnings.h b/src/warnings.h index 28546eb753..e87b64a86d 100644 --- a/src/warnings.h +++ b/src/warnings.h @@ -11,8 +11,6 @@ struct bilingual_str; void SetMiscWarning(const bilingual_str& warning); -void SetfLargeWorkForkFound(bool flag); -bool GetfLargeWorkForkFound(); void SetfLargeWorkInvalidChainFound(bool flag); /** Format a string that describes several potential problems detected by the core. * @param[in] verbose bool diff --git a/test/config.ini.in b/test/config.ini.in index 4b4a092a9d..77c9a720c3 100644 --- a/test/config.ini.in +++ b/test/config.ini.in @@ -17,6 +17,7 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py # Which components are enabled. These are commented out by `configure` if they were disabled when running config. @ENABLE_WALLET_TRUE@ENABLE_WALLET=true @USE_SQLITE_TRUE@USE_SQLITE=true +@USE_BDB_TRUE@USE_BDB=true @BUILD_BITCOIN_CLI_TRUE@ENABLE_CLI=true @BUILD_BITCOIN_WALLET_TRUE@ENABLE_WALLET_TOOL=true @BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true diff --git a/test/functional/README.md b/test/functional/README.md index 82b30fed51..2764acbf18 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -34,7 +34,7 @@ don't have test cases for. - When subclassing the BitcoinTestFramework, place overrides for the `set_test_params()`, `add_options()` and `setup_xxxx()` methods at the top of the subclass, then locally-defined helper methods, then the `run_test()` method. -- Use `'{}'.format(x)` for string formatting, not `'%s' % x`. +- Use `f'{x}'` for string formatting in preference to `'{}'.format(x)` or `'%s' % x`. #### Naming guidelines diff --git a/test/functional/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/feature_taproot.py b/test/functional/feature_taproot.py index 6e28cfb265..0f0fe8a34a 100755 --- a/test/functional/feature_taproot.py +++ b/test/functional/feature_taproot.py @@ -1442,17 +1442,23 @@ class TaprootTest(BitcoinTestFramework): self.nodes[1].generate(101) self.test_spenders(self.nodes[1], spenders_taproot_active(), input_counts=[1, 2, 2, 2, 2, 3]) - # Transfer funds to pre-taproot node. + # Transfer value of the largest 500 coins to pre-taproot node. addr = self.nodes[0].getnewaddress() + + unsp = self.nodes[1].listunspent() + unsp = sorted(unsp, key=lambda i: i['amount'], reverse=True) + unsp = unsp[:500] + rawtx = self.nodes[1].createrawtransaction( inputs=[{ 'txid': i['txid'], 'vout': i['vout'] - } for i in self.nodes[1].listunspent()], - outputs={addr: self.nodes[1].getbalance()}, + } for i in unsp], + outputs={addr: sum(i['amount'] for i in unsp)} ) rawtx = self.nodes[1].signrawtransactionwithwallet(rawtx)['hex'] - # Transaction is too large to fit into the mempool, so put it into a block + + # Mine a block with the transaction block = create_block(tmpl=self.nodes[1].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS), txlist=[rawtx]) add_witness_commitment(block) block.rehash() diff --git a/test/functional/mempool_compatibility.py b/test/functional/mempool_compatibility.py index 7168cb4ab2..8ac91bd008 100755 --- a/test/functional/mempool_compatibility.py +++ b/test/functional/mempool_compatibility.py @@ -29,7 +29,7 @@ class MempoolCompatibilityTest(BitcoinTestFramework): def setup_network(self): self.add_nodes(self.num_nodes, versions=[ - 150200, # oldest version supported by the test framework + 190100, # oldest version with getmempoolinfo.loaded (used to avoid intermittent issues) None, ]) self.start_nodes() @@ -72,5 +72,6 @@ class MempoolCompatibilityTest(BitcoinTestFramework): assert old_tx_hash in old_node.getrawmempool() assert unbroadcasted_tx_hash in old_node.getrawmempool() + if __name__ == "__main__": MempoolCompatibilityTest().main() diff --git a/test/functional/mempool_spend_coinbase.py b/test/functional/mempool_spend_coinbase.py index 854d506f0d..86d382ff69 100755 --- a/test/functional/mempool_spend_coinbase.py +++ b/test/functional/mempool_spend_coinbase.py @@ -13,44 +13,48 @@ but less mature coinbase spends are NOT. """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.blocktools import create_raw_transaction from test_framework.util import assert_equal, assert_raises_rpc_error +from test_framework.wallet import MiniWallet class MempoolSpendCoinbaseTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 - - def skip_test_if_missing_module(self): - self.skip_if_no_wallet() + self.setup_clean_chain = True def run_test(self): + wallet = MiniWallet(self.nodes[0]) + + wallet.generate(200) chain_height = self.nodes[0].getblockcount() assert_equal(chain_height, 200) - node0_address = self.nodes[0].getnewaddress() # Coinbase at height chain_height-100+1 ok in mempool, should # get mined. Coinbase at height chain_height-100+2 is - # is too immature to spend. + # too immature to spend. b = [self.nodes[0].getblockhash(n) for n in range(101, 103)] coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b] - spends_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in coinbase_txids] + utxo_101 = wallet.get_utxo(txid=coinbase_txids[0]) + utxo_102 = wallet.get_utxo(txid=coinbase_txids[1]) - spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0]) + spend_101_id = wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_101)["txid"] # coinbase at height 102 should be too immature to spend - assert_raises_rpc_error(-26,"bad-txns-premature-spend-of-coinbase", self.nodes[0].sendrawtransaction, spends_raw[1]) + assert_raises_rpc_error(-26, + "bad-txns-premature-spend-of-coinbase", + lambda: wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_102)) # mempool should have just spend_101: - assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ]) + assert_equal(self.nodes[0].getrawmempool(), [spend_101_id]) # mine a block, spend_101 should get confirmed self.nodes[0].generate(1) assert_equal(set(self.nodes[0].getrawmempool()), set()) # ... and now height 102 can be spent: - spend_102_id = self.nodes[0].sendrawtransaction(spends_raw[1]) - assert_equal(self.nodes[0].getrawmempool(), [ spend_102_id ]) + spend_102_id = wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_102)["txid"] + assert_equal(self.nodes[0].getrawmempool(), [spend_102_id]) + if __name__ == '__main__': MempoolSpendCoinbaseTest().main() diff --git a/test/functional/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..8ee0ecab0a 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,88 @@ 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}) + # Test that funding non-standard "zero-fee" transactions is valid. + result5 = self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 0}) + result6 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 0}) + + result_fee_rate = result['fee'] * 1000 / count_bytes(result['hex']) + assert_fee_amount(result1['fee'], count_bytes(result2['hex']), 2 * result_fee_rate) + assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate) + assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) + assert_fee_amount(result4['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) + assert_fee_amount(result5['fee'], count_bytes(result5['hex']), 0) + assert_fee_amount(result6['fee'], count_bytes(result6['hex']), 0) - 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") + for param, value in {("fee_rate", 100000), ("feeRate", 1.000)}: + assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", + node.fundrawtransaction, rawtx, {param: value, "add_inputs": True}) + assert_raises_rpc_error(-3, "Amount out of range", + node.fundrawtransaction, rawtx, {param: -1, "add_inputs": True}) + assert_raises_rpc_error(-3, "Amount is not a number or string", + node.fundrawtransaction, rawtx, {param: {"foo": "bar"}, "add_inputs": True}) + assert_raises_rpc_error(-3, "Invalid amount", + node.fundrawtransaction, rawtx, {param: "", "add_inputs": True}) + + self.log.info("Test min fee rate checks are bypassed with fundrawtxn, e.g. a fee_rate under 1 sat/vB is allowed") + node.fundrawtransaction(rawtx, {"fee_rate": 0.99999999, "add_inputs": True}) + node.fundrawtransaction(rawtx, {"feeRate": 0.00000999, "add_inputs": True}) + + self.log.info("- raises RPC error if both feeRate and fee_rate are passed") + assert_raises_rpc_error(-8, "Cannot specify both fee_rate (sat/vB) and feeRate (BTC/kvB)", + node.fundrawtransaction, rawtx, {"fee_rate": 0.1, "feeRate": 0.1, "add_inputs": True}) + + self.log.info("- raises RPC error if both feeRate and estimate_mode passed") + assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and feeRate", + node.fundrawtransaction, rawtx, {"estimate_mode": "economical", "feeRate": 0.1, "add_inputs": True}) + + for param in ["feeRate", "fee_rate"]: + self.log.info("- raises RPC error if both {} and conf_target are passed".format(param)) + assert_raises_rpc_error(-8, "Cannot specify both conf_target and {}. Please provide either a confirmation " + "target in blocks for automatic fee estimation, or an explicit fee rate.".format(param), + node.fundrawtransaction, rawtx, {param: 1, "conf_target": 1, "add_inputs": True}) + + self.log.info("- raises RPC error if both fee_rate and estimate_mode are passed") + assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate", + node.fundrawtransaction, rawtx, {"fee_rate": 1, "estimate_mode": "economical", "add_inputs": True}) def test_address_reuse(self): """Test no address reuse occurs.""" @@ -803,12 +816,32 @@ class RawTransactionsTest(BitcoinTestFramework): outputs = {self.nodes[2].getnewaddress(): 1} rawtx = self.nodes[3].createrawtransaction(inputs, outputs) + # Test subtract fee from outputs with feeRate (BTC/kvB) result = [self.nodes[3].fundrawtransaction(rawtx), # uses self.min_relay_tx_fee (set by settxfee) self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": []}), # empty subtraction list self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0]}), # uses self.min_relay_tx_fee (set by settxfee) self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee}), self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee, "subtractFeeFromOutputs": [0]}),] + dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result] + output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)] + change = [d['vout'][r['changepos']]['value'] for d, r in zip(dec_tx, result)] + + assert_equal(result[0]['fee'], result[1]['fee'], result[2]['fee']) + assert_equal(result[3]['fee'], result[4]['fee']) + assert_equal(change[0], change[1]) + assert_equal(output[0], output[1]) + assert_equal(output[0], output[2] + result[2]['fee']) + assert_equal(change[0] + result[0]['fee'], change[2]) + assert_equal(output[3], output[4] + result[4]['fee']) + assert_equal(change[3] + result[3]['fee'], change[4]) + # Test subtract fee from outputs with fee_rate (sat/vB) + btc_kvb_to_sat_vb = 100000 # (1e5) + result = [self.nodes[3].fundrawtransaction(rawtx), # uses self.min_relay_tx_fee (set by settxfee) + self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": []}), # empty subtraction list + self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0]}), # uses self.min_relay_tx_fee (set by settxfee) + self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee}), + self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee, "subtractFeeFromOutputs": [0]}),] dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result] output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)] change = [d['vout'][r['changepos']]['value'] for d, r in zip(dec_tx, result)] diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index ca75bcb9bb..5840801b00 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -187,60 +187,75 @@ 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 min fee rate checks with walletcreatefundedpsbt are bypassed and that funding non-standard 'zero-fee' transactions is valid") + for param in ["fee_rate", "feeRate"]: + assert_equal(self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {param: 0, "add_inputs": True})["fee"], 0) + + self.log.info("Test invalid fee rate settings") + for param, value in {("fee_rate", 100000), ("feeRate", 1)}: + assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: value, "add_inputs": True}) + assert_raises_rpc_error(-3, "Amount out of range", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: -1, "add_inputs": True}) + assert_raises_rpc_error(-3, "Amount is not a number or string", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: {"foo": "bar"}, "add_inputs": True}) + assert_raises_rpc_error(-3, "Invalid amount", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: "", "add_inputs": True}) + + self.log.info("- raises RPC error if both feeRate and fee_rate are passed") + assert_raises_rpc_error(-8, "Cannot specify both fee_rate (sat/vB) and feeRate (BTC/kvB)", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0.1, "feeRate": 0.1, "add_inputs": True}) + + self.log.info("- raises RPC error if both feeRate and estimate_mode passed") + assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and feeRate", + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": "economical", "feeRate": 0.1, "add_inputs": True}) + + for param in ["feeRate", "fee_rate"]: + self.log.info("- raises RPC error if both {} and conf_target are passed".format(param)) + assert_raises_rpc_error(-8, "Cannot specify both conf_target and {}. Please provide either a confirmation " + "target in blocks for automatic fee estimation, or an explicit fee rate.".format(param), + self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {param: 1, "conf_target": 1, "add_inputs": True}) + + self.log.info("- raises RPC error if both fee_rate and estimate_mode are passed") + assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate", + self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {"fee_rate": 1, "estimate_mode": "economical", "add_inputs": True}) self.log.info("- raises RPC error with invalid estimate_mode settings") for k, v in {"number": 42, "object": {"foo": "bar"}}.items(): assert_raises_rpc_error(-3, "Expected type string for estimate_mode, got {}".format(k), - 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/test_framework.py b/test/functional/test_framework/test_framework.py index 831599913d..bf047c5f68 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -782,6 +782,11 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): if not self.is_sqlite_compiled(): raise SkipTest("sqlite has not been compiled.") + def skip_if_no_bdb(self): + """Skip the running test if BDB has not been compiled.""" + if not self.is_bdb_compiled(): + raise SkipTest("BDB has not been compiled.") + def skip_if_no_wallet_tool(self): """Skip the running test if bitcoin-wallet has not been compiled.""" if not self.is_wallet_tool_compiled(): @@ -822,5 +827,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): return self.config["components"].getboolean("ENABLE_ZMQ") def is_sqlite_compiled(self): - """Checks whether the wallet module was compiled.""" + """Checks whether the wallet module was compiled with Sqlite support.""" return self.config["components"].getboolean("USE_SQLITE") + + def is_bdb_compiled(self): + """Checks whether the wallet module was compiled with BDB support.""" + return self.config["components"].getboolean("USE_BDB") diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 046efe730e..0a5b7f551c 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -544,7 +544,7 @@ class TestNode(): def num_test_p2p_connections(self): """Return number of test framework p2p connections to the node.""" - return len([peer for peer in self.getpeerinfo() if peer['subver'] == MY_SUBVERSION]) + return len([peer for peer in self.getpeerinfo() if peer['subver'] == MY_SUBVERSION.decode("utf-8")]) def disconnect_p2ps(self): """Close all p2p connections to the node.""" diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py index 39b3bf2a5b..a71f2c69cb 100644 --- a/test/functional/test_framework/wallet.py +++ b/test/functional/test_framework/wallet.py @@ -40,9 +40,20 @@ class MiniWallet: self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value']}) return blocks - def get_utxo(self): - """Return the last utxo. Can be used to get the change output immediately after a send_self_transfer""" - return self._utxos.pop() + def get_utxo(self, *, txid=''): + """ + Returns a utxo and marks it as spent (pops it from the internal list) + + Args: + txid (string), optional: get the first utxo we find from a specific transaction + + Note: Can be used to get the change output immediately after a send_self_transfer + """ + index = -1 # by default the last utxo + if txid: + utxo = next(filter(lambda utxo: txid == utxo['txid'], self._utxos)) + index = self._utxos.index(utxo) + return self._utxos.pop(index) def send_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node, utxo_to_spend=None): """Create and send a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed.""" diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 40daffd2c2..ac4a6e4948 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,40 @@ 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', - ) + txid = self.nodes[2].sendmany(amounts={address: 10}, 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 +296,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 +356,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 +398,42 @@ 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', - ) + txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=fee_rate_sat_vb) tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex']) - self.sync_all(self.nodes[0:3]) self.nodes[0].generate(1) self.sync_all(self.nodes[0:3]) postbalance = self.nodes[2].getbalance() - fee = prebalance - postbalance - Decimal('1') - assert_fee_amount(fee, tx_size, Decimal('0.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 +491,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..99c9737258 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,42 @@ 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", 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", 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 +151,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 +302,11 @@ def test_dust_to_fee(self, rbf_node, dest_address): # boundary. Thus expected transaction size (p2wpkh, 1 input, 2 outputs) is 140-141 vbytes, usually 141. if not 140 <= fulltx["vsize"] <= 141: raise AssertionError("Invalid tx vsize of {} (140-141 expected), full tx: {}".format(fulltx["vsize"], fulltx)) - # Bump with fee_rate of 0.00350250 BTC per 1000 vbytes to create dust. + # Bump with fee_rate of 350.25 sat/vB vbytes to create dust. # Expected fee is 141 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049385 BTC. # or occasionally 140 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049035 BTC. # Dust should be dropped to the fee, so actual bump fee is 0.00050000 BTC. - bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": 0.00350250}) + bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": 350.25}) full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1) assert_equal(bumped_tx["fee"], Decimal("0.00050000")) assert_equal(len(fulltx["vout"]), 2) @@ -436,7 +419,7 @@ def test_watchonly_psbt(self, peer_node, rbf_node, dest_address): self.sync_all() # Create single-input PSBT for transaction to be bumped - psbt = watcher.walletcreatefundedpsbt([], {dest_address: 0.0005}, 0, {"feeRate": 0.00001}, True)['psbt'] + psbt = watcher.walletcreatefundedpsbt([], {dest_address: 0.0005}, 0, {"fee_rate": 1}, True)['psbt'] psbt_signed = signer.walletprocesspsbt(psbt=psbt, sign=True, sighashtype="ALL", bip32derivs=True) psbt_final = watcher.finalizepsbt(psbt_signed["psbt"]) original_txid = watcher.sendrawtransaction(psbt_final["hex"]) diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index df16ec741f..eeaa607db7 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -355,12 +355,18 @@ class MultiWalletTest(BitcoinTestFramework): assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].unloadwallet) assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", self.nodes[0].unloadwallet, "dummy") assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", node.get_wallet_rpc("dummy").unloadwallet) - assert_raises_rpc_error(-8, "Cannot unload the requested wallet", w1.unloadwallet, "w2"), + assert_raises_rpc_error(-8, "RPC endpoint wallet and wallet_name parameter specify different wallets", w1.unloadwallet, "w2"), # Successfully unload the specified wallet name self.nodes[0].unloadwallet("w1") assert 'w1' not in self.nodes[0].listwallets() + # Unload w1 again, this time providing the wallet name twice + self.nodes[0].loadwallet("w1") + assert 'w1' in self.nodes[0].listwallets() + w1.unloadwallet("w1") + assert 'w1' not in self.nodes[0].listwallets() + # Successfully unload the wallet referenced by the request endpoint # Also ensure unload works during walletpassphrase timeout w2.encryptwallet('test') diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py index 921a726d4b..192e9065e6 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,62 @@ 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) + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=7, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00007")) - res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=2, estimate_mode="sat/b", add_to_wallet=False) + # "unset" and None are treated the same for estimate_mode + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=2, estimate_mode="unset", add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00002")) - 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) + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=4.531, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00004531")) - res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_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 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))) + # Test that passing fee_rate as both an argument and an option raises. + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=1, fee_rate=1, add_to_wallet=False, + expect_error=(-8, "Pass the fee_rate either as an argument, or in the options object, but not both")) + + assert_raises_rpc_error(-8, "Use fee_rate (sat/vB) instead of feeRate", w0.send, {w1.getnewaddress(): 1}, 6, "conservative", 1, {"feeRate": 0.01}) + + assert_raises_rpc_error(-3, "Unexpected key totalFee", w0.send, {w1.getnewaddress(): 1}, 6, "conservative", 1, {"totalFee": 0.01}) + + for target, mode in product([-1, 0, 1009], ["economical", "conservative"]): + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=target, estimate_mode=mode, + expect_error=(-8, "Invalid conf_target, must be between 1 and 1008")) # max value of 1008 per src/policy/fees.h + msg = 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"' + for target, mode in product([-1, 0], ["btc/kb", "sat/b"]): + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=target, estimate_mode=mode, expect_error=(-8, msg)) + for mode in ["", "foo", Decimal("3.141592")]: + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode=mode, expect_error=(-8, msg)) + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0.1, arg_estimate_mode=mode, expect_error=(-8, msg)) + assert_raises_rpc_error(-8, msg, w0.send, {w1.getnewaddress(): 1}, 0.1, mode) + + for mode in ["economical", "conservative", "btc/kb", "sat/b"]: + self.log.debug("{}".format(mode)) + for k, v in {"string": "true", "object": {"foo": "bar"}}.items(): + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=v, estimate_mode=mode, + expect_error=(-3, "Expected type number for conf_target, got {}".format(k))) + + # Test setting explicit fee rate just below the minimum and at zero. + self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if fee_rate of 0.99999999 is passed") + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0.99999999, + expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)")) + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=0.99999999, + expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)")) + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0, + expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)")) + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=0, + expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)")) # TODO: Return hex if fee rate is below -maxmempool # res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", add_to_wallet=False) diff --git a/test/functional/wallet_upgradewallet.py b/test/functional/wallet_upgradewallet.py index 8ab4b3f76c..d0bb6135a8 100755 --- a/test/functional/wallet_upgradewallet.py +++ b/test/functional/wallet_upgradewallet.py @@ -22,9 +22,7 @@ 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, ) @@ -92,6 +90,32 @@ class UpgradeWalletTest(BitcoinTestFramework): v16_3_node.submitblock(b) assert_equal(v16_3_node.getblockcount(), to_height) + def test_upgradewallet(self, wallet, previous_version, requested_version=None, expected_version=None): + unchanged = expected_version == previous_version + new_version = previous_version if unchanged else expected_version if expected_version else requested_version + assert_equal(wallet.getwalletinfo()["walletversion"], previous_version) + assert_equal(wallet.upgradewallet(requested_version), + { + "wallet_name": "", + "previous_version": previous_version, + "current_version": new_version, + "result": "Already at latest version. Wallet version unchanged." if unchanged else "Wallet upgraded successfully from version {} to version {}.".format(previous_version, new_version), + } + ) + assert_equal(wallet.getwalletinfo()["walletversion"], new_version) + + def test_upgradewallet_error(self, wallet, previous_version, requested_version, msg): + assert_equal(wallet.getwalletinfo()["walletversion"], previous_version) + assert_equal(wallet.upgradewallet(requested_version), + { + "wallet_name": "", + "previous_version": previous_version, + "current_version": previous_version, + "error": msg, + } + ) + assert_equal(wallet.getwalletinfo()["walletversion"], previous_version) + def run_test(self): self.nodes[0].generatetoaddress(101, self.nodes[0].getnewaddress()) self.dumb_sync_blocks() @@ -158,14 +182,8 @@ class UpgradeWalletTest(BitcoinTestFramework): 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 - # should return nothing if successful - assert_equal(wallet.upgradewallet(), {}) - new_version = wallet.getwalletinfo()["walletversion"] - # upgraded wallet version should be greater than older one - assert_greater_than(new_version, old_version) + self.log.info("Test upgradewallet without a version argument") + self.test_upgradewallet(wallet, previous_version=159900, expected_version=169900) # wallet should still contain the same balance assert_equal(wallet.getbalance(), v16_3_balance) @@ -173,32 +191,28 @@ class UpgradeWalletTest(BitcoinTestFramework): wallet = node_master.get_wallet_rpc(self.default_wallet_name) # should have no master key hash before conversion assert_equal('hdseedid' in wallet.getwalletinfo(), False) - # calling upgradewallet with explicit version number - # should return nothing if successful - assert_equal(wallet.upgradewallet(169900), {}) - new_version = wallet.getwalletinfo()["walletversion"] - # upgraded wallet should have version 169900 - assert_equal(new_version, 169900) + self.log.info("Test upgradewallet with explicit version number") + self.test_upgradewallet(wallet, previous_version=60000, requested_version=169900) # after conversion master key hash should be present assert_is_hex_string(wallet.getwalletinfo()['hdseedid']) - self.log.info('Intermediary versions don\'t effect anything') + 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']) + # Test an "upgrade" from 60000 to 129999 has no effect, as the next version is 130000 + self.test_upgradewallet(wallet, previous_version=60000, requested_version=129999, expected_version=60000) wallet.unloadwallet() assert_equal(before_checksum, sha256sum_file(node_master_wallet)) node_master.loadwallet('') self.log.info('Wallets cannot be downgraded') copy_non_hd() - assert_raises_rpc_error(-4, 'Cannot downgrade wallet', wallet.upgradewallet, 40000) + self.test_upgradewallet_error(wallet, previous_version=60000, requested_version=40000, + msg="Cannot downgrade wallet from version 60000 to version 40000. Wallet version unchanged.") wallet.unloadwallet() assert_equal(before_checksum, sha256sum_file(node_master_wallet)) node_master.loadwallet('') @@ -208,8 +222,7 @@ class UpgradeWalletTest(BitcoinTestFramework): 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']) + self.test_upgradewallet(wallet, previous_version=60000, requested_version=130000) # Check that there is now a hd chain and it is version 1, no internal chain counter new_kvs = dump_bdb_kv(node_master_wallet) assert b'\x07hdchain' in new_kvs @@ -236,16 +249,13 @@ class UpgradeWalletTest(BitcoinTestFramework): 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']) + for version in [139900, 159900, 169899]: + self.test_upgradewallet_error(wallet, previous_version=130000, requested_version=version, + msg="Cannot upgrade a non HD split wallet from version {} to version {} without upgrading to " + "support pre-split keypool. Please use version 169900 or no version specified.".format(130000, version)) self.log.info('Upgrade HD to HD chain split') - wallet.upgradewallet(169900) - assert_equal(169900, wallet.getwalletinfo()['walletversion']) + self.test_upgradewallet(wallet, previous_version=130000, requested_version=169900) # Check that the hdchain updated correctly new_kvs = dump_bdb_kv(node_master_wallet) hd_chain = new_kvs[b'\x07hdchain'] @@ -271,8 +281,7 @@ class UpgradeWalletTest(BitcoinTestFramework): self.log.info('Upgrade non-HD to HD chain split') copy_non_hd() - wallet.upgradewallet(169900) - assert_equal(169900, wallet.getwalletinfo()['walletversion']) + self.test_upgradewallet(wallet, previous_version=60000, requested_version=169900) # Check that the hdchain updated correctly new_kvs = dump_bdb_kv(node_master_wallet) hd_chain = new_kvs[b'\x07hdchain'] @@ -333,8 +342,8 @@ class UpgradeWalletTest(BitcoinTestFramework): # 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) + self.log.info("Upgrade the wallet. Should still have the same default key.") + self.test_upgradewallet(wallet, previous_version=139900, requested_version=159900) new_kvs = dump_bdb_kv(node_master_wallet) up_defaultkey = new_kvs[b'\x0adefaultkey'] assert_equal(defaultkey, up_defaultkey) @@ -342,5 +351,6 @@ class UpgradeWalletTest(BitcoinTestFramework): 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/extended-lint-cppcheck.sh b/test/lint/extended-lint-cppcheck.sh index 20021d8605..dfa49977de 100755 --- a/test/lint/extended-lint-cppcheck.sh +++ b/test/lint/extended-lint-cppcheck.sh @@ -66,7 +66,7 @@ function join_array { ENABLED_CHECKS_REGEXP=$(join_array "|" "${ENABLED_CHECKS[@]}") IGNORED_WARNINGS_REGEXP=$(join_array "|" "${IGNORED_WARNINGS[@]}") WARNINGS=$(git ls-files -- "*.cpp" "*.h" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" | \ - xargs cppcheck --enable=all -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++11 --template=gcc -D__cplusplus -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCLIENT_VERSION_REVISION -DCOPYRIGHT_YEAR -DDEBUG -I src/ -q 2>&1 | sort -u | \ + xargs cppcheck --enable=all -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++11 --template=gcc -D__cplusplus -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCOPYRIGHT_YEAR -DDEBUG -I src/ -q 2>&1 | sort -u | \ grep -E "${ENABLED_CHECKS_REGEXP}" | \ grep -vE "${IGNORED_WARNINGS_REGEXP}") if [[ ${WARNINGS} != "" ]]; then diff --git a/test/lint/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/ubsan b/test/sanitizer_suppressions/ubsan index e2f3fec851..291aab0a4a 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -6,6 +6,7 @@ # contains files in which we expect unsigned integer overflows to occur. The # list is used to suppress -fsanitize=integer warnings when running our CI UBSan # job. +unsigned-integer-overflow:*/include/c++/*/bits/basic_string.tcc unsigned-integer-overflow:arith_uint256.h unsigned-integer-overflow:basic_string.h unsigned-integer-overflow:bench/bench.h diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json index 99cd4ab695..0a9846b4be 100644 --- a/test/util/data/bitcoin-util-test.json +++ b/test/util/data/bitcoin-util-test.json @@ -221,7 +221,7 @@ { "exec": "./bitcoin-tx", "args": ["-create", "outscript=0:123badscript"], "return_code": 1, - "error_txt": "error: script parse error", + "error_txt": "error: script parse error: unknown opcode", "description": "Create a new transaction with an invalid output script" }, { "exec": "./bitcoin-tx", |